summaryrefslogtreecommitdiff
path: root/src/boot
diff options
context:
space:
mode:
authorTharo <tharo10600@gmail.com>2026-05-06 08:25:34 +0100
committerGitHub <noreply@github.com>2026-05-06 09:25:34 +0200
commit18d73ff3743ec70127e03f7a28947d586298bd30 (patch)
tree39d241f8ae66b35de250185c0bd5b092e085153a /src/boot
parent5625f1826e0f5fac87bc66acefe5cdf3fd038237 (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.c2
-rw-r--r--src/boot/cic6105.c100
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);
}