main() bring-up sequence
4. main() bring-up sequence
Section titled “4. main() bring-up sequence”Primarily describes the second-pass execution from §3; steps now understood to belong to the first pass are noted explicitly.
4.1 Prologue and boot markers
Section titled “4.1 Prologue and boot markers”- Standard N32 stack frame; saves
raands0–s7. FullAllocAndFree(a0)runs immediately. inferred heap sanity/defrag pass.- An 8-byte magic value written to
0x01FE0000— a boot-progress marker. - EE Timer 0’s MODE register (
0x10000010) set to0x83. Reused later as an RNG seed source.
4.2 Core SDK bring-up
Section titled “4.2 Core SDK bring-up”mwInit()sceSifInitRpc()sceCdInit()Followed by the IOP kernel reboot — sceSifRebootIop with two fixed string
literals (the kernel’s path and args), confirmed via boot log to load a distinct
ROM-style image (§6) located
immediately after main on disc. sceSifSyncIop waits for completion; RPC and
filesystem drivers are re-initialized since IOP-side state resets across the
reboot. Thread priority is raised via ChangeThreadPriority(tid, 0x2D).
inferred — this reboot very likely triggers the full EE-side reset
from §3, i.e. this is
the end of the first-pass execution of main, not a mid-sequence step within
one continuous run.
4.3 CStorage::Open and SIF RPC system server IDs
Section titled “4.3 CStorage::Open and SIF RPC system server IDs”confirmed — CStorage::Open’s small integer parameter (e.g. 0,
1, 2 as seen at various call sites) is not itself a raw SIF System Server
ID. It is CStorage::Open’s own internal index, which it translates to one of
the standard PS2 SDK SIF RPC System Server IDs before issuing the actual RPC.
inferred — this table is inferred from standard documentation (sourced from ps2tek). If the IOP module is custom then the SIF RPC System Server IDs may differ from the standard PS2 SDK values.
| ID | Purpose | Module |
|---|---|---|
0x80000001 |
File I/O | FILEIO |
0x80000003 |
IOP heap allocation | FILEIO |
0x80000006 |
Module/ELF loader | LOADFILE |
0x80000100 |
Pad | PADMAN |
0x80000101 |
Pad extension (unconfirmed) | PADMAN |
0x80000400 |
Memory cards | MCSERV |
0x80000592 |
CDVD init | CDVDFSV |
0x80000593 |
CDVD S commands | CDVDFSV |
0x80000595 |
CDVD N commands | CDVDFSV |
0x80000597 |
CDVD SearchFile | CDVDFSV |
0x8000059A |
CDVD disk ready | CDVDFSV |
0x80000701 |
LIBSD remote (not in BIOS) | SDRDRV |
0x80000901–0x80000905 |
MTAP port management (not in BIOS) | MTAPMAN |
0x80001400 |
EyeToy (not in BIOS) | EYETOY |
4.4 Engine (CBios) bring-up
Section titled “4.4 Engine (CBios) bring-up”CBios::GetStorage() -> CStorage::StorageInit()CBios::GetStorage() -> CStorage::MakeFileSystem() ; see section 7CBios::GetDecompress() ; handle reused throughout bootCSif::Init()RNG seeding: a live EE Timer0 COUNT register read, multiplied by a fixed
constant, 0xCAD added, and the result seeds InitRandom().
confirmed, fully reproducible.
4.5 Conditional gate: the shared flag byte
Section titled “4.5 Conditional gate: the shared flag byte”confirmed — a flag byte at storage + 0xD99B gates multiple
subsequent decisions. Everywhere it is read, nonzero means “skip the real work,
return success/no-op immediately.”
inferred, revised given
§3: since main runs
twice across an EE reset, this flag may specifically distinguish first-pass from
second-pass state. It is worth checking whether it reads differently across the
two executions rather than assuming a generic “dev-mode” meaning. Alternatively,
this flag could be a soft-reset flag.
4.6 Game-specific IOP module load
Section titled “4.6 Game-specific IOP module load”Gated by the flag in §4.5.
confirmed — the core OS-level modules (SYSMEM, LOADFILE,
PADMAN, MCSERV, CDVDFSV… see IOPRP300.IMG) are already active by this
point, provided by the kernel image from the first pass
(§4.2). This loop’s 12 modules are game-specific IOP
modules, loaded via a CStorage::Open/Read from the first TOC entry, proven
from disk read logs.
Loop mechanics:
- Buffer read and decompressed via
CDecompress::Decode. - DMA’d into IOP heap memory.
- 12 modules loaded in a loop (indices 0–11):
- Indices 8 and 9 are special-cased:
sceSifLoadStartModuleBufferwith argument strings from a fixed string table (likely driver args — inferred). - All other indices:
sceSifLoadModuleBuffer.
- Indices 8 and 9 are special-cased:
4.7 Region setup, graphics, task init
Section titled “4.7 Region setup, graphics, task init”CStorage::InitHdd,std::set_new_handler,sceDmaReset.- PAL/NTSC branch, GS display parameters per region.
CPSTask::InitTask— the main task/scheduler object.- 16 iterations of
CPSTask::GsSyncPath.
4.8 Sound init
Section titled “4.8 Sound init”Same gate as §4.5.
CSoundManager::InitSoundManager()CSoundManager::InitSoundMemory(...)CSoundManager::InitMusicList(...)CVoiceManager::SetVoiceTable(...)CSoundManager::InitKeepSE(...) ; conditional on a second flag4.9 Secret key and checksum pass
Section titled “4.9 Secret key and checksum pass”CSound::GetSecretKeyCode fills a buffer, which is processed by a VU0
microprogram, combined with CStorage::ReadClock, summed into a byte, and used
as a loop bound to burn additional Random() calls. inferred:
entropy mixing, not a hard integrity gate.
4.10 Overlay segment loader: hand-off to segment 1 (Step0 00)
Section titled “4.10 Overlay segment loader: hand-off to segment 1 (Step0 00)”index = 1loop: header = CDecompress::GetCompHeader(decompress_handle, buffer2, index) if header == NULL: break CBios::DecompressProgramOnly(decompress_handle, header, ...) index += 1
CBios::DecompressAndExec(decompress_handle, buffer2, index=1) ; hardcodedconfirmed — buffer2 holds a concatenated table of compressed
segments. GetCompHeader is 1-based and returns NULL past the last segment;
every segment from index 1 upward is pre-staged via DecompressProgramOnly; once
exhausted, DecompressAndExec transfers execution permanently into segment 1.
Code after this point is very likely dead.
inferred — segment 1 almost certainly contains the runtime
overlay-switching logic, since segments 2 and up are pre-staged but never
executed from main() itself.