diff options
| author | Tharo <tharo10600@gmail.com> | 2026-05-06 08:25:34 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-06 09:25:34 +0200 |
| commit | 18d73ff3743ec70127e03f7a28947d586298bd30 (patch) | |
| tree | 39d241f8ae66b35de250185c0bd5b092e085153a /src/boot | |
| parent | 5625f1826e0f5fac87bc66acefe5cdf3fd038237 (diff) | |
Document CIC6105 (#2739)
* Document CIC6105
* Changes, AUDIOMGR_DEBUG_LEVEL -> AUDIOMGR_ACTIVITY_LEVEL
Diffstat (limited to 'src/boot')
| -rw-r--r-- | src/boot/boot_main.c | 2 | ||||
| -rw-r--r-- | src/boot/cic6105.c | 100 |
2 files changed, 67 insertions, 35 deletions
diff --git a/src/boot/boot_main.c b/src/boot/boot_main.c index 91b74cbe9..ba95a33bf 100644 --- a/src/boot/boot_main.c +++ b/src/boot/boot_main.c @@ -29,7 +29,7 @@ void bootproc(void) { osMemSize = osGetMemSize(); #if PLATFORM_N64 - func_80001720(); + CIC6105_SaveBootMagicValues(); #endif bootclear(); osInitialize(); diff --git a/src/boot/cic6105.c b/src/boot/cic6105.c index fadae3a18..8f8ba0d0e 100644 --- a/src/boot/cic6105.c +++ b/src/boot/cic6105.c @@ -1,5 +1,19 @@ +/** + * @file cic6105.c + * + * This file implements routines relating to the CIC X105 anti-piracy measures present in N64 releases. + * + * The "authentication" chain begins in IPL3, which deposits specific expected values into RAM and runs an RSP task in + * parallel with loading the boot segment into RAM. This RSP task leaves data in the RSP's registers which rspboot and + * the CIC6105 RSP task later read according to routines in this file. Their security model relied on CICs being + * uncloneable with scarcely many donor CIC options from other games available at the time, in which case IPL3 would be + * unmodifiable. The rest of the chain is designed with a "security through obscurity" mindset, storing later antipiracy + * checks intermixed with other game code or RSP code that was expected to be non-trivial to analyze in a timely + * fashion. Notably this effort did little to curb emulation, almost wholly due to early emulators being insufficiently + * accurate to run RSP code or even IPL3 at a low level, sidestepping much of the early setup in favor of providing a + * known-good post-boot state to begin emulation from. + */ #pragma increment_block_number "ntsc-1.0:132 ntsc-1.1:132 ntsc-1.2:132 pal-1.0:132 pal-1.1:132" - #include "audiomgr.h" #include "build.h" #include "cic6105.h" @@ -7,35 +21,47 @@ #include "regs.h" #include "sched.h" -s32 func_80001714(void); +s32 CIC6105_Stub(void); -OSTask D_800067C0_unknown = { - 4, 0, rspbootTextStart, 0x3E8, cic6105TextStart, 0x20, (u64*)gBuildCreator, 8, NULL, 0, NULL, 0, NULL, 0, NULL, 0, +OSTask sCIC6105Task = { + // clang-format off + 4, + 0, + rspbootTextStart, 0x3E8, + cic6105TextStart, 0x20, + (u64*)gBuildCreator, 8, + NULL, 0, + NULL, NULL, + NULL, 0, + NULL, 0, + // clang-format on }; -u32 B_80008EE0; -u32 B_80008EE4; +u32 gCICBootMagic0; +u32 gCICBootMagic1; FaultClient sCIC6105FaultClient; -u32 B_80008EF8; -u32 B_80008EFC; +u32 sCICTaskResult0; +u32 sCICTaskResult1; -void func_800014D0(void) { - R_AUDIOMGR_DEBUG_LEVEL = AUDIOMGR_DEBUG_LEVEL_NO_RSP; +void CIC6105_DisableAudio(void) { + R_AUDIOMGR_ACTIVITY_LEVEL = AUDIOMGR_ACTIVITY_LEVEL_NO_RSP; } -void func_800014E8(void) { - R_AUDIOMGR_DEBUG_LEVEL = AUDIOMGR_DEBUG_LEVEL_NONE; +void CIC6105_EnableAudio(void) { + R_AUDIOMGR_ACTIVITY_LEVEL = AUDIOMGR_ACTIVITY_LEVEL_ALL; } void CIC6105_FaultClient(void) { - s32 spStatus; + u32 spStatus = IO_READ(SP_STATUS_REG); - spStatus = IO_READ(SP_STATUS_REG); Fault_SetCursor(48, 200); + // Signal 7 is set by rspboot when it is first executed, corresponding to + // whether rspboot's antipiracy checks passed. Signal 7 is expected to + // stay set for the entire duration of the game running. if (spStatus & SP_STATUS_SIG7) { - Fault_Printf("OCARINA %08x %08x", B_80008EF8, B_80008EFC); + Fault_Printf("OCARINA %08x %08x", sCICTaskResult0, sCICTaskResult1); } else { - Fault_Printf("LEGEND %08x %08x", B_80008EF8, B_80008EFC); + Fault_Printf("LEGEND %08x %08x", sCICTaskResult0, sCICTaskResult1); } Fault_SetCursor(40, 184); Fault_Printf("ROM_F"); @@ -47,7 +73,7 @@ void CIC6105_FaultClient(void) { #else Fault_SetCursor(96, 32); #endif - Fault_Printf("I LOVE YOU %08x", func_80001714()); + Fault_Printf("I LOVE YOU %08x", CIC6105_Stub()); } void CIC6105_AddFaultClient(void) { @@ -58,31 +84,37 @@ void CIC6105_RemoveFaultClient(void) { Fault_RemoveClient(&sCIC6105FaultClient); } -void func_80001640(void) { - OSScTask sp38; +void CIC6105_RunBootTask(void) { + OSScTask scTask; OSMesgQueue queue; OSMesg msg; + // Prepare the CIC6105 task osCreateMesgQueue(&queue, &msg, 1); - sp38.next = NULL; - sp38.flags = OS_SC_NEEDS_RSP; - sp38.msgQueue = &queue; - sp38.msg = (OSMesg)0; - sp38.framebuffer = 0; - sp38.list = D_800067C0_unknown; - osSendMesg(&gScheduler.cmdQueue, &sp38, OS_MESG_BLOCK); + scTask.next = NULL; + scTask.flags = OS_SC_NEEDS_RSP; + scTask.msgQueue = &queue; + scTask.msg = (OSMesg)0; + scTask.framebuffer = NULL; + scTask.list = sCIC6105Task; + // Send it to the scheduler for execution + osSendMesg(&gScheduler.cmdQueue, &scTask, OS_MESG_BLOCK); Sched_Notify(&gScheduler); - osRecvMesg(&queue, NULL, 1); - B_80008EF8 = IO_READ(SP_DMEM_START + 0xFF4); - B_80008EFC = IO_READ(SP_DMEM_START + 0xFFC); - func_80001714(); + // Blocking wait until completion + osRecvMesg(&queue, NULL, OS_MESG_BLOCK); + // Retrieve results from RSP DMEM, it is assumed no other RSP task is running + sCICTaskResult0 = IO_READ(SP_DMEM_START + 0xFF4); + sCICTaskResult1 = IO_READ(SP_DMEM_START + 0xFFC); + CIC6105_Stub(); } -s32 func_80001714(void) { +s32 CIC6105_Stub(void) { return 0; } -void func_80001720(void) { - B_80008EE0 = IO_READ(0x002FB1F4); - B_80008EE4 = IO_READ(0x002FE1C0); +void CIC6105_SaveBootMagicValues(void) { + // IPL3 writes two magic values into RDRAM during the boot process into fixed locations. + // These must be retrieved early before memory is claimed by game memory management systems. + gCICBootMagic0 = IO_READ(0x002FB1F4); + gCICBootMagic1 = IO_READ(0x002FE1C0); } |
