NK.exe Cold Boot Flow¶
This page documents the detailed execution flow of NK.exe during a cold boot, from initial entry through kernel initialization and into the scheduler.
Entry Point¶
NK.exe entry is at VA 0x80076B50 (PA 0x00076B50, kseg0). The first instructions:
- CP0 initialization
JRto0xA0076BA0(kseg1 -- uncached mirror of the same code)- Set SP =
0xA0003800 - Enable CMU (Clock Management Unit) clocks
- Call ROM HW init routines
Early Hardware Init (0x76C60)¶
After a BCU (Bus Control Unit) revision check, the main hardware initialization path at 0x76C60 performs:
- Version check at PA
0x2400for value0x03020100 - Hibernate signature check at PA
0x2524(upper 16 bits ==0x3210) - VRC4173 companion chip initialization
- NAND controller initialization
- Cache initialization
- Switch SP to kseg0
Pre-Init Phase (0xA0079460)¶
The pre-init continuation calls a series of initialization functions:
0x79ADC-- hardware setup0x7AC50-- additional init0x79B2C,0x79B4C-- subsystem initJ 0x79510-- PMU/SDRAM configuration loop at0x79560-0x79598
The Warm Path Bug¶
After the pre-init phase, NK.exe switches to kseg0 via FUN_800795B4, which computes address 0x800795D8 and jumps to it. From there:
check1 (0x80079AC4)¶
Reads the button register at PA 0x0A00A042, masks with 0x9E00, and stores the result in $v0. Critically, it also sets $t0 = 0xAA00A000 (always non-zero, a side effect of the LUI used to form the register address).
check2 (0x8007AFA8)¶
Reads VRC4173 status registers. Does not modify $t0.
Branch Decision (0x795F0)¶
Because $t0 was set to 0xAA00A000 by check1 and never cleared, this branch is always taken. The cold boot initialization code at 0x79DF8 is effectively dead code.
Warning
This appears to be a bug in NK.exe. The $t0 register is clobbered by check1 before it can be tested as a cold/warm discriminator. As a result, NK.exe always takes the warm (resume) path, even on a genuine cold boot. The emulator works around this by seeding the resume context at PA 0x2200 with cold-start values.
Warm Path: GPR/CP0 Restore (0x79634)¶
The warm path proceeds through:
JAL 0x78BC0-- OAL vtable initialization- VR41xx hardware setup (timers, ICU, ISR, VRC4173)
- CP0 restore from resume_ctx (PA
0x2200) at addresses0x79668-0x79714 - Full GPR restore from resume_ctx at
0x79730 - Epilogue at
0x797DC:LW $t0, 0($sp); JR $ra; ADDIU $sp, 4
The JR $ra returns to whatever address was stored in the resume context's RA field. On a seeded cold boot, this is 0x8007B398.
Cold-Start Kernel Entry (0x8007B398)¶
This is the true kernel cold-start initialization, building everything from scratch:
CP0 Setup¶
Clears: Cause, EntryHi, Context, EntryLo0, EntryLo1, PageMask, Count.
Page Table¶
Zeros the page table at PA 0x1000 (4 KB).
Section Table¶
Sets up 64 entries at PA 0x18C0:
- Default handler:
0x8008BC18 - Section 9 handler:
0x8008B8E4(special)
Stack and Pointers¶
- SP =
0xA00017E0(kseg1, no TLB needed) - Kernel data pointer at PA
0x1AC8=0x80000000 - Kernel data pointer at PA
0x1ACC=0x8008B84C
TLB Configuration¶
- PageMask =
0x1800 - Wired = 2
- Writes fixed TLB entries for kernel address space
Exception Handlers¶
Installed via JAL 0x8007B5F4:
| Vector Address | Handler Source | Purpose |
|---|---|---|
PA 0x0000 |
Code from 0x8008C418 |
TLB refill |
PA 0x0180 |
Code from 0x8008B240 |
General exception |
PA 0x0100 |
Code from 0x800A8438 |
Cache error |
Kernel Main Init¶
The critical call:
This function creates processes, loads the 95 XIP modules referenced by the ROMHDR, and starts the shell.
Post-Init Calls¶
After kernel_init returns:
JAL 0x80078BC0-- OAL vtable initJAL 0x800A5C78-- display and splash screen setupJAL 0x800942B4-- additional kernel initJAL 0x800964FC-- final setup- Enter the scheduler
NK.exe Memory Layout¶
0x80060000-0x80075FFF Bootstrap and OAL data
0x80076B50-0x80079xxx OAL initialization code
0x8007Axxx-0x8007Bxxx OAL hardware drivers and cold-start
0x80080000-0x800Fffff Kernel proper (~640KB)
0x800A0000-0x800Bxxxx OAL callbacks and device drivers
0x80060000-0x80656AC8 Total NK.exe image (6.2MB)
0x80655C54 ROMHDR (pTOC)
0x80660000-0x81000000 RAM (ulRAMStart to ulRAMEnd)
ROMHDR¶
The ROMHDR structure at pTOC (0x80655C54):
| Field | Value |
|---|---|
| physfirst | 0x80060000 |
| physlast | 0x80656AC8 |
| nummods | 95 |
| ulRAMStart | 0x80660000 |
Display Mechanism¶
The "Initializing..." and "Starting..." splash screens are rendered at runtime:
- OAL display function at
0x80078E10acts as a blit dispatcher:a0=10-- clear screen (fill framebuffer at0xAA200000)a0=0-- blit splash buffer from VA0x80061188a0=6-- blit 240x160 pixel buffer from VA0x80061CD0to framebuffer
- The buffers are zero-filled in NK.exe and populated at runtime by GWE font rendering
Kernel Entry Table¶
Located at VA 0x80074D90:
| Index | Address | Note |
|---|---|---|
| 0 | 0x8008CEA4 |
|
| 1 | 0x8009101C |
|
| 2 | 0x80090F34 |
|
| 3 | 0x80090F40 |
|
| 4 | 0x80090F8C |
|
| 5 | 0x80090FC8 |
|
| 6 | 0x80090FF4 |
|
| 7 | 0x00000000 |
Unused |
Additional entries:
0x80074DB0=0x80655C54(pTOC pointer)0x80074DBC="OEM\0"(ASCII identifier)