diff --git a/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff b/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff
index 4daf88e7..1cb6ab99 100644
--- a/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff
+++ b/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff
@@ -1,4 +1,4 @@
-131,156c131,157
+131,156c131,159
< #define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \
< HANDLER(GicDistributor, Empty, UINT64_C(0x50041000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
< HANDLER(GicCpuInterface, GicDistributor, UINT64_C(0x50042000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
@@ -49,7 +49,9 @@
> HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
> HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
> HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
-> HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ExternalMemoryController0, MemoryController1, UINT64_C(0x7001E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ExternalMemoryController1, ExternalMemoryController0, UINT64_C(0x7001F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(Sdmmc, ExternalMemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
> HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
> HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
> HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
diff --git a/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff b/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff
index 0817bad4..e4c4375a 100644
--- a/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff
+++ b/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff
@@ -1,9 +1,10 @@
-100a101,104
+100a101,105
> #include "secmon_define_emc_access_table.inc"
+> #include "secmon_define_emc01_access_table.inc"
> #include "secmon_define_flow_controller_access_table.inc"
> #include "secmon_define_exception_vectors_access_table.inc"
> #include "secmon_define_rtc_pmc_access_table.inc"
-104,107c108,115
+104,107c109,118
< { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
< { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
< { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
@@ -12,6 +13,8 @@
> { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
> { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
> { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
+> { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Size, },
+> { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Size, },
> { FlowControllerAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceFlowController.GetAddress(), FlowControllerAccessTable::Address, FlowControllerAccessTable::Size, },
> { ExceptionVectorsAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExceptionVectors.GetAddress(), ExceptionVectorsAccessTable::Address, ExceptionVectorsAccessTable::Size, },
> { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
diff --git a/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc b/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc
new file mode 100644
index 00000000..3a34e1dc
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define __ACCESS_TABLE_NAME__ Emc01AccessTable
+#define __ACCESS_TABLE_ADDRESS__ 0
+#define __ACCESS_TABLE_INC__ "secmon_emc01_access_table_data.inc"
+
+#include "secmon_define_access_table.inc"
+
+#undef __ACCESS_TABLE_INC__
+#undef __ACCESS_TABLE_ADDRESS__
+#undef __ACCESS_TABLE_NAME__
diff --git a/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc b/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc
new file mode 100644
index 00000000..a3718c5e
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (c) Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+SetRegisterAllowed(0x0);
+SetRegisterAllowed(0x4);
+SetRegisterAllowed(0x8);
+SetRegisterAllowed(0xC);
+SetRegisterAllowed(0x10);
+SetRegisterAllowed(0x14);
+SetRegisterAllowed(0x18);
+SetRegisterAllowed(0x1C);
+SetRegisterAllowed(0x20);
+SetRegisterAllowed(0x24);
+SetRegisterAllowed(0x28);
+SetRegisterAllowed(0x2C);
+SetRegisterAllowed(0x30);
+SetRegisterAllowed(0x34);
+SetRegisterAllowed(0x38);
+SetRegisterAllowed(0x3C);
+SetRegisterAllowed(0x40);
+SetRegisterAllowed(0x44);
+SetRegisterAllowed(0x48);
+SetRegisterAllowed(0x4C);
+SetRegisterAllowed(0x50);
+SetRegisterAllowed(0x54);
+SetRegisterAllowed(0x58);
+SetRegisterAllowed(0x5C);
+SetRegisterAllowed(0x60);
+SetRegisterAllowed(0x64);
+SetRegisterAllowed(0x68);
+SetRegisterAllowed(0x6C);
+SetRegisterAllowed(0x70);
+SetRegisterAllowed(0x74);
+SetRegisterAllowed(0x78);
+SetRegisterAllowed(0x7C);
+SetRegisterAllowed(0x80);
+SetRegisterAllowed(0x84);
+SetRegisterAllowed(0x88);
+SetRegisterAllowed(0x8C);
+SetRegisterAllowed(0x90);
+SetRegisterAllowed(0x94);
+SetRegisterAllowed(0x98);
+SetRegisterAllowed(0x9C);
+SetRegisterAllowed(0xA0);
+SetRegisterAllowed(0xA4);
+SetRegisterAllowed(0xA8);
+SetRegisterAllowed(0xAC);
+SetRegisterAllowed(0xB0);
+SetRegisterAllowed(0xB4);
+SetRegisterAllowed(0xB8);
+SetRegisterAllowed(0xBC);
+SetRegisterAllowed(0xC0);
+SetRegisterAllowed(0xC4);
+SetRegisterAllowed(0xC8);
+SetRegisterAllowed(0xCC);
+SetRegisterAllowed(0xD0);
+SetRegisterAllowed(0xD4);
+SetRegisterAllowed(0xD8);
+SetRegisterAllowed(0xDC);
+SetRegisterAllowed(0xE0);
+SetRegisterAllowed(0xE4);
+SetRegisterAllowed(0xE8);
+SetRegisterAllowed(0xEC);
+SetRegisterAllowed(0xF0);
+SetRegisterAllowed(0xF4);
+SetRegisterAllowed(0xF8);
+SetRegisterAllowed(0xFC);
+SetRegisterAllowed(0x100);
+SetRegisterAllowed(0x104);
+SetRegisterAllowed(0x108);
+SetRegisterAllowed(0x10C);
+SetRegisterAllowed(0x110);
+SetRegisterAllowed(0x114);
+SetRegisterAllowed(0x118);
+SetRegisterAllowed(0x11C);
+SetRegisterAllowed(0x120);
+SetRegisterAllowed(0x124);
+SetRegisterAllowed(0x128);
+SetRegisterAllowed(0x12C);
+SetRegisterAllowed(0x130);
+SetRegisterAllowed(0x134);
+SetRegisterAllowed(0x138);
+SetRegisterAllowed(0x13C);
+SetRegisterAllowed(0x140);
+SetRegisterAllowed(0x144);
+SetRegisterAllowed(0x148);
+SetRegisterAllowed(0x14C);
+SetRegisterAllowed(0x150);
+SetRegisterAllowed(0x154);
+SetRegisterAllowed(0x158);
+SetRegisterAllowed(0x15C);
+SetRegisterAllowed(0x160);
+SetRegisterAllowed(0x164);
+SetRegisterAllowed(0x168);
+SetRegisterAllowed(0x16C);
+SetRegisterAllowed(0x170);
+SetRegisterAllowed(0x174);
+SetRegisterAllowed(0x178);
+SetRegisterAllowed(0x17C);
+SetRegisterAllowed(0x180);
+SetRegisterAllowed(0x184);
+SetRegisterAllowed(0x188);
+SetRegisterAllowed(0x18C);
+SetRegisterAllowed(0x190);
+SetRegisterAllowed(0x194);
+SetRegisterAllowed(0x198);
+SetRegisterAllowed(0x19C);
+SetRegisterAllowed(0x1A0);
+SetRegisterAllowed(0x1A4);
+SetRegisterAllowed(0x1A8);
+SetRegisterAllowed(0x1AC);
+SetRegisterAllowed(0x1B0);
+SetRegisterAllowed(0x1B4);
+SetRegisterAllowed(0x1B8);
+SetRegisterAllowed(0x1BC);
+SetRegisterAllowed(0x1C0);
+SetRegisterAllowed(0x1C4);
+SetRegisterAllowed(0x1C8);
+SetRegisterAllowed(0x1CC);
+SetRegisterAllowed(0x1D0);
+SetRegisterAllowed(0x1D4);
+SetRegisterAllowed(0x1D8);
+SetRegisterAllowed(0x1DC);
+SetRegisterAllowed(0x1E0);
+SetRegisterAllowed(0x1E4);
+SetRegisterAllowed(0x1E8);
+SetRegisterAllowed(0x1EC);
+SetRegisterAllowed(0x1F0);
+SetRegisterAllowed(0x1F4);
+SetRegisterAllowed(0x1F8);
+SetRegisterAllowed(0x1FC);
+SetRegisterAllowed(0x200);
+SetRegisterAllowed(0x204);
+SetRegisterAllowed(0x208);
+SetRegisterAllowed(0x20C);
+SetRegisterAllowed(0x210);
+SetRegisterAllowed(0x214);
+SetRegisterAllowed(0x218);
+SetRegisterAllowed(0x21C);
+SetRegisterAllowed(0x220);
+SetRegisterAllowed(0x224);
+SetRegisterAllowed(0x228);
+SetRegisterAllowed(0x22C);
+SetRegisterAllowed(0x230);
+SetRegisterAllowed(0x234);
+SetRegisterAllowed(0x238);
+SetRegisterAllowed(0x23C);
+SetRegisterAllowed(0x240);
+SetRegisterAllowed(0x244);
+SetRegisterAllowed(0x248);
+SetRegisterAllowed(0x24C);
+SetRegisterAllowed(0x250);
+SetRegisterAllowed(0x254);
+SetRegisterAllowed(0x258);
+SetRegisterAllowed(0x25C);
+SetRegisterAllowed(0x260);
+SetRegisterAllowed(0x264);
+SetRegisterAllowed(0x268);
+SetRegisterAllowed(0x26C);
+SetRegisterAllowed(0x270);
+SetRegisterAllowed(0x274);
+SetRegisterAllowed(0x278);
+SetRegisterAllowed(0x27C);
+SetRegisterAllowed(0x280);
+SetRegisterAllowed(0x284);
+SetRegisterAllowed(0x288);
+SetRegisterAllowed(0x28C);
+SetRegisterAllowed(0x290);
+SetRegisterAllowed(0x294);
+SetRegisterAllowed(0x298);
+SetRegisterAllowed(0x29C);
+SetRegisterAllowed(0x2A0);
+SetRegisterAllowed(0x2A4);
+SetRegisterAllowed(0x2A8);
+SetRegisterAllowed(0x2AC);
+SetRegisterAllowed(0x2B0);
+SetRegisterAllowed(0x2B4);
+SetRegisterAllowed(0x2B8);
+SetRegisterAllowed(0x2BC);
+SetRegisterAllowed(0x2C0);
+SetRegisterAllowed(0x2C4);
+SetRegisterAllowed(0x2C8);
+SetRegisterAllowed(0x2CC);
+SetRegisterAllowed(0x2D0);
+SetRegisterAllowed(0x2D4);
+SetRegisterAllowed(0x2D8);
+SetRegisterAllowed(0x2DC);
+SetRegisterAllowed(0x2E0);
+SetRegisterAllowed(0x2E4);
+SetRegisterAllowed(0x2E8);
+SetRegisterAllowed(0x2EC);
+SetRegisterAllowed(0x2F0);
+SetRegisterAllowed(0x2F4);
+SetRegisterAllowed(0x2F8);
+SetRegisterAllowed(0x2FC);
+SetRegisterAllowed(0x300);
+SetRegisterAllowed(0x304);
+SetRegisterAllowed(0x308);
+SetRegisterAllowed(0x30C);
+SetRegisterAllowed(0x310);
+SetRegisterAllowed(0x314);
+SetRegisterAllowed(0x318);
+SetRegisterAllowed(0x31C);
+SetRegisterAllowed(0x320);
+SetRegisterAllowed(0x324);
+SetRegisterAllowed(0x328);
+SetRegisterAllowed(0x32C);
+SetRegisterAllowed(0x330);
+SetRegisterAllowed(0x334);
+SetRegisterAllowed(0x338);
+SetRegisterAllowed(0x33C);
+SetRegisterAllowed(0x340);
+SetRegisterAllowed(0x344);
+SetRegisterAllowed(0x348);
+SetRegisterAllowed(0x34C);
+SetRegisterAllowed(0x350);
+SetRegisterAllowed(0x354);
+SetRegisterAllowed(0x358);
+SetRegisterAllowed(0x35C);
+SetRegisterAllowed(0x360);
+SetRegisterAllowed(0x364);
+SetRegisterAllowed(0x368);
+SetRegisterAllowed(0x36C);
+SetRegisterAllowed(0x370);
+SetRegisterAllowed(0x374);
+SetRegisterAllowed(0x378);
+SetRegisterAllowed(0x37C);
+SetRegisterAllowed(0x380);
+SetRegisterAllowed(0x384);
+SetRegisterAllowed(0x388);
+SetRegisterAllowed(0x38C);
+SetRegisterAllowed(0x390);
+SetRegisterAllowed(0x394);
+SetRegisterAllowed(0x398);
+SetRegisterAllowed(0x39C);
+SetRegisterAllowed(0x3A0);
+SetRegisterAllowed(0x3A4);
+SetRegisterAllowed(0x3A8);
+SetRegisterAllowed(0x3AC);
+SetRegisterAllowed(0x3B0);
+SetRegisterAllowed(0x3B4);
+SetRegisterAllowed(0x3B8);
+SetRegisterAllowed(0x3BC);
+SetRegisterAllowed(0x3C0);
+SetRegisterAllowed(0x3C4);
+SetRegisterAllowed(0x3C8);
+SetRegisterAllowed(0x3CC);
+SetRegisterAllowed(0x3D0);
+SetRegisterAllowed(0x3D4);
+SetRegisterAllowed(0x3D8);
+SetRegisterAllowed(0x3DC);
+SetRegisterAllowed(0x3E0);
+SetRegisterAllowed(0x3E4);
+SetRegisterAllowed(0x3E8);
+SetRegisterAllowed(0x3EC);
+SetRegisterAllowed(0x3F0);
+SetRegisterAllowed(0x3F4);
+SetRegisterAllowed(0x3F8);
+SetRegisterAllowed(0x3FC);
+SetRegisterAllowed(0x400);
+SetRegisterAllowed(0x404);
+SetRegisterAllowed(0x408);
+SetRegisterAllowed(0x40C);
+SetRegisterAllowed(0x410);
+SetRegisterAllowed(0x414);
+SetRegisterAllowed(0x418);
+SetRegisterAllowed(0x41C);
+SetRegisterAllowed(0x420);
+SetRegisterAllowed(0x424);
+SetRegisterAllowed(0x428);
+SetRegisterAllowed(0x42C);
+SetRegisterAllowed(0x430);
+SetRegisterAllowed(0x434);
+SetRegisterAllowed(0x438);
+SetRegisterAllowed(0x43C);
+SetRegisterAllowed(0x440);
+SetRegisterAllowed(0x444);
+SetRegisterAllowed(0x448);
+SetRegisterAllowed(0x44C);
+SetRegisterAllowed(0x450);
+SetRegisterAllowed(0x454);
+SetRegisterAllowed(0x458);
+SetRegisterAllowed(0x45C);
+SetRegisterAllowed(0x460);
+SetRegisterAllowed(0x464);
+SetRegisterAllowed(0x468);
+SetRegisterAllowed(0x46C);
+SetRegisterAllowed(0x470);
+SetRegisterAllowed(0x474);
+SetRegisterAllowed(0x478);
+SetRegisterAllowed(0x47C);
+SetRegisterAllowed(0x480);
+SetRegisterAllowed(0x484);
+SetRegisterAllowed(0x488);
+SetRegisterAllowed(0x48C);
+SetRegisterAllowed(0x490);
+SetRegisterAllowed(0x494);
+SetRegisterAllowed(0x498);
+SetRegisterAllowed(0x49C);
+SetRegisterAllowed(0x4A0);
+SetRegisterAllowed(0x4A4);
+SetRegisterAllowed(0x4A8);
+SetRegisterAllowed(0x4AC);
+SetRegisterAllowed(0x4B0);
+SetRegisterAllowed(0x4B4);
+SetRegisterAllowed(0x4B8);
+SetRegisterAllowed(0x4BC);
+SetRegisterAllowed(0x4C0);
+SetRegisterAllowed(0x4C4);
+SetRegisterAllowed(0x4C8);
+SetRegisterAllowed(0x4CC);
+SetRegisterAllowed(0x4D0);
+SetRegisterAllowed(0x4D4);
+SetRegisterAllowed(0x4D8);
+SetRegisterAllowed(0x4DC);
+SetRegisterAllowed(0x4E0);
+SetRegisterAllowed(0x4E4);
+SetRegisterAllowed(0x4E8);
+SetRegisterAllowed(0x4EC);
+SetRegisterAllowed(0x4F0);
+SetRegisterAllowed(0x4F4);
+SetRegisterAllowed(0x4F8);
+SetRegisterAllowed(0x4FC);
+SetRegisterAllowed(0x500);
+SetRegisterAllowed(0x504);
+SetRegisterAllowed(0x508);
+SetRegisterAllowed(0x50C);
+SetRegisterAllowed(0x510);
+SetRegisterAllowed(0x514);
+SetRegisterAllowed(0x518);
+SetRegisterAllowed(0x51C);
+SetRegisterAllowed(0x520);
+SetRegisterAllowed(0x524);
+SetRegisterAllowed(0x528);
+SetRegisterAllowed(0x52C);
+SetRegisterAllowed(0x530);
+SetRegisterAllowed(0x534);
+SetRegisterAllowed(0x538);
+SetRegisterAllowed(0x53C);
+SetRegisterAllowed(0x540);
+SetRegisterAllowed(0x544);
+SetRegisterAllowed(0x548);
+SetRegisterAllowed(0x54C);
+SetRegisterAllowed(0x550);
+SetRegisterAllowed(0x554);
+SetRegisterAllowed(0x558);
+SetRegisterAllowed(0x55C);
+SetRegisterAllowed(0x560);
+SetRegisterAllowed(0x564);
+SetRegisterAllowed(0x568);
+SetRegisterAllowed(0x56C);
+SetRegisterAllowed(0x570);
+SetRegisterAllowed(0x574);
+SetRegisterAllowed(0x578);
+SetRegisterAllowed(0x57C);
+SetRegisterAllowed(0x580);
+SetRegisterAllowed(0x584);
+SetRegisterAllowed(0x588);
+SetRegisterAllowed(0x58C);
+SetRegisterAllowed(0x590);
+SetRegisterAllowed(0x594);
+SetRegisterAllowed(0x598);
+SetRegisterAllowed(0x59C);
+SetRegisterAllowed(0x5A0);
+SetRegisterAllowed(0x5A4);
+SetRegisterAllowed(0x5A8);
+SetRegisterAllowed(0x5AC);
+SetRegisterAllowed(0x5B0);
+SetRegisterAllowed(0x5B4);
+SetRegisterAllowed(0x5B8);
+SetRegisterAllowed(0x5BC);
+SetRegisterAllowed(0x5C0);
+SetRegisterAllowed(0x5C4);
+SetRegisterAllowed(0x5C8);
+SetRegisterAllowed(0x5CC);
+SetRegisterAllowed(0x5D0);
+SetRegisterAllowed(0x5D4);
+SetRegisterAllowed(0x5D8);
+SetRegisterAllowed(0x5DC);
+SetRegisterAllowed(0x5E0);
+SetRegisterAllowed(0x5E4);
+SetRegisterAllowed(0x5E8);
+SetRegisterAllowed(0x5EC);
+SetRegisterAllowed(0x5F0);
+SetRegisterAllowed(0x5F4);
+SetRegisterAllowed(0x5F8);
+SetRegisterAllowed(0x5FC);
+SetRegisterAllowed(0x600);
+SetRegisterAllowed(0x604);
+SetRegisterAllowed(0x608);
+SetRegisterAllowed(0x60C);
+SetRegisterAllowed(0x610);
+SetRegisterAllowed(0x614);
+SetRegisterAllowed(0x618);
+SetRegisterAllowed(0x61C);
+SetRegisterAllowed(0x620);
+SetRegisterAllowed(0x624);
+SetRegisterAllowed(0x628);
+SetRegisterAllowed(0x62C);
+SetRegisterAllowed(0x630);
+SetRegisterAllowed(0x634);
+SetRegisterAllowed(0x638);
+SetRegisterAllowed(0x63C);
+SetRegisterAllowed(0x640);
+SetRegisterAllowed(0x644);
+SetRegisterAllowed(0x648);
+SetRegisterAllowed(0x64C);
+SetRegisterAllowed(0x650);
+SetRegisterAllowed(0x654);
+SetRegisterAllowed(0x658);
+SetRegisterAllowed(0x65C);
+SetRegisterAllowed(0x660);
+SetRegisterAllowed(0x664);
+SetRegisterAllowed(0x668);
+SetRegisterAllowed(0x66C);
+SetRegisterAllowed(0x670);
+SetRegisterAllowed(0x674);
+SetRegisterAllowed(0x678);
+SetRegisterAllowed(0x67C);
+SetRegisterAllowed(0x680);
+SetRegisterAllowed(0x684);
+SetRegisterAllowed(0x688);
+SetRegisterAllowed(0x68C);
+SetRegisterAllowed(0x690);
+SetRegisterAllowed(0x694);
+SetRegisterAllowed(0x698);
+SetRegisterAllowed(0x69C);
+SetRegisterAllowed(0x6A0);
+SetRegisterAllowed(0x6A4);
+SetRegisterAllowed(0x6A8);
+SetRegisterAllowed(0x6AC);
+SetRegisterAllowed(0x6B0);
+SetRegisterAllowed(0x6B4);
+SetRegisterAllowed(0x6B8);
+SetRegisterAllowed(0x6BC);
+SetRegisterAllowed(0x6C0);
+SetRegisterAllowed(0x6C4);
+SetRegisterAllowed(0x6C8);
+SetRegisterAllowed(0x6CC);
+SetRegisterAllowed(0x6D0);
+SetRegisterAllowed(0x6D4);
+SetRegisterAllowed(0x6D8);
+SetRegisterAllowed(0x6DC);
+SetRegisterAllowed(0x6E0);
+SetRegisterAllowed(0x6E4);
+SetRegisterAllowed(0x6E8);
+SetRegisterAllowed(0x6EC);
+SetRegisterAllowed(0x6F0);
+SetRegisterAllowed(0x6F4);
+SetRegisterAllowed(0x6F8);
+SetRegisterAllowed(0x6FC);
+SetRegisterAllowed(0x700);
+SetRegisterAllowed(0x704);
+SetRegisterAllowed(0x708);
+SetRegisterAllowed(0x70C);
+SetRegisterAllowed(0x710);
+SetRegisterAllowed(0x714);
+SetRegisterAllowed(0x718);
+SetRegisterAllowed(0x71C);
+SetRegisterAllowed(0x720);
+SetRegisterAllowed(0x724);
+SetRegisterAllowed(0x728);
+SetRegisterAllowed(0x72C);
+SetRegisterAllowed(0x730);
+SetRegisterAllowed(0x734);
+SetRegisterAllowed(0x738);
+SetRegisterAllowed(0x73C);
+SetRegisterAllowed(0x740);
+SetRegisterAllowed(0x744);
+SetRegisterAllowed(0x748);
+SetRegisterAllowed(0x74C);
+SetRegisterAllowed(0x750);
+SetRegisterAllowed(0x754);
+SetRegisterAllowed(0x758);
+SetRegisterAllowed(0x75C);
+SetRegisterAllowed(0x760);
+SetRegisterAllowed(0x764);
+SetRegisterAllowed(0x768);
+SetRegisterAllowed(0x76C);
+SetRegisterAllowed(0x770);
+SetRegisterAllowed(0x774);
+SetRegisterAllowed(0x778);
+SetRegisterAllowed(0x77C);
+SetRegisterAllowed(0x780);
+SetRegisterAllowed(0x784);
+SetRegisterAllowed(0x788);
+SetRegisterAllowed(0x78C);
+SetRegisterAllowed(0x790);
+SetRegisterAllowed(0x794);
+SetRegisterAllowed(0x798);
+SetRegisterAllowed(0x79C);
+SetRegisterAllowed(0x7A0);
+SetRegisterAllowed(0x7A4);
+SetRegisterAllowed(0x7A8);
+SetRegisterAllowed(0x7AC);
+SetRegisterAllowed(0x7B0);
+SetRegisterAllowed(0x7B4);
+SetRegisterAllowed(0x7B8);
+SetRegisterAllowed(0x7BC);
+SetRegisterAllowed(0x7C0);
+SetRegisterAllowed(0x7C4);
+SetRegisterAllowed(0x7C8);
+SetRegisterAllowed(0x7CC);
+SetRegisterAllowed(0x7D0);
+SetRegisterAllowed(0x7D4);
+SetRegisterAllowed(0x7D8);
+SetRegisterAllowed(0x7DC);
+SetRegisterAllowed(0x7E0);
+SetRegisterAllowed(0x7E4);
+SetRegisterAllowed(0x7E8);
+SetRegisterAllowed(0x7EC);
+SetRegisterAllowed(0x7F0);
+SetRegisterAllowed(0x7F4);
+SetRegisterAllowed(0x7F8);
+SetRegisterAllowed(0x7FC);
+SetRegisterAllowed(0x800);
+SetRegisterAllowed(0x804);
+SetRegisterAllowed(0x808);
+SetRegisterAllowed(0x80C);
+SetRegisterAllowed(0x810);
+SetRegisterAllowed(0x814);
+SetRegisterAllowed(0x818);
+SetRegisterAllowed(0x81C);
+SetRegisterAllowed(0x820);
+SetRegisterAllowed(0x824);
+SetRegisterAllowed(0x828);
+SetRegisterAllowed(0x82C);
+SetRegisterAllowed(0x830);
+SetRegisterAllowed(0x834);
+SetRegisterAllowed(0x838);
+SetRegisterAllowed(0x83C);
+SetRegisterAllowed(0x840);
+SetRegisterAllowed(0x844);
+SetRegisterAllowed(0x848);
+SetRegisterAllowed(0x84C);
+SetRegisterAllowed(0x850);
+SetRegisterAllowed(0x854);
+SetRegisterAllowed(0x858);
+SetRegisterAllowed(0x85C);
+SetRegisterAllowed(0x860);
+SetRegisterAllowed(0x864);
+SetRegisterAllowed(0x868);
+SetRegisterAllowed(0x86C);
+SetRegisterAllowed(0x870);
+SetRegisterAllowed(0x874);
+SetRegisterAllowed(0x878);
+SetRegisterAllowed(0x87C);
+SetRegisterAllowed(0x880);
+SetRegisterAllowed(0x884);
+SetRegisterAllowed(0x888);
+SetRegisterAllowed(0x88C);
+SetRegisterAllowed(0x890);
+SetRegisterAllowed(0x894);
+SetRegisterAllowed(0x898);
+SetRegisterAllowed(0x89C);
+SetRegisterAllowed(0x8A0);
+SetRegisterAllowed(0x8A4);
+SetRegisterAllowed(0x8A8);
+SetRegisterAllowed(0x8AC);
+SetRegisterAllowed(0x8B0);
+SetRegisterAllowed(0x8B4);
+SetRegisterAllowed(0x8B8);
+SetRegisterAllowed(0x8BC);
+SetRegisterAllowed(0x8C0);
+SetRegisterAllowed(0x8C4);
+SetRegisterAllowed(0x8C8);
+SetRegisterAllowed(0x8CC);
+SetRegisterAllowed(0x8D0);
+SetRegisterAllowed(0x8D4);
+SetRegisterAllowed(0x8D8);
+SetRegisterAllowed(0x8DC);
+SetRegisterAllowed(0x8E0);
+SetRegisterAllowed(0x8E4);
+SetRegisterAllowed(0x8E8);
+SetRegisterAllowed(0x8EC);
+SetRegisterAllowed(0x8F0);
+SetRegisterAllowed(0x8F4);
+SetRegisterAllowed(0x8F8);
+SetRegisterAllowed(0x8FC);
+SetRegisterAllowed(0x900);
+SetRegisterAllowed(0x904);
+SetRegisterAllowed(0x908);
+SetRegisterAllowed(0x90C);
+SetRegisterAllowed(0x910);
+SetRegisterAllowed(0x914);
+SetRegisterAllowed(0x918);
+SetRegisterAllowed(0x91C);
+SetRegisterAllowed(0x920);
+SetRegisterAllowed(0x924);
+SetRegisterAllowed(0x928);
+SetRegisterAllowed(0x92C);
+SetRegisterAllowed(0x930);
+SetRegisterAllowed(0x934);
+SetRegisterAllowed(0x938);
+SetRegisterAllowed(0x93C);
+SetRegisterAllowed(0x940);
+SetRegisterAllowed(0x944);
+SetRegisterAllowed(0x948);
+SetRegisterAllowed(0x94C);
+SetRegisterAllowed(0x950);
+SetRegisterAllowed(0x954);
+SetRegisterAllowed(0x958);
+SetRegisterAllowed(0x95C);
+SetRegisterAllowed(0x960);
+SetRegisterAllowed(0x964);
+SetRegisterAllowed(0x968);
+SetRegisterAllowed(0x96C);
+SetRegisterAllowed(0x970);
+SetRegisterAllowed(0x974);
+SetRegisterAllowed(0x978);
+SetRegisterAllowed(0x97C);
+SetRegisterAllowed(0x980);
+SetRegisterAllowed(0x984);
+SetRegisterAllowed(0x988);
+SetRegisterAllowed(0x98C);
+SetRegisterAllowed(0x990);
+SetRegisterAllowed(0x994);
+SetRegisterAllowed(0x998);
+SetRegisterAllowed(0x99C);
+SetRegisterAllowed(0x9A0);
+SetRegisterAllowed(0x9A4);
+SetRegisterAllowed(0x9A8);
+SetRegisterAllowed(0x9AC);
+SetRegisterAllowed(0x9B0);
+SetRegisterAllowed(0x9B4);
+SetRegisterAllowed(0x9B8);
+SetRegisterAllowed(0x9BC);
+SetRegisterAllowed(0x9C0);
+SetRegisterAllowed(0x9C4);
+SetRegisterAllowed(0x9C8);
+SetRegisterAllowed(0x9CC);
+SetRegisterAllowed(0x9D0);
+SetRegisterAllowed(0x9D4);
+SetRegisterAllowed(0x9D8);
+SetRegisterAllowed(0x9DC);
+SetRegisterAllowed(0x9E0);
+SetRegisterAllowed(0x9E4);
+SetRegisterAllowed(0x9E8);
+SetRegisterAllowed(0x9EC);
+SetRegisterAllowed(0x9F0);
+SetRegisterAllowed(0x9F4);
+SetRegisterAllowed(0x9F8);
+SetRegisterAllowed(0x9FC);
+SetRegisterAllowed(0xA00);
+SetRegisterAllowed(0xA04);
+SetRegisterAllowed(0xA08);
+SetRegisterAllowed(0xA0C);
+SetRegisterAllowed(0xA10);
+SetRegisterAllowed(0xA14);
+SetRegisterAllowed(0xA18);
+SetRegisterAllowed(0xA1C);
+SetRegisterAllowed(0xA20);
+SetRegisterAllowed(0xA24);
+SetRegisterAllowed(0xA28);
+SetRegisterAllowed(0xA2C);
+SetRegisterAllowed(0xA30);
+SetRegisterAllowed(0xA34);
+SetRegisterAllowed(0xA38);
+SetRegisterAllowed(0xA3C);
+SetRegisterAllowed(0xA40);
+SetRegisterAllowed(0xA44);
+SetRegisterAllowed(0xA48);
+SetRegisterAllowed(0xA4C);
+SetRegisterAllowed(0xA50);
+SetRegisterAllowed(0xA54);
+SetRegisterAllowed(0xA58);
+SetRegisterAllowed(0xA5C);
+SetRegisterAllowed(0xA60);
+SetRegisterAllowed(0xA64);
+SetRegisterAllowed(0xA68);
+SetRegisterAllowed(0xA6C);
+SetRegisterAllowed(0xA70);
+SetRegisterAllowed(0xA74);
+SetRegisterAllowed(0xA78);
+SetRegisterAllowed(0xA7C);
+SetRegisterAllowed(0xA80);
+SetRegisterAllowed(0xA84);
+SetRegisterAllowed(0xA88);
+SetRegisterAllowed(0xA8C);
+SetRegisterAllowed(0xA90);
+SetRegisterAllowed(0xA94);
+SetRegisterAllowed(0xA98);
+SetRegisterAllowed(0xA9C);
+SetRegisterAllowed(0xAA0);
+SetRegisterAllowed(0xAA4);
+SetRegisterAllowed(0xAA8);
+SetRegisterAllowed(0xAAC);
+SetRegisterAllowed(0xAB0);
+SetRegisterAllowed(0xAB4);
+SetRegisterAllowed(0xAB8);
+SetRegisterAllowed(0xABC);
+SetRegisterAllowed(0xAC0);
+SetRegisterAllowed(0xAC4);
+SetRegisterAllowed(0xAC8);
+SetRegisterAllowed(0xACC);
+SetRegisterAllowed(0xAD0);
+SetRegisterAllowed(0xAD4);
+SetRegisterAllowed(0xAD8);
+SetRegisterAllowed(0xADC);
+SetRegisterAllowed(0xAE0);
+SetRegisterAllowed(0xAE4);
+SetRegisterAllowed(0xAE8);
+SetRegisterAllowed(0xAEC);
+SetRegisterAllowed(0xAF0);
+SetRegisterAllowed(0xAF4);
+SetRegisterAllowed(0xAF8);
+SetRegisterAllowed(0xAFC);
+SetRegisterAllowed(0xB00);
+SetRegisterAllowed(0xB04);
+SetRegisterAllowed(0xB08);
+SetRegisterAllowed(0xB0C);
+SetRegisterAllowed(0xB10);
+SetRegisterAllowed(0xB14);
+SetRegisterAllowed(0xB18);
+SetRegisterAllowed(0xB1C);
+SetRegisterAllowed(0xB20);
+SetRegisterAllowed(0xB24);
+SetRegisterAllowed(0xB28);
+SetRegisterAllowed(0xB2C);
+SetRegisterAllowed(0xB30);
+SetRegisterAllowed(0xB34);
+SetRegisterAllowed(0xB38);
+SetRegisterAllowed(0xB3C);
+SetRegisterAllowed(0xB40);
+SetRegisterAllowed(0xB44);
+SetRegisterAllowed(0xB48);
+SetRegisterAllowed(0xB4C);
+SetRegisterAllowed(0xB50);
+SetRegisterAllowed(0xB54);
+SetRegisterAllowed(0xB58);
+SetRegisterAllowed(0xB5C);
+SetRegisterAllowed(0xB60);
+SetRegisterAllowed(0xB64);
+SetRegisterAllowed(0xB68);
+SetRegisterAllowed(0xB6C);
+SetRegisterAllowed(0xB70);
+SetRegisterAllowed(0xB74);
+SetRegisterAllowed(0xB78);
+SetRegisterAllowed(0xB7C);
+SetRegisterAllowed(0xB80);
+SetRegisterAllowed(0xB84);
+SetRegisterAllowed(0xB88);
+SetRegisterAllowed(0xB8C);
+SetRegisterAllowed(0xB90);
+SetRegisterAllowed(0xB94);
+SetRegisterAllowed(0xB98);
+SetRegisterAllowed(0xB9C);
+SetRegisterAllowed(0xBA0);
+SetRegisterAllowed(0xBA4);
+SetRegisterAllowed(0xBA8);
+SetRegisterAllowed(0xBAC);
+SetRegisterAllowed(0xBB0);
+SetRegisterAllowed(0xBB4);
+SetRegisterAllowed(0xBB8);
+SetRegisterAllowed(0xBBC);
+SetRegisterAllowed(0xBC0);
+SetRegisterAllowed(0xBC4);
+SetRegisterAllowed(0xBC8);
+SetRegisterAllowed(0xBCC);
+SetRegisterAllowed(0xBD0);
+SetRegisterAllowed(0xBD4);
+SetRegisterAllowed(0xBD8);
+SetRegisterAllowed(0xBDC);
+SetRegisterAllowed(0xBE0);
+SetRegisterAllowed(0xBE4);
+SetRegisterAllowed(0xBE8);
+SetRegisterAllowed(0xBEC);
+SetRegisterAllowed(0xBF0);
+SetRegisterAllowed(0xBF4);
+SetRegisterAllowed(0xBF8);
+SetRegisterAllowed(0xBFC);
+SetRegisterAllowed(0xC00);
+SetRegisterAllowed(0xC04);
+SetRegisterAllowed(0xC08);
+SetRegisterAllowed(0xC0C);
+SetRegisterAllowed(0xC10);
+SetRegisterAllowed(0xC14);
+SetRegisterAllowed(0xC18);
+SetRegisterAllowed(0xC1C);
+SetRegisterAllowed(0xC20);
+SetRegisterAllowed(0xC24);
+SetRegisterAllowed(0xC28);
+SetRegisterAllowed(0xC2C);
+SetRegisterAllowed(0xC30);
+SetRegisterAllowed(0xC34);
+SetRegisterAllowed(0xC38);
+SetRegisterAllowed(0xC3C);
+SetRegisterAllowed(0xC40);
+SetRegisterAllowed(0xC44);
+SetRegisterAllowed(0xC48);
+SetRegisterAllowed(0xC4C);
+SetRegisterAllowed(0xC50);
+SetRegisterAllowed(0xC54);
+SetRegisterAllowed(0xC58);
+SetRegisterAllowed(0xC5C);
+SetRegisterAllowed(0xC60);
+SetRegisterAllowed(0xC64);
+SetRegisterAllowed(0xC68);
+SetRegisterAllowed(0xC6C);
+SetRegisterAllowed(0xC70);
+SetRegisterAllowed(0xC74);
+SetRegisterAllowed(0xC78);
+SetRegisterAllowed(0xC7C);
+SetRegisterAllowed(0xC80);
+SetRegisterAllowed(0xC84);
+SetRegisterAllowed(0xC88);
+SetRegisterAllowed(0xC8C);
+SetRegisterAllowed(0xC90);
+SetRegisterAllowed(0xC94);
+SetRegisterAllowed(0xC98);
+SetRegisterAllowed(0xC9C);
+SetRegisterAllowed(0xCA0);
+SetRegisterAllowed(0xCA4);
+SetRegisterAllowed(0xCA8);
+SetRegisterAllowed(0xCAC);
+SetRegisterAllowed(0xCB0);
+SetRegisterAllowed(0xCB4);
+SetRegisterAllowed(0xCB8);
+SetRegisterAllowed(0xCBC);
+SetRegisterAllowed(0xCC0);
+SetRegisterAllowed(0xCC4);
+SetRegisterAllowed(0xCC8);
+SetRegisterAllowed(0xCCC);
+SetRegisterAllowed(0xCD0);
+SetRegisterAllowed(0xCD4);
+SetRegisterAllowed(0xCD8);
+SetRegisterAllowed(0xCDC);
+SetRegisterAllowed(0xCE0);
+SetRegisterAllowed(0xCE4);
+SetRegisterAllowed(0xCE8);
+SetRegisterAllowed(0xCEC);
+SetRegisterAllowed(0xCF0);
+SetRegisterAllowed(0xCF4);
+SetRegisterAllowed(0xCF8);
+SetRegisterAllowed(0xCFC);
+SetRegisterAllowed(0xD00);
+SetRegisterAllowed(0xD04);
+SetRegisterAllowed(0xD08);
+SetRegisterAllowed(0xD0C);
+SetRegisterAllowed(0xD10);
+SetRegisterAllowed(0xD14);
+SetRegisterAllowed(0xD18);
+SetRegisterAllowed(0xD1C);
+SetRegisterAllowed(0xD20);
+SetRegisterAllowed(0xD24);
+SetRegisterAllowed(0xD28);
+SetRegisterAllowed(0xD2C);
+SetRegisterAllowed(0xD30);
+SetRegisterAllowed(0xD34);
+SetRegisterAllowed(0xD38);
+SetRegisterAllowed(0xD3C);
+SetRegisterAllowed(0xD40);
+SetRegisterAllowed(0xD44);
+SetRegisterAllowed(0xD48);
+SetRegisterAllowed(0xD4C);
+SetRegisterAllowed(0xD50);
+SetRegisterAllowed(0xD54);
+SetRegisterAllowed(0xD58);
+SetRegisterAllowed(0xD5C);
+SetRegisterAllowed(0xD60);
+SetRegisterAllowed(0xD64);
+SetRegisterAllowed(0xD68);
+SetRegisterAllowed(0xD6C);
+SetRegisterAllowed(0xD70);
+SetRegisterAllowed(0xD74);
+SetRegisterAllowed(0xD78);
+SetRegisterAllowed(0xD7C);
+SetRegisterAllowed(0xD80);
+SetRegisterAllowed(0xD84);
+SetRegisterAllowed(0xD88);
+SetRegisterAllowed(0xD8C);
+SetRegisterAllowed(0xD90);
+SetRegisterAllowed(0xD94);
+SetRegisterAllowed(0xD98);
+SetRegisterAllowed(0xD9C);
+SetRegisterAllowed(0xDA0);
+SetRegisterAllowed(0xDA4);
+SetRegisterAllowed(0xDA8);
+SetRegisterAllowed(0xDAC);
+SetRegisterAllowed(0xDB0);
+SetRegisterAllowed(0xDB4);
+SetRegisterAllowed(0xDB8);
+SetRegisterAllowed(0xDBC);
+SetRegisterAllowed(0xDC0);
+SetRegisterAllowed(0xDC4);
+SetRegisterAllowed(0xDC8);
+SetRegisterAllowed(0xDCC);
+SetRegisterAllowed(0xDD0);
+SetRegisterAllowed(0xDD4);
+SetRegisterAllowed(0xDD8);
+SetRegisterAllowed(0xDDC);
+SetRegisterAllowed(0xDE0);
+SetRegisterAllowed(0xDE4);
+SetRegisterAllowed(0xDE8);
+SetRegisterAllowed(0xDEC);
+SetRegisterAllowed(0xDF0);
+SetRegisterAllowed(0xDF4);
+SetRegisterAllowed(0xDF8);
+SetRegisterAllowed(0xDFC);
+SetRegisterAllowed(0xE00);
+SetRegisterAllowed(0xE04);
+SetRegisterAllowed(0xE08);
+SetRegisterAllowed(0xE0C);
+SetRegisterAllowed(0xE10);
+SetRegisterAllowed(0xE14);
+SetRegisterAllowed(0xE18);
+SetRegisterAllowed(0xE1C);
+SetRegisterAllowed(0xE20);
+SetRegisterAllowed(0xE24);
+SetRegisterAllowed(0xE28);
+SetRegisterAllowed(0xE2C);
+SetRegisterAllowed(0xE30);
+SetRegisterAllowed(0xE34);
+SetRegisterAllowed(0xE38);
+SetRegisterAllowed(0xE3C);
+SetRegisterAllowed(0xE40);
+SetRegisterAllowed(0xE44);
+SetRegisterAllowed(0xE48);
+SetRegisterAllowed(0xE4C);
+SetRegisterAllowed(0xE50);
+SetRegisterAllowed(0xE54);
+SetRegisterAllowed(0xE58);
+SetRegisterAllowed(0xE5C);
+SetRegisterAllowed(0xE60);
+SetRegisterAllowed(0xE64);
+SetRegisterAllowed(0xE68);
+SetRegisterAllowed(0xE6C);
+SetRegisterAllowed(0xE70);
+SetRegisterAllowed(0xE74);
+SetRegisterAllowed(0xE78);
+SetRegisterAllowed(0xE7C);
+SetRegisterAllowed(0xE80);
+SetRegisterAllowed(0xE84);
+SetRegisterAllowed(0xE88);
+SetRegisterAllowed(0xE8C);
+SetRegisterAllowed(0xE90);
+SetRegisterAllowed(0xE94);
+SetRegisterAllowed(0xE98);
+SetRegisterAllowed(0xE9C);
+SetRegisterAllowed(0xEA0);
+SetRegisterAllowed(0xEA4);
+SetRegisterAllowed(0xEA8);
+SetRegisterAllowed(0xEAC);
+SetRegisterAllowed(0xEB0);
+SetRegisterAllowed(0xEB4);
+SetRegisterAllowed(0xEB8);
+SetRegisterAllowed(0xEBC);
+SetRegisterAllowed(0xEC0);
+SetRegisterAllowed(0xEC4);
+SetRegisterAllowed(0xEC8);
+SetRegisterAllowed(0xECC);
+SetRegisterAllowed(0xED0);
+SetRegisterAllowed(0xED4);
+SetRegisterAllowed(0xED8);
+SetRegisterAllowed(0xEDC);
+SetRegisterAllowed(0xEE0);
+SetRegisterAllowed(0xEE4);
+SetRegisterAllowed(0xEE8);
+SetRegisterAllowed(0xEEC);
+SetRegisterAllowed(0xEF0);
+SetRegisterAllowed(0xEF4);
+SetRegisterAllowed(0xEF8);
+SetRegisterAllowed(0xEFC);
+SetRegisterAllowed(0xF00);
+SetRegisterAllowed(0xF04);
+SetRegisterAllowed(0xF08);
+SetRegisterAllowed(0xF0C);
+SetRegisterAllowed(0xF10);
+SetRegisterAllowed(0xF14);
+SetRegisterAllowed(0xF18);
+SetRegisterAllowed(0xF1C);
+SetRegisterAllowed(0xF20);
+SetRegisterAllowed(0xF24);
+SetRegisterAllowed(0xF28);
+SetRegisterAllowed(0xF2C);
+SetRegisterAllowed(0xF30);
+SetRegisterAllowed(0xF34);
+SetRegisterAllowed(0xF38);
+SetRegisterAllowed(0xF3C);
+SetRegisterAllowed(0xF40);
+SetRegisterAllowed(0xF44);
+SetRegisterAllowed(0xF48);
+SetRegisterAllowed(0xF4C);
+SetRegisterAllowed(0xF50);
+SetRegisterAllowed(0xF54);
+SetRegisterAllowed(0xF58);
+SetRegisterAllowed(0xF5C);
+SetRegisterAllowed(0xF60);
+SetRegisterAllowed(0xF64);
+SetRegisterAllowed(0xF68);
+SetRegisterAllowed(0xF6C);
+SetRegisterAllowed(0xF70);
+SetRegisterAllowed(0xF74);
+SetRegisterAllowed(0xF78);
+SetRegisterAllowed(0xF7C);
+SetRegisterAllowed(0xF80);
+SetRegisterAllowed(0xF84);
+SetRegisterAllowed(0xF88);
+SetRegisterAllowed(0xF8C);
+SetRegisterAllowed(0xF90);
+SetRegisterAllowed(0xF94);
+SetRegisterAllowed(0xF98);
+SetRegisterAllowed(0xF9C);
+SetRegisterAllowed(0xFA0);
+SetRegisterAllowed(0xFA4);
+SetRegisterAllowed(0xFA8);
+SetRegisterAllowed(0xFAC);
+SetRegisterAllowed(0xFB0);
+SetRegisterAllowed(0xFB4);
+SetRegisterAllowed(0xFB8);
+SetRegisterAllowed(0xFBC);
+SetRegisterAllowed(0xFC0);
+SetRegisterAllowed(0xFC4);
+SetRegisterAllowed(0xFC8);
+SetRegisterAllowed(0xFCC);
+SetRegisterAllowed(0xFD0);
+SetRegisterAllowed(0xFD4);
+SetRegisterAllowed(0xFD8);
+SetRegisterAllowed(0xFDC);
+SetRegisterAllowed(0xFE0);
+SetRegisterAllowed(0xFE4);
+SetRegisterAllowed(0xFE8);
+SetRegisterAllowed(0xFEC);
+SetRegisterAllowed(0xFF0);
+SetRegisterAllowed(0xFF4);
+SetRegisterAllowed(0xFF8);
+SetRegisterAllowed(0xFFC);
diff --git a/Source/Atmosphere-Patches/secmon_memory_layout.hpp b/Source/Atmosphere-Patches/secmon_memory_layout.hpp
index 7c0e499a..ba3e3ab8 100644
--- a/Source/Atmosphere-Patches/secmon_memory_layout.hpp
+++ b/Source/Atmosphere-Patches/secmon_memory_layout.hpp
@@ -151,7 +151,9 @@ namespace ams::secmon {
HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
- HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+ HANDLER(ExternalMemoryController0, MemoryController1, UINT64_C(0x7001E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+ HANDLER(ExternalMemoryController1, ExternalMemoryController0, UINT64_C(0x7001F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+ HANDLER(Sdmmc, ExternalMemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
diff --git a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp
index af04fa04..36932196 100644
--- a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp
+++ b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp
@@ -99,6 +99,7 @@ namespace ams::secmon::smc {
#include "secmon_define_pmc_access_table.inc"
#include "secmon_define_mc_access_table.inc"
#include "secmon_define_emc_access_table.inc"
+ #include "secmon_define_emc01_access_table.inc"
#include "secmon_define_flow_controller_access_table.inc"
#include "secmon_define_exception_vectors_access_table.inc"
#include "secmon_define_rtc_pmc_access_table.inc"
@@ -108,6 +109,8 @@ namespace ams::secmon::smc {
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
+ { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Size, },
+ { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Size, },
{ FlowControllerAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceFlowController.GetAddress(), FlowControllerAccessTable::Address, FlowControllerAccessTable::Size, },
{ ExceptionVectorsAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExceptionVectors.GetAddress(), ExceptionVectorsAccessTable::Address, ExceptionVectorsAccessTable::Size, },
{ RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
diff --git a/Source/hoc-clk/sysmodule/src/board/board.cpp b/Source/hoc-clk/sysmodule/src/board/board.cpp
index 4923f46c..503c282b 100644
--- a/Source/hoc-clk/sysmodule/src/board/board.cpp
+++ b/Source/hoc-clk/sysmodule/src/board/board.cpp
@@ -50,6 +50,7 @@
#include
#include
#include "../mapping/mem_map.hpp"
+#include "../soc/dram_mrr.hpp"
namespace board {
u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr, sysVirtAddr, actmonVirtAddr, gpuVirtAddr, tmrVirtAddr;
@@ -286,6 +287,10 @@ namespace board {
}
u8 GetDramID() {
+ return soc::mrr::IdentifyDramId();
+ }
+
+ u8 GetFuseDramId() {
return gDramID;
}
diff --git a/Source/hoc-clk/sysmodule/src/board/board.hpp b/Source/hoc-clk/sysmodule/src/board/board.hpp
index 57fa514e..9f9cf356 100644
--- a/Source/hoc-clk/sysmodule/src/board/board.hpp
+++ b/Source/hoc-clk/sysmodule/src/board/board.hpp
@@ -56,6 +56,7 @@ namespace board {
void Exit();
HocClkSocType GetSocType();
HocClkConsoleType GetConsoleType();
+ u8 GetFuseDramId();
u8 GetDramID();
u8 GetGpuSpeedoBracket();
bool IsDram8GB();
diff --git a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp
new file mode 100644
index 00000000..29d6603d
--- /dev/null
+++ b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) CtCaer
+ *
+ * Copyright (c) Souldbminer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "dram_mrr.hpp"
+#include "../board/board.hpp"
+
+#include
+#include
+#include
+
+namespace soc::mrr {
+ constexpr u64 EmcPhysBase = 0x7001B000;
+ constexpr u64 Emc0PhysBase = 0x7001E000;
+ constexpr u64 Emc1PhysBase = 0x7001F000;
+
+ constexpr u32 EmcRegMrr = 0xEC;
+ constexpr u32 EmcRegAdrCfg = 0x10;
+ constexpr u32 EmcRegFbioCfg7 = 0x584;
+ constexpr u32 EmcRegEmcStatus = 0x2B4;
+ constexpr u32 EmcStatusMrrDivld = (1u << 20);
+ constexpr int EmcStatusUpdateTimeout = 100000;
+
+ static bool SmcRead(u64 phys_addr, u32 *out) {
+ SecmonArgs args = {};
+ args.X[0] = 0xF0000002;
+ args.X[1] = phys_addr;
+ args.X[2] = 0;
+ args.X[3] = 0;
+ svcCallSecureMonitor(&args);
+ if (args.X[1] == phys_addr) {
+ return false;
+ }
+ *out = static_cast(args.X[1]);
+ return true;
+ }
+
+ static bool SmcWrite(u64 phys_addr, u32 value) {
+ SecmonArgs args = {};
+ args.X[0] = 0xF0000002;
+ args.X[1] = phys_addr;
+ args.X[2] = 0xFFFFFFFF;
+ args.X[3] = value;
+ svcCallSecureMonitor(&args);
+ return args.X[1] != phys_addr;
+ }
+
+ static bool EmcRead(u32 offset, u32 *out) { return SmcRead(EmcPhysBase + offset, out); }
+ static bool EmcWrite(u32 offset, u32 value) { return SmcWrite(EmcPhysBase + offset, value); }
+ static bool Emc0Read(u32 offset, u32 *out) { return SmcRead(Emc0PhysBase + offset, out); }
+ static bool Emc1Read(u32 offset, u32 *out) { return SmcRead(Emc1PhysBase + offset, out); }
+
+ /* 0 = ignore */
+
+ const DramRevisionMap rev[DRAM_COUNT] = {
+ /* Erista */
+ { .soc = HocClkSocType_Erista, .mfg = MFG_Samsung, .major = 0, .minor = 0, .density = 0, .densityCount = 0 }, /* HB-MGCH */
+ { .soc = HocClkSocType_Erista, .mfg = MFG_SKHynix, .major = 0, .minor = 0, .density = 0, .densityCount = 0 }, /* NLE */
+ { .soc = HocClkSocType_Erista, .mfg = MFG_Micron, .major = 0, .minor = 0, .density = 0, .densityCount = 0 }, /* WT:C */
+
+ /* Mariko */
+ /* Samsung */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Samsung, .major = 6, .minor = 0x10, .density = 1, .densityCount = 2 }, /* AM-MGCJ (6.10, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Samsung, .major = 7, .minor = 0, .density = 1, .densityCount = 2 }, /* AA-MGCL (7.00, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Samsung, .major = 8, .minor = 0, .density = 1, .densityCount = 2 }, /* AB-MGCL (8.00, 4GB) */
+
+ /* Micron */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 4, .minor = 0x10, .density = 1, .densityCount = 2 }, /* WT:E (4.10, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 5, .minor = 0, .density = 1, .densityCount = 2 }, /* WT:F (5.00, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 7, .minor = 0, .density = 1, .densityCount = 2 }, /* WT:B (7.00, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 7, .minor = 0, .density = 1, .densityCount = 4 }, /* WT:B (7.00, 8GB) */
+
+ /* SK Hynix */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 4, .minor = 0, .density = 1, .densityCount = 2 }, /* NME (4.00, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 6, .minor = 0, .density = 1, .densityCount = 2 }, /* NEE (6.00, 4GB) */
+ { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 6, .minor = 0, .density = 1, .densityCount = 4 }, /* NEE (6.00, 8GB) */
+ };
+
+ /* Ported from hekate */
+
+ bool IsMrrAvailable() {
+ u32 val = 0;
+ return EmcRead(EmcRegAdrCfg, &val);
+ }
+
+ static int _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
+ {
+ for (s32 i = 0; i < EmcStatusUpdateTimeout; i++)
+ {
+ u32 val = 0;
+ bool ok;
+ if (emc_channel)
+ {
+ if (emc_channel != 1)
+ return 1;
+
+ ok = Emc1Read(reg_offset, &val);
+ }
+ else
+ {
+ ok = EmcRead(reg_offset, &val);
+ }
+
+ if (ok && (((val & bit_mask) != 0) == updated_state))
+ return 0;
+
+ usleep(1);
+ }
+
+ return 1;
+ }
+
+ static bool _sdram_req_mrr_data(u32 data, bool dual_channel)
+ {
+ if (!EmcWrite(EmcRegMrr, data))
+ return false;
+ if (_sdram_wait_emc_status(EmcRegEmcStatus, EmcStatusMrrDivld, true, EMC_CHAN0) != 0)
+ return false;
+ if (dual_channel && _sdram_wait_emc_status(EmcRegEmcStatus, EmcStatusMrrDivld, true, EMC_CHAN1) != 0)
+ return false;
+ return true;
+ }
+
+ struct EmcTopology {
+ u32 ranks;
+ u32 channels;
+ };
+
+ static bool QueryTopology(EmcTopology *topo) {
+ u32 tmp = 0;
+ if (!EmcRead(EmcRegAdrCfg, &tmp))
+ return false;
+ topo->ranks = (tmp & 1) + 1;
+ if (!EmcRead(EmcRegFbioCfg7, &tmp))
+ return false;
+ u32 ch = (tmp >> 1) & 3;
+ topo->channels = (ch & 1) + ((ch & 2) >> 1);
+ return topo->channels != 0;
+ }
+
+ static void ClearMrrLeftovers() {
+ u32 tmp = 0;
+ for (u32 i = 0; i < 16; i++)
+ {
+ (void)EmcRead(EmcRegMrr, &tmp);
+ usleep(1);
+ }
+ }
+
+ static void StoreMrrBytes(u32 mrr, u8 *lo, u8 *hi) {
+ *lo = mrr & 0xFF;
+ *hi = (mrr >> 8) & 0xFF;
+ }
+
+ static bool ReadMrxRank(emc_mr_t mrx, bool dual_rank, bool dual_channel, emc_mr_data_t *out) {
+ memset(out, 0xFF, sizeof(*out));
+ u32 mrr = 0;
+
+ // Get Device 0 (Rank 0) info from both dram chips (channels).
+ if (!_sdram_req_mrr_data((2u << 30) | (static_cast(mrx) << 16), dual_channel))
+ return false;
+
+ // Ram module 0 info.
+ if (!Emc0Read(EmcRegMrr, &mrr))
+ return false;
+ StoreMrrBytes(mrr, &out->chip0.rank0_ch0, &out->chip0.rank0_ch1);
+
+ // Ram module 1 info.
+ if (dual_channel)
+ {
+ if (!Emc1Read(EmcRegMrr, &mrr))
+ return false;
+ StoreMrrBytes(mrr, &out->chip1.rank0_ch0, &out->chip1.rank0_ch1);
+ }
+
+ // If Rank 1 exists, get info.
+ if (dual_rank)
+ {
+ // Get Device 1 (Rank 1) info from both dram chips (channels).
+ if (!_sdram_req_mrr_data((1u << 30) | (static_cast(mrx) << 16), dual_channel))
+ return false;
+
+ // Ram module 0 info.
+ if (!Emc0Read(EmcRegMrr, &mrr))
+ return false;
+ StoreMrrBytes(mrr, &out->chip0.rank1_ch0, &out->chip0.rank1_ch1);
+
+ // Ram module 1 info.
+ if (dual_channel)
+ {
+ if (!Emc1Read(EmcRegMrr, &mrr))
+ return false;
+ StoreMrrBytes(mrr, &out->chip1.rank1_ch0, &out->chip1.rank1_ch1);
+ }
+ }
+
+ return true;
+ }
+
+ static bool ReadMrxSet(emc_mr_data_t *vendor, emc_mr_data_t *rev0, emc_mr_data_t *rev1,
+ emc_mr_data_t *density, EmcTopology *topo) {
+ EmcTopology t = {};
+ if (!QueryTopology(&t))
+ return false;
+ const bool dual_rank = t.ranks > 1;
+ const bool dual_channel = t.channels > 1;
+
+ ClearMrrLeftovers();
+
+ if (!ReadMrxRank(MR5_MAN_ID, dual_rank, dual_channel, vendor))
+ return false;
+ if (!ReadMrxRank(MR6_REV_ID1, dual_rank, dual_channel, rev0))
+ return false;
+ if (!ReadMrxRank(MR7_REV_ID2, dual_rank, dual_channel, rev1))
+ return false;
+ if (!ReadMrxRank(MR8_DENSITY, dual_rank, dual_channel, density))
+ return false;
+
+ *topo = t;
+ return true;
+ }
+
+ emc_mr_data_t sdram_read_mrx(emc_mr_t mrx)
+ {
+ emc_mr_data_t data;
+ memset(&data, 0xFF, sizeof(emc_mr_data_t));
+
+ EmcTopology topo = {};
+ if (!QueryTopology(&topo))
+ return data;
+
+ ClearMrrLeftovers();
+
+ (void)ReadMrxRank(mrx, topo.ranks > 1, topo.channels > 1, &data);
+ return data;
+ }
+
+ /* MR8 density field (bits 5:2) to MB */
+ static bool DecodeDensityMb(u8 mr8, u32 *mb) {
+ switch ((mr8 & 0x3C) >> 2)
+ {
+ case 2: *mb = 512; break;
+ case 3: *mb = 768; break;
+ case 4: *mb = 1024; break;
+ case 5: *mb = 1536; break;
+ case 6: *mb = 2048; break;
+ default: return false;
+ }
+ return true;
+ }
+
+ static bool MatchModule(HocClkSocType soc, DramMfg mfg, u8 major, u8 minor,
+ u32 densityMb, u32 densityCount, RealDramModule *mod) {
+ for (int i = 0; i < DRAM_COUNT; i++)
+ {
+ const DramRevisionMap &e = rev[i];
+ if (e.soc != soc || e.mfg != mfg)
+ continue;
+ if (soc != HocClkSocType_Erista)
+ {
+ if (e.major != major || e.minor != minor)
+ continue;
+ if (e.density * 1024u != densityMb)
+ continue;
+ if (e.densityCount != densityCount)
+ continue;
+ }
+ *mod = static_cast(i);
+ return true;
+ }
+ return false;
+ }
+
+ static u8 FuseIdForModule(RealDramModule mod, HocClkConsoleType console, u8 fuseFallback) {
+ switch (mod)
+ {
+ case DRAM_HBMGCH:
+ case DRAM_NLE:
+ case DRAM_WTC:
+ return fuseFallback;
+ case DRAM_AMMGCJ:
+ if (console == HocClkConsoleType_Hoag) return 12;
+ if (console == HocClkConsoleType_Iowa) return 8;
+ return fuseFallback;
+ case DRAM_AAMGCL:
+ if (console == HocClkConsoleType_Iowa) return 17;
+ if (console == HocClkConsoleType_Hoag) return 19;
+ if (console == HocClkConsoleType_Aula) return 24;
+ return fuseFallback;
+ case DRAM_ABMGCL:
+ if (console == HocClkConsoleType_Iowa) return 20;
+ if (console == HocClkConsoleType_Hoag) return 21;
+ if (console == HocClkConsoleType_Aula) return 22;
+ return fuseFallback;
+ case DRAM_WTE:
+ if (console == HocClkConsoleType_Iowa) return 11;
+ if (console == HocClkConsoleType_Hoag) return 15;
+ return fuseFallback;
+ case DRAM_WTF:
+ if (console == HocClkConsoleType_Iowa) return 25;
+ if (console == HocClkConsoleType_Hoag) return 26;
+ if (console == HocClkConsoleType_Aula) return 27;
+ return fuseFallback;
+ case DRAM_WTB:
+ if (console == HocClkConsoleType_Iowa) return 32;
+ if (console == HocClkConsoleType_Hoag) return 33;
+ if (console == HocClkConsoleType_Aula) return 34;
+ return fuseFallback;
+ case DRAM_WTB_8GB:
+ case DRAM_NEE_8GB:
+ /* Used in atmosphere and commonly burnt for 8gb upgrade */
+ return 28;
+ case DRAM_NME:
+ if (console == HocClkConsoleType_Iowa) return 10;
+ if (console == HocClkConsoleType_Hoag) return 14;
+ return fuseFallback;
+ case DRAM_NEE:
+ if (console == HocClkConsoleType_Iowa) return 6;
+ if (console == HocClkConsoleType_Hoag) return 3;
+ if (console == HocClkConsoleType_Aula) return 5;
+ return fuseFallback;
+ default:
+ return fuseFallback;
+ }
+ }
+
+ u8 IdentifyDramId() {
+ const u8 fuseId = board::GetFuseDramId();
+ const HocClkSocType soc = board::GetSocType();
+
+ if (soc == HocClkSocType_Erista)
+ return fuseId;
+
+ if (!IsMrrAvailable())
+ return fuseId;
+
+ emc_mr_data_t vendor = {}, rev0 = {}, rev1 = {}, density = {};
+ EmcTopology topo = {};
+ if (!ReadMrxSet(&vendor, &rev0, &rev1, &density, &topo))
+ return fuseId;
+
+ DramMfg mfg;
+ switch (vendor.chip0.rank0_ch0)
+ {
+ case MFG_Samsung:
+ case MFG_SKHynix:
+ case MFG_Micron:
+ mfg = static_cast(vendor.chip0.rank0_ch0);
+ break;
+ default:
+ return fuseId;
+ }
+
+ u32 densityMb = 0;
+ if (!DecodeDensityMb(density.chip0.rank0_ch0, &densityMb))
+ return fuseId;
+
+ RealDramModule mod = DRAM_COUNT;
+ if (!MatchModule(soc, mfg, rev0.chip0.rank0_ch0, rev1.chip0.rank0_ch0,
+ densityMb, topo.ranks * topo.channels, &mod))
+ return fuseId; /* TODO: Find hynix x267 config */
+
+ return FuseIdForModule(mod, board::GetConsoleType(), fuseId);
+ }
+
+
+}
\ No newline at end of file
diff --git a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp
new file mode 100644
index 00000000..4a425df1
--- /dev/null
+++ b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) CtCaer
+ *
+ * Copyright (c) Souldbminer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#include
+
+namespace soc::mrr {
+ typedef enum RealDramModule {
+ /* Erista */
+ DRAM_HBMGCH = 0,
+ DRAM_NLE,
+ DRAM_WTC,
+
+ /* Mariko */
+
+ /* Samsung */
+ DRAM_AMMGCJ,
+ DRAM_AAMGCL,
+ DRAM_ABMGCL,
+
+ /* Micron */
+ DRAM_WTE,
+ DRAM_WTF,
+ DRAM_WTB,
+ DRAM_WTB_8GB,
+
+ /* SK Hynix */
+ DRAM_NME,
+ DRAM_NEE,
+ DRAM_NEE_8GB,
+ DRAM_COUNT,
+ } RealDramModule;
+
+ typedef enum _emc_mr_t
+ {
+ MR0_FEAT = 0,
+ MR4_TEMP = 4,
+ MR5_MAN_ID = 5,
+ MR6_REV_ID1 = 6,
+ MR7_REV_ID2 = 7,
+ MR8_DENSITY = 8,
+ } emc_mr_t;
+
+ enum
+ {
+ EMC_CHAN0 = 0,
+ EMC_CHAN1 = 1
+ };
+
+ typedef struct _emc_mr_chip_data_t
+ {
+ // Device 0.
+ u8 rank0_ch0;
+ u8 rank0_ch1;
+
+ // Device 1.
+ u8 rank1_ch0;
+ u8 rank1_ch1;
+ } emc_mr_chip_data_t;
+
+ typedef struct _emc_mr_data_t
+ {
+ emc_mr_chip_data_t chip0;
+ emc_mr_chip_data_t chip1;
+ } emc_mr_data_t;
+
+ typedef enum DramMfg {
+ MFG_Samsung = 1,
+ MFG_SKHynix = 6,
+ MFG_Micron = 255,
+ } DramMfg;
+
+ typedef struct DramRevisionMap {
+ HocClkSocType soc;
+ DramMfg mfg;
+ u8 major;
+ u8 minor;
+ u8 density; // GB per die
+ u8 densityCount; // number of dies (2 = 4GB, 4 = 8GB)
+ } DramRevisionMap;
+
+ extern const DramRevisionMap rev[DRAM_COUNT];
+
+ emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
+ bool IsMrrAvailable();
+
+ /* Fuse-style DRAM ID (hekate numbering, as in board::GetDramID):
+ derived from MRR when the patched exosphere grants EMC access,
+ otherwise falls back to the fuse ODM4 ID. MRR-detected 8GB WT:B/NEE
+ (no dedicated fuse numbering) alias to Aula AA-MGCL 8GB (28). */
+ u8 IdentifyDramId();
+}
\ No newline at end of file
diff --git a/build.sh b/build.sh
index 29b842fa..c2161a58 100755
--- a/build.sh
+++ b/build.sh
@@ -114,6 +114,8 @@ if [ "$NO_EXO" -eq 0 ]; then
cp -v "$EXO_SRC/secmon_setup.cpp" "$EXO_PROGRAM_DEST/"
cp -v "$EXO_SRC/secmon_define_emc_access_table.inc" "$EXO_DEST/"
cp -v "$EXO_SRC/secmon_emc_access_table_data.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_define_emc01_access_table.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_emc01_access_table_data.inc" "$EXO_DEST/"
cp -v "$EXO_SRC/secmon_define_rtc_pmc_access_table.inc" "$EXO_DEST/"
cp -v "$EXO_SRC/secmon_rtc_pmc_access_table_data.inc" "$EXO_DEST/"
cp -v "$EXO_SRC/secmon_define_flow_controller_access_table.inc" "$EXO_DEST/"