diff --git a/.gitattributes b/.gitattributes index e410e21..8650aaa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,9 +5,8 @@ *.patch -text translator/tests/Translator.Tests/TestAssets/**/*.bin binary -# Region tables reproduced by tools/region/ +# Region tables projects/mkwii-ntsc-*/MAP.txt linguist-generated=true projects/mkwii-ntsc-*/region_port.json linguist-generated=true projects/mkwii-ntsc-j/data_addresses.txt linguist-generated=true -runtime/include/guest_abi/guest_address_table.inc linguist-generated=true -runtime/include/guest_function_imports.inc linguist-generated=true +runtime/include/guest_abi/guest_versions.inc linguist-generated=true diff --git a/.gitignore b/.gitignore index 331770e..704d29c 100644 --- a/.gitignore +++ b/.gitignore @@ -67,7 +67,6 @@ project.lock.json /.vscode/ /.idea/ /tools/* -!/tools/region/ __pycache__/ /TEMP/ /tmp/ diff --git a/Launcher/Test-Recompilation.ps1 b/Launcher/Test-Recompilation.ps1 index ab3ae91..cc2799e 100644 --- a/Launcher/Test-Recompilation.ps1 +++ b/Launcher/Test-Recompilation.ps1 @@ -54,16 +54,10 @@ foreach ($relative in $sourceFiles | Sort-Object -Unique) { } # One synthetic text section: li r3,40; addi r3,r3,2; nop; blr. -# Native HLE wrappers also call these guest symbols directly. Give each -# its own generated blr function so the real product can link without game code. -# Keep this list explicit: a new unresolved guest dependency must fail the test. +# Guest functions the runtime calls directly resolve through the registry at run time, so the +# product links without any game code. [uint32]$entry = 0x80001000L -[uint32[]]$guestCallbacks = @( - 0x8012B830L, 0x801A0620L, 0x801A1ED8L, 0x801A961CL, - 0x801AADE0L, 0x801D8D30L, 0x801D9E94L, 0x8055531CL, - 0x80601C64L, 0x8061E348L, 0x8061E3B4L -) -$textSize = [int]($guestCallbacks[-1] - $entry + 4) +$textSize = 0x10 $dataOffset = 0x100 + $textSize $dol = [byte[]]::new($dataOffset + 4) function Write-BigEndian32([int]$Offset, [uint32]$Value) { @@ -74,24 +68,21 @@ function Write-BigEndian32([int]$Offset, [uint32]$Value) { } Write-BigEndian32 0x00 0x100 # text[0] file offset Write-BigEndian32 0x48 $entry # text[0] guest address -Write-BigEndian32 0x90 $textSize # text[0] length (unreachable gaps are zero) +Write-BigEndian32 0x90 $textSize # text[0] length Write-BigEndian32 0x1C $dataOffset # data[0] file offset -Write-BigEndian32 0x64 0x80700000L # data[0] guest address +Write-BigEndian32 0x64 0x80600000L # data[0] guest address Write-BigEndian32 0xAC 4 # data[0] length -Write-BigEndian32 0xD8 0x80701000L # BSS address +Write-BigEndian32 0xD8 0x80601000L # BSS address Write-BigEndian32 0xDC 32 # BSS length Write-BigEndian32 0xE0 $entry # entry point Write-BigEndian32 0x100 0x38600028 # li r3,40 Write-BigEndian32 0x104 0x38630002 # addi r3,r3,2 Write-BigEndian32 0x108 0x60000000 # nop Write-BigEndian32 0x10C 0x4E800020 # blr -foreach ($address in $guestCallbacks) { - Write-BigEndian32 ([int](0x100 + $address - $entry)) 0x4E800020 -} Write-BigEndian32 $dataOffset 0x12345678 [IO.File]::WriteAllBytes((Join-Path $stage 'synthetic.dol'), $dol) -$entryPoints = (@($entry) + $guestCallbacks | ForEach-Object { '0x{0:X8}' -f $_ }) -join ', ' -$functionMap = (@($entry) + $guestCallbacks | ForEach-Object { '{0:X8} func_{0:X8}' -f $_ }) -join "`n" +$entryPoints = '0x{0:X8}' -f $entry +$functionMap = '{0:X8} func_{0:X8}' -f $entry [IO.File]::WriteAllText((Join-Path $stage 'synthetic-functions.txt'), $functionMap) $manifest = Join-Path $stage 'recomp.yml' [IO.File]::WriteAllText($manifest, @" @@ -103,8 +94,8 @@ project: memory: base: 0x80000000 size: 0x01800000 - sda_base: 0x80700000 - sda2_base: 0x80700000 + sda_base: 0x80600000 + sda2_base: 0x80600000 inputs: dol: path: synthetic.dol @@ -129,7 +120,7 @@ Invoke-Checked $dotnet @($translator, 'translate-recursive', '0x80001000', '--pr 'Translating the synthetic DOL' # Function-map seeds can be skipped by discovery; do not accept a partial fixture. $translated = Get-Content -LiteralPath $metadata -Raw | ConvertFrom-Json -foreach ($address in @($entry) + $guestCallbacks) { +foreach ($address in @($entry)) { if ($address -notin $translated.functions.entryPoint) { throw ('Synthetic function 0x{0:X8} was not translated.' -f $address) } diff --git a/Launcher/WiiCompiled.Setup.Windows/ToolkitFingerprint.cs b/Launcher/WiiCompiled.Setup.Windows/ToolkitFingerprint.cs index 16aa770..d7c83b4 100644 --- a/Launcher/WiiCompiled.Setup.Windows/ToolkitFingerprint.cs +++ b/Launcher/WiiCompiled.Setup.Windows/ToolkitFingerprint.cs @@ -43,7 +43,7 @@ internal static class ToolkitFingerprint [ InstalledLayout.WorkspaceEntryPrefix + "LocalBuild.ps1", // Maps the PAL-keyed native index to the installed release's addresses. - InstalledLayout.WorkspaceEntryPrefix + "runtime/include/guest_abi/guest_address_table.inc" + InstalledLayout.WorkspaceEntryPrefix + "runtime/include/guest_abi/guest_versions.inc" ]; private const string NativeSourcePrefix = InstalledLayout.WorkspaceEntryPrefix + "runtime/src/"; diff --git a/Launcher/build-cache.sh b/Launcher/build-cache.sh index e6a395c..55cc070 100644 --- a/Launcher/build-cache.sh +++ b/Launcher/build-cache.sh @@ -77,7 +77,7 @@ mkw_translation_identity() { printf 'rel %s\n' "$(mkw_digest_path "$workspace/Assets/StaticR.rel")" printf 'translator %s\n' "$(mkw_digest_path "$translator")" printf 'script %s\n' "$(mkw_digest_path "$script")" - printf 'regions %s\n' "$(mkw_digest_path "$workspace/runtime/include/guest_abi/guest_address_table.inc")" + printf 'regions %s\n' "$(mkw_digest_path "$workspace/runtime/include/guest_abi/guest_versions.inc")" mkw_digest_tree "$workspace" projects mkw_native_index_identity "$workspace" } | mkw_sha256 diff --git a/runtime/game/guest_region.cpp b/runtime/game/guest_region.cpp index f7fc4a1..7504a2e 100644 --- a/runtime/game/guest_region.cpp +++ b/runtime/game/guest_region.cpp @@ -1,5 +1,4 @@ #include "guest_abi/guest_region.h" -#include "guest_function_imports.h" #if !defined(MKW_TRANSLATED_GUEST_REGION) #error "MKW_TRANSLATED_GUEST_REGION comes from the translator's shard manifest (emit-build-shards)" @@ -8,19 +7,3 @@ static_assert(MKW_TRANSLATED_GUEST_REGION >= 0 && MKW_TRANSLATED_GUEST_REGION < GuestRegion::kCount); extern "C" const uint8_t kMkwGuestRegion = MKW_TRANSLATED_GUEST_REGION; - -#define MKW_DEFINE_GUEST_FUNCTION_IMPORT(pal, symbol) \ - extern "C" void func_##symbol(CpuContext*); \ - extern "C" void (*const mkw_guest_function_##pal)(CpuContext*) = &func_##symbol; \ - static_assert(MKW_GADDR_CT(pal) == 0x##symbol##u, "guest_function_imports.inc disagrees with " \ - "guest_address_table.inc"); - -#if MKW_TRANSLATED_GUEST_REGION == 0 -#define MKW_GUEST_FUNCTION_IMPORT(pal, ntscU, ntscJ) MKW_DEFINE_GUEST_FUNCTION_IMPORT(pal, pal) -#elif MKW_TRANSLATED_GUEST_REGION == 1 -#define MKW_GUEST_FUNCTION_IMPORT(pal, ntscU, ntscJ) MKW_DEFINE_GUEST_FUNCTION_IMPORT(pal, ntscU) -#else -#define MKW_GUEST_FUNCTION_IMPORT(pal, ntscU, ntscJ) MKW_DEFINE_GUEST_FUNCTION_IMPORT(pal, ntscJ) -#endif -#include "guest_function_imports.inc" -#undef MKW_GUEST_FUNCTION_IMPORT diff --git a/runtime/include/guest_abi/guest_address_table.inc b/runtime/include/guest_abi/guest_address_table.inc deleted file mode 100644 index 9abf45c..0000000 --- a/runtime/include/guest_abi/guest_address_table.inc +++ /dev/null @@ -1,748 +0,0 @@ -// AUTO-GENERATED by tools/region/gen_guest_address_table.py - DO NOT EDIT. -// PAL identity -> address in each region: MKW_GUEST_ADDRESS(PAL, NTSC-U, NTSC-J). -// Sorted by PAL address; guest_abi/guest_region.h relies on that. -MKW_GUEST_ADDRESS(80006348, 80006348, 80006348) // __init_hardware -MKW_GUEST_ADDRESS(800077C8, 800077C8, 800077C8) // StrapScene::CheckInput -MKW_GUEST_ADDRESS(8000A000, 80009FC0, 80009F5C) -MKW_GUEST_ADDRESS(8000A400, 8000A3C0, 8000A35C) -MKW_GUEST_ADDRESS(80015500, 800149A0, 80015424) // __write_console -MKW_GUEST_ADDRESS(8002001C, 8001F4BC, 8001FF40) -MKW_GUEST_ADDRESS(80044B30, 80044A90, 80044A50) // GXEnd -MKW_GUEST_ADDRESS(80048C30, 80048B90, 80048B50) // GXEnd -MKW_GUEST_ADDRESS(800847C0, 80084720, 800846E0) // nw4r::lyt::detail::DrawQuad -MKW_GUEST_ADDRESS(80084D20, 80084C80, 80084C40) // nw4r::lyt::detail::DrawQuad -MKW_GUEST_ADDRESS(800A35E0, 800A3540, 800A3500) // nw4r::snd::SoundPlayer::SetVolume -MKW_GUEST_ADDRESS(800BD860, 800BD7C0, 800BD780) // thunk_0x800bc440 -MKW_GUEST_ADDRESS(80123F88, 80123EE8, 80123EA8) // AIRegisterDMACallback -MKW_GUEST_ADDRESS(80123FCC, 80123F2C, 80123EEC) // AIInitDMA -MKW_GUEST_ADDRESS(80124048, 80123FA8, 80123F68) // AIStartDMA -MKW_GUEST_ADDRESS(8012405C, 80123FBC, 80123F7C) // AIGetDMABytesLeft -MKW_GUEST_ADDRESS(8012406C, 80123FCC, 80123F8C) // AIGetDMAStartAddr -MKW_GUEST_ADDRESS(80124084, 80123FE4, 80123FA4) // AIGetDMALength -MKW_GUEST_ADDRESS(80124094, 80123FF4, 80123FB4) // AICheckInit -MKW_GUEST_ADDRESS(8012409C, 80123FFC, 80123FBC) // AIGetDSPSampleRate -MKW_GUEST_ADDRESS(801240B0, 80124010, 80123FD0) // AIInit -MKW_GUEST_ADDRESS(80126948, 801268A8, 80126868) // __AXDSPInitCallback -MKW_GUEST_ADDRESS(80126954, 801268B4, 80126874) // __AXDSPResumeCallback -MKW_GUEST_ADDRESS(801269A8, 80126908, 801268C8) // __AXDSPRequestCallback -MKW_GUEST_ADDRESS(801269B8, 80126918, 801268D8) -MKW_GUEST_ADDRESS(801269BC, 8012691C, 801268DC) // __AXOutInitDSP -MKW_GUEST_ADDRESS(8012B830, 8012B790, 8012B750) // AXFXReverbStdExpCallback -MKW_GUEST_ADDRESS(8012E574, 8012E4D4, 8012E494) // PPCMfhid0 -MKW_GUEST_ADDRESS(8012E57C, 8012E4DC, 8012E49C) // PPCMthid0 -MKW_GUEST_ADDRESS(8012E594, 8012E4F4, 8012E4B4) // PPCMtdec -MKW_GUEST_ADDRESS(8012E59C, 8012E4FC, 8012E4BC) // PPCSync -MKW_GUEST_ADDRESS(8012E5A4, 8012E504, 8012E4C4) // PPCHalt -MKW_GUEST_ADDRESS(8012E5B8, 8012E518, 8012E4D8) // PPCMtmmcr0 -MKW_GUEST_ADDRESS(8012E5C0, 8012E520, 8012E4E0) // PPCMtmmcr1 -MKW_GUEST_ADDRESS(8012E5C8, 8012E528, 8012E4E8) // PPCMtpmc1 -MKW_GUEST_ADDRESS(8012E5D0, 8012E530, 8012E4F0) // PPCMtpmc2 -MKW_GUEST_ADDRESS(8012E5D8, 8012E538, 8012E4F8) // PPCMtpmc3 -MKW_GUEST_ADDRESS(8012E5E0, 8012E540, 8012E500) // PPCMtpmc4 -MKW_GUEST_ADDRESS(8012E630, 8012E590, 8012E550) // PPCMfhid2 -MKW_GUEST_ADDRESS(8012E638, 8012E598, 8012E558) // PPCMthid2 -MKW_GUEST_ADDRESS(8012E640, 8012E5A0, 8012E560) // PPCMfwpar -MKW_GUEST_ADDRESS(8012E64C, 8012E5AC, 8012E56C) // PPCMtwpar -MKW_GUEST_ADDRESS(8012E654, 8012E5B4, 8012E574) // PPCDisableSpeculation -MKW_GUEST_ADDRESS(8012E684, 8012E5E4, 8012E5A4) // PPCMthid4 -MKW_GUEST_ADDRESS(801301B4, 80130114, 801300D4) // GKI_delay -MKW_GUEST_ADDRESS(8015BC80, 8015BBE0, 8015BBA0) // contentFastOpenNAND -MKW_GUEST_ADDRESS(8015BCF8, 8015BC58, 8015BC18) // contentReadNAND -MKW_GUEST_ADDRESS(8015D3FC, 8015D35C, 8015D31C) // DSPCheckMailToDSP -MKW_GUEST_ADDRESS(8015D40C, 8015D36C, 8015D32C) // RVL::DSPCheckMailFromDSP -MKW_GUEST_ADDRESS(8015D41C, 8015D37C, 8015D33C) // RVL::DSPReadMailFromDSP -MKW_GUEST_ADDRESS(8015D430, 8015D390, 8015D350) // DSPSendMailToDSP -MKW_GUEST_ADDRESS(8015D444, 8015D3A4, 8015D364) // DSPInit -MKW_GUEST_ADDRESS(8015D504, 8015D464, 8015D424) // DSPCheckInit -MKW_GUEST_ADDRESS(8015D50C, 8015D46C, 8015D42C) // DSPAddTask -MKW_GUEST_ADDRESS(8015D57C, 8015D4DC, 8015D49C) // DSPAssertTask -MKW_GUEST_ADDRESS(8015DC60, 8015DBC0, 8015DB80) // __DSP_boot_task -MKW_GUEST_ADDRESS(8015DF1C, 8015DE7C, 8015DE3C) // __DVDFSInit -MKW_GUEST_ADDRESS(8015E74C, 8015E6AC, 8015E66C) // DVD::ReadAsyncPrio -MKW_GUEST_ADDRESS(8015E834, 8015E794, 8015E754) // DVDReadPrio -MKW_GUEST_ADDRESS(8015EA1C, 8015E97C, 8015E93C) // DVD::Init -MKW_GUEST_ADDRESS(801628CC, 8016282C, 801627EC) // DVD::ReadAbsAsyncPrio -MKW_GUEST_ADDRESS(801643FC, 8016435C, 8016431C) // __DVDCheckDevice -MKW_GUEST_ADDRESS(80164848, 801647A8, 80164768) // DVD::LowInit -MKW_GUEST_ADDRESS(80164AAC, 80164A0C, 801649CC) // DVD::LowReadDiskID -MKW_GUEST_ADDRESS(80165708, 80165668, 80165628) // DVD::LowUnencryptedRead -MKW_GUEST_ADDRESS(80165A30, 80165990, 80165950) // DVD::LowInquiry -MKW_GUEST_ADDRESS(80166330, 80166290, 80166250) // DVD::LowRead -MKW_GUEST_ADDRESS(80166964, 801668C4, 80166884) // DVD::LowClearCoverInterrupt -MKW_GUEST_ADDRESS(801671D0, 80167130, 801670F0) // ESP_InitLib -MKW_GUEST_ADDRESS(80167224, 80167184, 80167144) // ESP_CloseLib -MKW_GUEST_ADDRESS(80167904, 80167864, 80167824) // ESP_GetDataDir -MKW_GUEST_ADDRESS(8016799C, 801678FC, 801678BC) // ESP_GetTitleId -MKW_GUEST_ADDRESS(80167E78, 80167DD8, 80167D98) // SetExiInterruptMask -MKW_GUEST_ADDRESS(80167F68, 80167EC8, 80167E88) // RVL::EXIImm -MKW_GUEST_ADDRESS(80168288, 801681E8, 801681A8) // RVL::EXIDma -MKW_GUEST_ADDRESS(80168380, 801682E0, 801682A0) // RVL::EXISync -MKW_GUEST_ADDRESS(801689D0, 80168930, 801688F0) // RVL::EXISelect -MKW_GUEST_ADDRESS(80168B00, 80168A60, 80168A20) // RVL::EXIDeselect -MKW_GUEST_ADDRESS(80168FA0, 80168F00, 80168EC0) // EXIInit -MKW_GUEST_ADDRESS(80169260, 801691C0, 80169180) // RVL::EXIUnlock -MKW_GUEST_ADDRESS(80169BCC, 80169B2C, 80169AEC) // ISFS::OpenLib -MKW_GUEST_ADDRESS(8016B49C, 8016B3FC, 8016B3BC) // __GX::DefaultTexRegionCallback -MKW_GUEST_ADDRESS(8016B590, 8016B4F0, 8016B4B0) // __GX::DefaultTlutRegionCallback -MKW_GUEST_ADDRESS(8016B5B4, 8016B514, 8016B4D4) // __GX::Shutdown -MKW_GUEST_ADDRESS(8016B720, 8016B680, 8016B640) // __GX::InitRevisionBits -MKW_GUEST_ADDRESS(8016B850, 8016B7B0, 8016B770) // GX::Init -MKW_GUEST_ADDRESS(8016C668, 8016C5C8, 8016C588) // GX::CPInterruptHandler -MKW_GUEST_ADDRESS(8016C94C, 8016C8AC, 8016C86C) // GX::SetCPUFifo -MKW_GUEST_ADDRESS(8016CB2C, 8016CA8C, 8016CA4C) // GX::SetGPFifo -MKW_GUEST_ADDRESS(8016CDBC, 8016CD1C, 8016CCDC) // __GX::SaveFifo -MKW_GUEST_ADDRESS(8016CF10, 8016CE70, 8016CE30) // GX::GetCPUFifo -MKW_GUEST_ADDRESS(8016D054, 8016CFB4, 8016CF74) // GX::SetBreakPtCallback -MKW_GUEST_ADDRESS(8016D098, 8016CFF8, 8016CFB8) // GX::EnableBreakPt -MKW_GUEST_ADDRESS(8016D138, 8016D098, 8016D058) // GX::DisableBreakPt -MKW_GUEST_ADDRESS(8016D1FC, 8016D15C, 8016D11C) // __GX::CleanGPFifo -MKW_GUEST_ADDRESS(8016D3A4, 8016D304, 8016D2C4) // GX::SetVtxDesc -MKW_GUEST_ADDRESS(8016D3C0, 8016D320, 8016D2E0) // GX::SetVtxDesc_switch -MKW_GUEST_ADDRESS(8016D3C4, 8016D324, 8016D2E4) // GX::SetVtxDesc_caseD_0 -MKW_GUEST_ADDRESS(8016D3D8, 8016D338, 8016D2F8) // GX::SetVtxDesc_caseD_1 -MKW_GUEST_ADDRESS(8016D3EC, 8016D34C, 8016D30C) // GX::SetVtxDesc_caseD_2 -MKW_GUEST_ADDRESS(8016D400, 8016D360, 8016D320) // GX::SetVtxDesc_caseD_3 -MKW_GUEST_ADDRESS(8016D414, 8016D374, 8016D334) // GX::SetVtxDesc_caseD_4 -MKW_GUEST_ADDRESS(8016D428, 8016D388, 8016D348) // GX::SetVtxDesc_caseD_5 -MKW_GUEST_ADDRESS(8016D43C, 8016D39C, 8016D35C) // GX::SetVtxDesc_caseD_6 -MKW_GUEST_ADDRESS(8016D450, 8016D3B0, 8016D370) // GX::SetVtxDesc_caseD_7 -MKW_GUEST_ADDRESS(8016D464, 8016D3C4, 8016D384) // GX::SetVtxDesc_caseD_8 -MKW_GUEST_ADDRESS(8016D478, 8016D3D8, 8016D398) // GX::SetVtxDesc_caseD_9 -MKW_GUEST_ADDRESS(8016D48C, 8016D3EC, 8016D3AC) // GX::SetVtxDesc_caseD_a -MKW_GUEST_ADDRESS(8016D4C0, 8016D420, 8016D3E0) // GX::SetVtxDesc_caseD_19 -MKW_GUEST_ADDRESS(8016D4F4, 8016D454, 8016D414) // GX::SetVtxDesc_caseD_b -MKW_GUEST_ADDRESS(8016D508, 8016D468, 8016D428) // GX::SetVtxDesc_caseD_c -MKW_GUEST_ADDRESS(8016D51C, 8016D47C, 8016D43C) // GX::SetVtxDesc_caseD_d -MKW_GUEST_ADDRESS(8016D530, 8016D490, 8016D450) // GX::SetVtxDesc_caseD_e -MKW_GUEST_ADDRESS(8016D544, 8016D4A4, 8016D464) // GX::SetVtxDesc_caseD_f -MKW_GUEST_ADDRESS(8016D558, 8016D4B8, 8016D478) // GX::SetVtxDesc_caseD_10 -MKW_GUEST_ADDRESS(8016D56C, 8016D4CC, 8016D48C) // GX::SetVtxDesc_caseD_11 -MKW_GUEST_ADDRESS(8016D580, 8016D4E0, 8016D4A0) // GX::SetVtxDesc_caseD_12 -MKW_GUEST_ADDRESS(8016D594, 8016D4F4, 8016D4B4) // GX::SetVtxDesc_caseD_13 -MKW_GUEST_ADDRESS(8016D5A8, 8016D508, 8016D4C8) // GX::SetVtxDesc_caseD_14 -MKW_GUEST_ADDRESS(8016D5B8, 8016D518, 8016D4D8) // GX::SetVtxDesc_caseD_15 -MKW_GUEST_ADDRESS(8016D608, 8016D568, 8016D528) // GX::SetVtxDescv -MKW_GUEST_ADDRESS(8016D814, 8016D774, 8016D734) // __GX::SetVCD -MKW_GUEST_ADDRESS(8016D8C4, 8016D824, 8016D7E4) // __GX::CalculateVLim -MKW_GUEST_ADDRESS(8016D9F0, 8016D950, 8016D910) // GX::GetVtxDesc -MKW_GUEST_ADDRESS(8016DA0C, 8016D96C, 8016D92C) // GX::GetVtxDesc_switch -MKW_GUEST_ADDRESS(8016DA10, 8016D970, 8016D930) // GX::GetVtxDesc_caseD_0 -MKW_GUEST_ADDRESS(8016DA20, 8016D980, 8016D940) // GX::GetVtxDesc_caseD_1 -MKW_GUEST_ADDRESS(8016DA30, 8016D990, 8016D950) // GX::GetVtxDesc_caseD_2 -MKW_GUEST_ADDRESS(8016DA40, 8016D9A0, 8016D960) // GX::GetVtxDesc_caseD_3 -MKW_GUEST_ADDRESS(8016DA50, 8016D9B0, 8016D970) // GX::GetVtxDesc_caseD_4 -MKW_GUEST_ADDRESS(8016DA60, 8016D9C0, 8016D980) // GX::GetVtxDesc_caseD_5 -MKW_GUEST_ADDRESS(8016DA70, 8016D9D0, 8016D990) // GX::GetVtxDesc_caseD_6 -MKW_GUEST_ADDRESS(8016DA80, 8016D9E0, 8016D9A0) // GX::GetVtxDesc_caseD_7 -MKW_GUEST_ADDRESS(8016DA90, 8016D9F0, 8016D9B0) // GX::GetVtxDesc_caseD_8 -MKW_GUEST_ADDRESS(8016DAA0, 8016DA00, 8016D9C0) // GX::GetVtxDesc_caseD_9 -MKW_GUEST_ADDRESS(8016DAB0, 8016DA10, 8016D9D0) // GX::GetVtxDesc_caseD_a -MKW_GUEST_ADDRESS(8016DAD4, 8016DA34, 8016D9F4) // GX::GetVtxDesc_caseD_19 -MKW_GUEST_ADDRESS(8016DAF8, 8016DA58, 8016DA18) // GX::GetVtxDesc_caseD_b -MKW_GUEST_ADDRESS(8016DB08, 8016DA68, 8016DA28) // GX::GetVtxDesc_caseD_c -MKW_GUEST_ADDRESS(8016DB18, 8016DA78, 8016DA38) // GX::GetVtxDesc_caseD_d -MKW_GUEST_ADDRESS(8016DB28, 8016DA88, 8016DA48) // GX::GetVtxDesc_caseD_e -MKW_GUEST_ADDRESS(8016DB38, 8016DA98, 8016DA58) // GX::GetVtxDesc_caseD_f -MKW_GUEST_ADDRESS(8016DB48, 8016DAA8, 8016DA68) // GX::GetVtxDesc_caseD_10 -MKW_GUEST_ADDRESS(8016DB58, 8016DAB8, 8016DA78) // GX::GetVtxDesc_caseD_11 -MKW_GUEST_ADDRESS(8016DB68, 8016DAC8, 8016DA88) // GX::GetVtxDesc_caseD_12 -MKW_GUEST_ADDRESS(8016DB78, 8016DAD8, 8016DA98) // GX::GetVtxDesc_caseD_13 -MKW_GUEST_ADDRESS(8016DB88, 8016DAE8, 8016DAA8) // GX::GetVtxDesc_caseD_14 -MKW_GUEST_ADDRESS(8016DB98, 8016DAF8, 8016DAB8) // GX::GetVtxDesc_caseD_15 -MKW_GUEST_ADDRESS(8016DBA4, 8016DB04, 8016DAC4) // GX::GetVtxDescv -MKW_GUEST_ADDRESS(8016DC34, 8016DB94, 8016DB54) // GX::ClearVtxDesc -MKW_GUEST_ADDRESS(8016DC68, 8016DBC8, 8016DB88) // GX::SetVtxAttrFmt -MKW_GUEST_ADDRESS(8016DC94, 8016DBF4, 8016DBB4) // GX::SetVtxAttrFmt_switch -MKW_GUEST_ADDRESS(8016DC98, 8016DBF8, 8016DBB8) // GX::SetVtxAttrFmt_caseD_9 -MKW_GUEST_ADDRESS(8016DCB0, 8016DC10, 8016DBD0) // GX::SetVtxAttrFmt_caseD_19 -MKW_GUEST_ADDRESS(8016DCEC, 8016DC4C, 8016DC0C) // GX::SetVtxAttrFmt_caseD_b -MKW_GUEST_ADDRESS(8016DD00, 8016DC60, 8016DC20) // GX::SetVtxAttrFmt_caseD_c -MKW_GUEST_ADDRESS(8016DD14, 8016DC74, 8016DC34) // GX::SetVtxAttrFmt_caseD_d -MKW_GUEST_ADDRESS(8016DD2C, 8016DC8C, 8016DC4C) // GX::SetVtxAttrFmt_caseD_e -MKW_GUEST_ADDRESS(8016DD44, 8016DCA4, 8016DC64) // GX::SetVtxAttrFmt_caseD_f -MKW_GUEST_ADDRESS(8016DD5C, 8016DCBC, 8016DC7C) // GX::SetVtxAttrFmt_caseD_10 -MKW_GUEST_ADDRESS(8016DD74, 8016DCD4, 8016DC94) // GX::SetVtxAttrFmt_caseD_11 -MKW_GUEST_ADDRESS(8016DD94, 8016DCF4, 8016DCB4) // GX::SetVtxAttrFmt_caseD_12 -MKW_GUEST_ADDRESS(8016DDAC, 8016DD0C, 8016DCCC) // GX::SetVtxAttrFmt_caseD_13 -MKW_GUEST_ADDRESS(8016DDC4, 8016DD24, 8016DCE4) // GX::SetVtxAttrFmt_caseD_14 -MKW_GUEST_ADDRESS(8016DDD8, 8016DD38, 8016DCF8) // GX::SetVtxAttrFmt_caseD_15 -MKW_GUEST_ADDRESS(8016DE08, 8016DD68, 8016DD28) // GX::SetVtxAttrFmtv -MKW_GUEST_ADDRESS(8016DE48, 8016DDA8, 8016DD68) // GX::SetVtxAttrFmtv_switch -MKW_GUEST_ADDRESS(8016DE4C, 8016DDAC, 8016DD6C) // GX::SetVtxAttrFmtv_caseD_9 -MKW_GUEST_ADDRESS(8016DE64, 8016DDC4, 8016DD84) // GX::SetVtxAttrFmtv_caseD_19 -MKW_GUEST_ADDRESS(8016DEA0, 8016DE00, 8016DDC0) // GX::SetVtxAttrFmtv_caseD_b -MKW_GUEST_ADDRESS(8016DEB4, 8016DE14, 8016DDD4) // GX::SetVtxAttrFmtv_caseD_c -MKW_GUEST_ADDRESS(8016DEC8, 8016DE28, 8016DDE8) // GX::SetVtxAttrFmtv_caseD_d -MKW_GUEST_ADDRESS(8016DEE0, 8016DE40, 8016DE00) // GX::SetVtxAttrFmtv_caseD_e -MKW_GUEST_ADDRESS(8016DEF8, 8016DE58, 8016DE18) // GX::SetVtxAttrFmtv_caseD_f -MKW_GUEST_ADDRESS(8016DF10, 8016DE70, 8016DE30) // GX::SetVtxAttrFmtv_caseD_10 -MKW_GUEST_ADDRESS(8016DF28, 8016DE88, 8016DE48) // GX::SetVtxAttrFmtv_caseD_11 -MKW_GUEST_ADDRESS(8016DF48, 8016DEA8, 8016DE68) // GX::SetVtxAttrFmtv_caseD_12 -MKW_GUEST_ADDRESS(8016DF60, 8016DEC0, 8016DE80) // GX::SetVtxAttrFmtv_caseD_13 -MKW_GUEST_ADDRESS(8016DF78, 8016DED8, 8016DE98) // GX::SetVtxAttrFmtv_caseD_14 -MKW_GUEST_ADDRESS(8016DF8C, 8016DEEC, 8016DEAC) // GX::SetVtxAttrFmtv_caseD_15 -MKW_GUEST_ADDRESS(8016DFCC, 8016DF2C, 8016DEEC) // __GX::SetVAT -MKW_GUEST_ADDRESS(8016E04C, 8016DFAC, 8016DF6C) // GX::GetVtxAttrFmt -MKW_GUEST_ADDRESS(8016E078, 8016DFD8, 8016DF98) // GX::GetVtxAttrFmt_switch -MKW_GUEST_ADDRESS(8016E07C, 8016DFDC, 8016DF9C) // GX::GetVtxAttrFmt_caseD_9 -MKW_GUEST_ADDRESS(8016E0A4, 8016E004, 8016DFC4) // GX::GetVtxAttrFmt_caseD_19 -MKW_GUEST_ADDRESS(8016E118, 8016E078, 8016E038) // GX::GetVtxAttrFmt_caseD_b -MKW_GUEST_ADDRESS(8016E13C, 8016E09C, 8016E05C) // GX::GetVtxAttrFmt_caseD_c -MKW_GUEST_ADDRESS(8016E160, 8016E0C0, 8016E080) // GX::GetVtxAttrFmt_caseD_d -MKW_GUEST_ADDRESS(8016E188, 8016E0E8, 8016E0A8) // GX::GetVtxAttrFmt_caseD_e -MKW_GUEST_ADDRESS(8016E1B0, 8016E110, 8016E0D0) // GX::GetVtxAttrFmt_caseD_f -MKW_GUEST_ADDRESS(8016E1C4, 8016E124, 8016E0E4) -MKW_GUEST_ADDRESS(8016E1D8, 8016E138, 8016E0F8) // GX::GetVtxAttrFmt_caseD_10 -MKW_GUEST_ADDRESS(8016E200, 8016E160, 8016E120) // GX::GetVtxAttrFmt_caseD_11 -MKW_GUEST_ADDRESS(8016E228, 8016E188, 8016E148) // GX::GetVtxAttrFmt_caseD_12 -MKW_GUEST_ADDRESS(8016E250, 8016E1B0, 8016E170) // GX::GetVtxAttrFmt_caseD_13 -MKW_GUEST_ADDRESS(8016E278, 8016E1D8, 8016E198) // GX::GetVtxAttrFmt_caseD_14 -MKW_GUEST_ADDRESS(8016E2A0, 8016E200, 8016E1C0) // GX::GetVtxAttrFmt_caseD_15 -MKW_GUEST_ADDRESS(8016E2B8, 8016E218, 8016E1D8) // GX::GetVtxAttrFmtv -MKW_GUEST_ADDRESS(8016E32C, 8016E28C, 8016E24C) // GX::SetArray -MKW_GUEST_ADDRESS(8016E37C, 8016E2DC, 8016E29C) // GX::SetTexCoordGen2 -MKW_GUEST_ADDRESS(8016E3A4, 8016E304, 8016E2C4) // GX::SetTexCoordGen2_switch -MKW_GUEST_ADDRESS(8016E3A8, 8016E308, 8016E2C8) // GX::SetTexCoordGen2_caseD_0 -MKW_GUEST_ADDRESS(8016E3B4, 8016E314, 8016E2D4) // GX::SetTexCoordGen2_caseD_1 -MKW_GUEST_ADDRESS(8016E3C0, 8016E320, 8016E2E0) // GX::SetTexCoordGen2_caseD_2 -MKW_GUEST_ADDRESS(8016E3CC, 8016E32C, 8016E2EC) // GX::SetTexCoordGen2_caseD_3 -MKW_GUEST_ADDRESS(8016E3D8, 8016E338, 8016E2F8) // GX::SetTexCoordGen2_caseD_13 -MKW_GUEST_ADDRESS(8016E3E0, 8016E340, 8016E300) // GX::SetTexCoordGen2_caseD_14 -MKW_GUEST_ADDRESS(8016E3E8, 8016E348, 8016E308) // GX::SetTexCoordGen2_caseD_4 -MKW_GUEST_ADDRESS(8016E3F0, 8016E350, 8016E310) // GX::SetTexCoordGen2_caseD_5 -MKW_GUEST_ADDRESS(8016E3F8, 8016E358, 8016E318) // GX::SetTexCoordGen2_caseD_6 -MKW_GUEST_ADDRESS(8016E400, 8016E360, 8016E320) // GX::SetTexCoordGen2_caseD_7 -MKW_GUEST_ADDRESS(8016E408, 8016E368, 8016E328) // GX::SetTexCoordGen2_caseD_8 -MKW_GUEST_ADDRESS(8016E410, 8016E370, 8016E330) // GX::SetTexCoordGen2_caseD_9 -MKW_GUEST_ADDRESS(8016E418, 8016E378, 8016E338) // GX::SetTexCoordGen2_caseD_a -MKW_GUEST_ADDRESS(8016E420, 8016E380, 8016E340) // GX::SetTexCoordGen2_caseD_b -MKW_GUEST_ADDRESS(8016E424, 8016E384, 8016E344) // GX::SetTexCoordGen2_caseD_10 -MKW_GUEST_ADDRESS(8016E514, 8016E474, 8016E434) // GX::SetTexCoordGen2_switch -MKW_GUEST_ADDRESS(8016E518, 8016E478, 8016E438) // GX::SetTexCoordGen2_caseD_0 -MKW_GUEST_ADDRESS(8016E528, 8016E488, 8016E448) // GX::SetTexCoordGen2_caseD_1 -MKW_GUEST_ADDRESS(8016E538, 8016E498, 8016E458) // GX::SetTexCoordGen2_caseD_2 -MKW_GUEST_ADDRESS(8016E548, 8016E4A8, 8016E468) // GX::SetTexCoordGen2_caseD_3 -MKW_GUEST_ADDRESS(8016E558, 8016E4B8, 8016E478) // GX::SetTexCoordGen2_caseD_4 -MKW_GUEST_ADDRESS(8016E568, 8016E4C8, 8016E488) // GX::SetTexCoordGen2_caseD_5 -MKW_GUEST_ADDRESS(8016E578, 8016E4D8, 8016E498) // GX::SetTexCoordGen2_caseD_6 -MKW_GUEST_ADDRESS(8016E588, 8016E4E8, 8016E4A8) -MKW_GUEST_ADDRESS(8016E5A4, 8016E504, 8016E4C4) // GX::SetNumTexGens -MKW_GUEST_ADDRESS(8016E654, 8016E5B4, 8016E574) // GX::Flush -MKW_GUEST_ADDRESS(8016E6B0, 8016E610, 8016E5D0) // GX::ResetWriteGatherPipe -MKW_GUEST_ADDRESS(8016E6E4, 8016E644, 8016E604) // __GX::Abort -MKW_GUEST_ADDRESS(8016E848, 8016E7A8, 8016E768) // GX::AbortFrame -MKW_GUEST_ADDRESS(8016E9FC, 8016E95C, 8016E91C) // GX::SetDrawSync -MKW_GUEST_ADDRESS(8016EAB0, 8016EA10, 8016E9D0) // GX::DrawDone -MKW_GUEST_ADDRESS(8016EB70, 8016EAD0, 8016EA90) // GX::PixModeSync -MKW_GUEST_ADDRESS(8016EB94, 8016EAF4, 8016EAB4) // GX::PokeAlphaMode -MKW_GUEST_ADDRESS(8016EBA4, 8016EB04, 8016EAC4) // GX::PokeAlphaUpdate -MKW_GUEST_ADDRESS(8016EBBC, 8016EB1C, 8016EADC) // GX::PokeAlphaUpdate -MKW_GUEST_ADDRESS(8016EBD0, 8016EB30, 8016EAF0) // GX::PokeBlendMode -MKW_GUEST_ADDRESS(8016EC2C, 8016EB8C, 8016EB4C) // GX::PokeColorUpdate -MKW_GUEST_ADDRESS(8016EC40, 8016EBA0, 8016EB60) // GX::PokeDstAlpha -MKW_GUEST_ADDRESS(8016EC58, 8016EBB8, 8016EB78) // GX::PokeDither -MKW_GUEST_ADDRESS(8016EC6C, 8016EBCC, 8016EB8C) // GX::PokeZMode -MKW_GUEST_ADDRESS(8016ECCC, 8016EC2C, 8016EBEC) // GX::TokenInterruptHandler -MKW_GUEST_ADDRESS(8016ED50, 8016ECB0, 8016EC70) // GX::SetDrawDoneCallback -MKW_GUEST_ADDRESS(8016ED94, 8016ECF4, 8016ECB4) // GX::FinishInterruptHandler -MKW_GUEST_ADDRESS(8016EE14, 8016ED74, 8016ED34) // __GX::PEInit -MKW_GUEST_ADDRESS(8016EE78, 8016EDD8, 8016ED98) // __GX::SetDirtyState -MKW_GUEST_ADDRESS(8016F0F0, 8016F050, 8016F010) // GX::Begin -MKW_GUEST_ADDRESS(8016F23C, 8016F19C, 8016F15C) // __GX::SendFlushPrim -MKW_GUEST_ADDRESS(8016F314, 8016F274, 8016F234) // GX::SetLineWidth -MKW_GUEST_ADDRESS(8016F348, 8016F2A8, 8016F268) // GX::SetPointSize -MKW_GUEST_ADDRESS(8016F37C, 8016F2DC, 8016F29C) // GX::EnableTexOffsets -MKW_GUEST_ADDRESS(8016F3B8, 8016F318, 8016F2D8) // GX::SetCullMode -MKW_GUEST_ADDRESS(8016F3E0, 8016F340, 8016F300) // GX::SetCoPlanar -MKW_GUEST_ADDRESS(8016F414, 8016F374, 8016F334) // __GX::SetGenMode -MKW_GUEST_ADDRESS(8016F438, 8016F398, 8016F358) // GX::SetDispCopySrc -MKW_GUEST_ADDRESS(8016F478, 8016F3D8, 8016F398) // GX::SetTexCopySrc -MKW_GUEST_ADDRESS(8016F4B8, 8016F418, 8016F3D8) // GX::SetDispCopyDst -MKW_GUEST_ADDRESS(8016F4DC, 8016F43C, 8016F3FC) // GX::SetTexCopyDst -MKW_GUEST_ADDRESS(8016F5F8, 8016F558, 8016F518) // GX::SetDispCopyFrame2Field -MKW_GUEST_ADDRESS(8016F618, 8016F578, 8016F538) // GX::SetCopyClamp -MKW_GUEST_ADDRESS(8016FA40, 8016F9A0, 8016F960) // GX::SetCopyFilter -MKW_GUEST_ADDRESS(8016FC24, 8016FB84, 8016FB44) // GX::SetDispCopyGamma -MKW_GUEST_ADDRESS(8016FC38, 8016FB98, 8016FB58) // GX::CopyDisp -MKW_GUEST_ADDRESS(8016FD74, 8016FCD4, 8016FC94) // GX::CopyTex -MKW_GUEST_ADDRESS(8016FECC, 8016FE2C, 8016FDEC) // GX::ClearBoundingBox -MKW_GUEST_ADDRESS(80170320, 80170280, 80170240) // GX::LoadLightObjImm -MKW_GUEST_ADDRESS(8017039C, 801702FC, 801702BC) // GX::SetChanAmbColor -MKW_GUEST_ADDRESS(80170474, 801703D4, 80170394) // GX::SetChanMatColor -MKW_GUEST_ADDRESS(8017054C, 801704AC, 8017046C) // GX::SetNumChans -MKW_GUEST_ADDRESS(80170570, 801704D0, 80170490) // GX::SetChanCtrl -MKW_GUEST_ADDRESS(801707F8, 80170758, 80170718) // GX::InitTexObj -MKW_GUEST_ADDRESS(80170938, 80170898, 80170858) // GX::InitTexObj_switch -MKW_GUEST_ADDRESS(8017093C, 8017089C, 8017085C) // GX::InitTexObj_caseD_0 -MKW_GUEST_ADDRESS(80170950, 801708B0, 80170870) // GX::InitTexObj_caseD_1 -MKW_GUEST_ADDRESS(80170964, 801708C4, 80170884) // GX::InitTexObj_caseD_3 -MKW_GUEST_ADDRESS(80170978, 801708D8, 80170898) // GX::InitTexObj_caseD_6 -MKW_GUEST_ADDRESS(8017098C, 801708EC, 801708AC) // GX::InitTexObj_caseD_e -MKW_GUEST_ADDRESS(801709A0, 80170900, 801708C0) // GX::InitTexObj_caseD_7 -MKW_GUEST_ADDRESS(80170A04, 80170964, 80170924) // GX::InitTexObjCI -MKW_GUEST_ADDRESS(80170A4C, 801709AC, 8017096C) // GX::InitTexObjLOD -MKW_GUEST_ADDRESS(80170B50, 80170AB0, 80170A70) // GX::InitTexObjWrapMode -MKW_GUEST_ADDRESS(80170B64, 80170AC4, 80170A84) // GX::InitTexObjTlut -MKW_GUEST_ADDRESS(80170B6C, 80170ACC, 80170A8C) // GX::InitTexObjFilter -MKW_GUEST_ADDRESS(80170B94, 80170AF4, 80170AB4) // GX::InitTexObjLODBias -MKW_GUEST_ADDRESS(80170BE8, 80170B48, 80170B08) // GX::InitTexObjUserData -MKW_GUEST_ADDRESS(80170BF8, 80170B58, 80170B18) // GX::GetTexObjAll -MKW_GUEST_ADDRESS(80170CBC, 80170C1C, 80170BDC) // GX::GetTexObjLODAll -MKW_GUEST_ADDRESS(80170DC8, 80170D28, 80170CE8) // GX::LoadTexObjPreLoaded -MKW_GUEST_ADDRESS(80170F2C, 80170E8C, 80170E4C) // GX::LoadTexObj -MKW_GUEST_ADDRESS(80170F80, 80170EE0, 80170EA0) // GX::InitTlutObj -MKW_GUEST_ADDRESS(80170FA8, 80170F08, 80170EC8) // GX::LoadTlut -MKW_GUEST_ADDRESS(80171110, 80171070, 80171030) // GX::InvalidateTexAll -MKW_GUEST_ADDRESS(80171180, 801710E0, 801710A0) // GX::SetTexCoordScaleManually -MKW_GUEST_ADDRESS(801711FC, 8017115C, 8017111C) // GX::SetTexCoordBias -MKW_GUEST_ADDRESS(801712F0, 80171250, 80171210) // __GX::SetSUTexRegs -MKW_GUEST_ADDRESS(80171458, 801713B8, 80171378) // __GX::SetTmemConfig -MKW_GUEST_ADDRESS(801717AC, 8017170C, 801716CC) // GX::SetTevIndirect -MKW_GUEST_ADDRESS(80171814, 80171774, 80171734) // GX::SetIndTexMtx -MKW_GUEST_ADDRESS(80171968, 801718C8, 80171888) // GX::SetIndTexCoordScale -MKW_GUEST_ADDRESS(80171A6C, 801719CC, 8017198C) // GX::SetIndTexOrder -MKW_GUEST_ADDRESS(80171B38, 80171A98, 80171A58) // GX::SetNumIndStages -MKW_GUEST_ADDRESS(80171B58, 80171AB8, 80171A78) // GX::SetTevDirect -MKW_GUEST_ADDRESS(80171BA0, 80171B00, 80171AC0) // GX::SetTevIndWarp -MKW_GUEST_ADDRESS(80171C28, 80171B88, 80171B48) // __GX::FlushTextureState -MKW_GUEST_ADDRESS(80171C4C, 80171BAC, 80171B6C) // GX::SetTevOp -MKW_GUEST_ADDRESS(80171CE0, 80171C40, 80171C00) // GX::SetTevColorIn -MKW_GUEST_ADDRESS(80171D20, 80171C80, 80171C40) // GX::SetTevAlphaIn -MKW_GUEST_ADDRESS(80171D60, 80171CC0, 80171C80) // GX::SetTevColorOp -MKW_GUEST_ADDRESS(80171DB8, 80171D18, 80171CD8) // GX::SetTevAlphaOp -MKW_GUEST_ADDRESS(80171E10, 80171D70, 80171D30) // GX::SetTevColor -MKW_GUEST_ADDRESS(80171E70, 80171DD0, 80171D90) // GX::SetTevColorS10 -MKW_GUEST_ADDRESS(80171ED4, 80171E34, 80171DF4) // GX::SetTevKColor -MKW_GUEST_ADDRESS(80171F30, 80171E90, 80171E50) // GX::SetTevKColorSel -MKW_GUEST_ADDRESS(80171F80, 80171EE0, 80171EA0) // GX::SetTevKAlphaSel -MKW_GUEST_ADDRESS(80171FD0, 80171F30, 80171EF0) // GX::SetTevSwapMode -MKW_GUEST_ADDRESS(8017200C, 80171F6C, 80171F2C) // GX::SetTevSwapModeTable -MKW_GUEST_ADDRESS(80172088, 80171FE8, 80171FA8) // GX::SetAlphaCompare -MKW_GUEST_ADDRESS(801720C0, 80172020, 80171FE0) // GX::SetZTexture -MKW_GUEST_ADDRESS(8017214C, 801720AC, 8017206C) // GX::SetTevOrder -MKW_GUEST_ADDRESS(801722A8, 80172208, 801721C8) // GX::SetNumTevStages -MKW_GUEST_ADDRESS(801722CC, 8017222C, 801721EC) // GX::SetFog -MKW_GUEST_ADDRESS(801724F8, 80172458, 80172418) // GX::InitFogAdjTable -MKW_GUEST_ADDRESS(8017277C, 801726DC, 8017269C) // GX::SetBlendMode -MKW_GUEST_ADDRESS(801727CC, 8017272C, 801726EC) // GX::SetColorUpdate -MKW_GUEST_ADDRESS(801727F8, 80172758, 80172718) // GX::SetAlphaUpdate -MKW_GUEST_ADDRESS(80172824, 80172784, 80172744) // GX::SetZMode -MKW_GUEST_ADDRESS(80172858, 801727B8, 80172778) // GX::SetZCompLoc -MKW_GUEST_ADDRESS(80172888, 801727E8, 801727A8) // GX::SetPixelFmt -MKW_GUEST_ADDRESS(80172930, 80172890, 80172850) // GX::SetDither -MKW_GUEST_ADDRESS(8017295C, 801728BC, 8017287C) // GX::SetDstAlpha -MKW_GUEST_ADDRESS(80172A30, 80172990, 80172950) // GX::DrawSphere -MKW_GUEST_ADDRESS(80172E00, 80172D60, 80172D20) // GX::BeginDisplayList -MKW_GUEST_ADDRESS(80172EB4, 80172E14, 80172DD4) // GX::EndDisplayList -MKW_GUEST_ADDRESS(80172F64, 80172EC4, 80172E84) // GX::CallDisplayList -MKW_GUEST_ADDRESS(80172FD8, 80172F38, 80172EF8) // __GX::SetProjection -MKW_GUEST_ADDRESS(8017301C, 80172F7C, 80172F3C) // GX::SetProjection -MKW_GUEST_ADDRESS(80173080, 80172FE0, 80172FA0) // GX::SetProjectionv -MKW_GUEST_ADDRESS(801730CC, 8017302C, 80172FEC) // GX::GetProjectionv -MKW_GUEST_ADDRESS(8017310C, 8017306C, 8017302C) // GX::LoadPosMtxImm -MKW_GUEST_ADDRESS(8017315C, 801730BC, 8017307C) // GX::LoadPosMtxIndx -MKW_GUEST_ADDRESS(80173188, 801730E8, 801730A8) // GX::LoadNrmMtxImm -MKW_GUEST_ADDRESS(801731E0, 80173140, 80173100) // GX::LoadNrmMtxIndx3x3 -MKW_GUEST_ADDRESS(80173214, 80173174, 80173134) // GX::SetCurrentMtx -MKW_GUEST_ADDRESS(80173234, 80173194, 80173154) // GX::LoadTexMtxImm -MKW_GUEST_ADDRESS(801732E8, 80173248, 80173208) // __GX::SetViewport -MKW_GUEST_ADDRESS(80173378, 801732D8, 80173298) // GX::SetViewportJitter -MKW_GUEST_ADDRESS(801733B4, 80173314, 801732D4) // GX::SetViewport -MKW_GUEST_ADDRESS(801733E0, 80173340, 80173300) // GX::GetViewportv -MKW_GUEST_ADDRESS(80173400, 80173360, 80173320) // GX::SetZScaleOffset -MKW_GUEST_ADDRESS(80173430, 80173390, 80173350) // GX::SetScissor -MKW_GUEST_ADDRESS(801734E0, 80173440, 80173400) // GX::SetScissorBoxOffset -MKW_GUEST_ADDRESS(8017351C, 8017347C, 8017343C) // GX::SetClipMode -MKW_GUEST_ADDRESS(80173544, 801734A4, 80173464) // __GX::SetMatrixIndex -MKW_GUEST_ADDRESS(801735CC, 8017352C, 801734EC) // GX::SetGPMetric -MKW_GUEST_ADDRESS(801736F4, 80173654, 80173614) // GX::SetGPMetric_switch -MKW_GUEST_ADDRESS(801736F8, 80173658, 80173618) // GX::SetGPMetric_caseD_0 -MKW_GUEST_ADDRESS(80173718, 80173678, 80173638) // GX::SetGPMetric_caseD_1 -MKW_GUEST_ADDRESS(80173738, 80173698, 80173658) // GX::SetGPMetric_caseD_2 -MKW_GUEST_ADDRESS(80173758, 801736B8, 80173678) // GX::SetGPMetric_caseD_3 -MKW_GUEST_ADDRESS(80173778, 801736D8, 80173698) // GX::SetGPMetric_caseD_4 -MKW_GUEST_ADDRESS(80173798, 801736F8, 801736B8) // GX::SetGPMetric_caseD_5 -MKW_GUEST_ADDRESS(801737B8, 80173718, 801736D8) // GX::SetGPMetric_caseD_6 -MKW_GUEST_ADDRESS(801737D8, 80173738, 801736F8) // GX::SetGPMetric_caseD_7 -MKW_GUEST_ADDRESS(801737F8, 80173758, 80173718) // GX::SetGPMetric_caseD_8 -MKW_GUEST_ADDRESS(80173818, 80173778, 80173738) // GX::SetGPMetric_caseD_9 -MKW_GUEST_ADDRESS(80173838, 80173798, 80173758) // GX::SetGPMetric_caseD_22 -MKW_GUEST_ADDRESS(80173858, 801737B8, 80173778) // GX::SetGPMetric_caseD_a -MKW_GUEST_ADDRESS(80173878, 801737D8, 80173798) // GX::SetGPMetric_caseD_b -MKW_GUEST_ADDRESS(80173894, 801737F4, 801737B4) // GX::SetGPMetric_caseD_c -MKW_GUEST_ADDRESS(801738B0, 80173810, 801737D0) // GX::SetGPMetric_caseD_d -MKW_GUEST_ADDRESS(801738CC, 8017382C, 801737EC) // GX::SetGPMetric_caseD_e -MKW_GUEST_ADDRESS(801738E8, 80173848, 80173808) // GX::SetGPMetric_caseD_f -MKW_GUEST_ADDRESS(80173904, 80173864, 80173824) // GX::SetGPMetric_caseD_10 -MKW_GUEST_ADDRESS(80173920, 80173880, 80173840) // GX::SetGPMetric_caseD_11 -MKW_GUEST_ADDRESS(8017393C, 8017389C, 8017385C) // GX::SetGPMetric_caseD_12 -MKW_GUEST_ADDRESS(80173958, 801738B8, 80173878) // GX::SetGPMetric_caseD_13 -MKW_GUEST_ADDRESS(80173974, 801738D4, 80173894) // GX::SetGPMetric_caseD_14 -MKW_GUEST_ADDRESS(80173990, 801738F0, 801738B0) // GX::SetGPMetric_caseD_15 -MKW_GUEST_ADDRESS(801739AC, 8017390C, 801738CC) // GX::SetGPMetric_caseD_16 -MKW_GUEST_ADDRESS(801739C8, 80173928, 801738E8) // GX::SetGPMetric_caseD_17 -MKW_GUEST_ADDRESS(801739E4, 80173944, 80173904) // GX::SetGPMetric_caseD_18 -MKW_GUEST_ADDRESS(80173A00, 80173960, 80173920) // GX::SetGPMetric_caseD_19 -MKW_GUEST_ADDRESS(80173A1C, 8017397C, 8017393C) // GX::SetGPMetric_caseD_1a -MKW_GUEST_ADDRESS(80173A38, 80173998, 80173958) // GX::SetGPMetric_caseD_1b -MKW_GUEST_ADDRESS(80173A54, 801739B4, 80173974) // GX::SetGPMetric_caseD_1c -MKW_GUEST_ADDRESS(80173A70, 801739D0, 80173990) // GX::SetGPMetric_caseD_1d -MKW_GUEST_ADDRESS(80173A8C, 801739EC, 801739AC) // GX::SetGPMetric_caseD_1e -MKW_GUEST_ADDRESS(80173AA8, 80173A08, 801739C8) // GX::SetGPMetric_caseD_1f -MKW_GUEST_ADDRESS(80173AC4, 80173A24, 801739E4) // GX::SetGPMetric_caseD_20 -MKW_GUEST_ADDRESS(80173AE0, 80173A40, 80173A00) // GX::SetGPMetric_caseD_21 -MKW_GUEST_ADDRESS(80173AF8, 80173A58, 80173A18) // GX::SetGPMetric_caseD_23 -MKW_GUEST_ADDRESS(80173B18, 80173A78, 80173A38) // GX::SetGPMetric_switch -MKW_GUEST_ADDRESS(80173B1C, 80173A7C, 80173A3C) // GX::SetGPMetric_caseD_0 -MKW_GUEST_ADDRESS(80173B38, 80173A98, 80173A58) // GX::SetGPMetric_caseD_1 -MKW_GUEST_ADDRESS(80173B54, 80173AB4, 80173A74) // GX::SetGPMetric_caseD_2 -MKW_GUEST_ADDRESS(80173B70, 80173AD0, 80173A90) // GX::SetGPMetric_caseD_3 -MKW_GUEST_ADDRESS(80173B8C, 80173AEC, 80173AAC) // GX::SetGPMetric_caseD_8 -MKW_GUEST_ADDRESS(80173BA8, 80173B08, 80173AC8) // GX::SetGPMetric_caseD_15 -MKW_GUEST_ADDRESS(80173BC4, 80173B24, 80173AE4) // GX::SetGPMetric_caseD_4 -MKW_GUEST_ADDRESS(80173BE0, 80173B40, 80173B00) // GX::SetGPMetric_caseD_5 -MKW_GUEST_ADDRESS(80173BFC, 80173B5C, 80173B1C) // GX::SetGPMetric_caseD_6 -MKW_GUEST_ADDRESS(80173C18, 80173B78, 80173B38) // GX::SetGPMetric_caseD_7 -MKW_GUEST_ADDRESS(80173C34, 80173B94, 80173B54) // GX::SetGPMetric_caseD_9 -MKW_GUEST_ADDRESS(80173C64, 80173BC4, 80173B84) // GX::SetGPMetric_caseD_a -MKW_GUEST_ADDRESS(80173C94, 80173BF4, 80173BB4) // GX::SetGPMetric_caseD_b -MKW_GUEST_ADDRESS(80173CC4, 80173C24, 80173BE4) // GX::SetGPMetric_caseD_c -MKW_GUEST_ADDRESS(80173CF4, 80173C54, 80173C14) // GX::SetGPMetric_caseD_d -MKW_GUEST_ADDRESS(80173D24, 80173C84, 80173C44) // GX::SetGPMetric_caseD_e -MKW_GUEST_ADDRESS(80173D54, 80173CB4, 80173C74) // GX::SetGPMetric_caseD_f -MKW_GUEST_ADDRESS(80173D84, 80173CE4, 80173CA4) // GX::SetGPMetric_caseD_10 -MKW_GUEST_ADDRESS(80173DB0, 80173D10, 80173CD0) // GX::SetGPMetric_caseD_11 -MKW_GUEST_ADDRESS(80173DC0, 80173D20, 80173CE0) // GX::SetGPMetric_caseD_12 -MKW_GUEST_ADDRESS(80173DD0, 80173D30, 80173CF0) // GX::SetGPMetric_caseD_13 -MKW_GUEST_ADDRESS(80173DE0, 80173D40, 80173D00) // GX::SetGPMetric_caseD_14 -MKW_GUEST_ADDRESS(80173DEC, 80173D4C, 80173D0C) // GX::SetGPMetric_caseD_16 -MKW_GUEST_ADDRESS(80173DF8, 80173D58, 80173D18) // GX::ClearGPMetric -MKW_GUEST_ADDRESS(80192F7C, 80192EDC, 80192E9C) // IPCInit -MKW_GUEST_ADDRESS(80193010, 80192F70, 80192F30) // IPCReadReg -MKW_GUEST_ADDRESS(80193020, 80192F80, 80192F40) // IPCWriteReg -MKW_GUEST_ADDRESS(80193040, 80192FA0, 80192F60) // IPCSetBufferLo -MKW_GUEST_ADDRESS(80193478, 801933D8, 80193398) // IPCCltInit -MKW_GUEST_ADDRESS(801937E0, 80193740, 80193700) // IOS::OpenAsync -MKW_GUEST_ADDRESS(801938F8, 80193858, 80193818) // IOS::Open -MKW_GUEST_ADDRESS(801938FC, 8019385C, 8019381C) -MKW_GUEST_ADDRESS(80193A18, 80193978, 80193938) // IOS::CloseAsync -MKW_GUEST_ADDRESS(80193AD8, 80193A38, 801939F8) // IOS::Close -MKW_GUEST_ADDRESS(80193B80, 80193AE0, 80193AA0) // IOS::ReadAsync -MKW_GUEST_ADDRESS(80193C80, 80193BE0, 80193BA0) // IOS::Read -MKW_GUEST_ADDRESS(80193D88, 80193CE8, 80193CA8) // IOS::WriteAsync -MKW_GUEST_ADDRESS(80193E88, 80193DE8, 80193DA8) // IOS::Write -MKW_GUEST_ADDRESS(80193F90, 80193EF0, 80193EB0) // IOS::SeekAsync -MKW_GUEST_ADDRESS(80194070, 80193FD0, 80193F90) // IOS::Seek -MKW_GUEST_ADDRESS(80194158, 801940B8, 80194078) // IOS::IoctlAsync -MKW_GUEST_ADDRESS(80194290, 801941F0, 801941B0) // IOS::Ioctl -MKW_GUEST_ADDRESS(801944FC, 8019445C, 8019441C) // IOS::IoctlvAsync -MKW_GUEST_ADDRESS(801945E0, 80194540, 80194500) // IOS::Ioctlv -MKW_GUEST_ADDRESS(801949B8, 80194918, 801948D8) // iosCreateHeap -MKW_GUEST_ADDRESS(8019B43C, 8019B39C, 8019B35C) // NAND::Create -MKW_GUEST_ADDRESS(8019B524, 8019B484, 8019B444) // NAND::Private::CreateAsync -MKW_GUEST_ADDRESS(8019B59C, 8019B4FC, 8019B4BC) // NAND::Delete -MKW_GUEST_ADDRESS(8019B6E4, 8019B644, 8019B604) // NAND::Private::DeleteAsync -MKW_GUEST_ADDRESS(8019B7A4, 8019B704, 8019B6C4) // NAND::Read -MKW_GUEST_ADDRESS(8019B80C, 8019B76C, 8019B72C) // NAND::ReadAsync -MKW_GUEST_ADDRESS(8019B884, 8019B7E4, 8019B7A4) // NAND::Write -MKW_GUEST_ADDRESS(8019B8EC, 8019B84C, 8019B80C) // NAND::WriteAsync -MKW_GUEST_ADDRESS(8019B964, 8019B8C4, 8019B884) // NAND::Seek -MKW_GUEST_ADDRESS(8019BA04, 8019B964, 8019B924) // NAND::SeekAsync -MKW_GUEST_ADDRESS(8019BBE0, 8019BB40, 8019BB00) // NAND::CreateDir -MKW_GUEST_ADDRESS(8019BCC8, 8019BC28, 8019BBE8) // NAND::Private::CreateDirAsync -MKW_GUEST_ADDRESS(8019BEE8, 8019BE48, 8019BE08) // NAND::Move -MKW_GUEST_ADDRESS(8019BF4C, 8019BEAC, 8019BE6C) // NAND::GetLength -MKW_GUEST_ADDRESS(8019C048, 8019BFA8, 8019BF68) // NAND::GetLengthAsync -MKW_GUEST_ADDRESS(8019C380, 8019C2E0, 8019C2A0) // NAND::GetStatus -MKW_GUEST_ADDRESS(8019C448, 8019C3A8, 8019C368) // NAND::Private::GetStatusAsync -MKW_GUEST_ADDRESS(8019C800, 8019C760, 8019C720) // NAND::Open -MKW_GUEST_ADDRESS(8019C918, 8019C878, 8019C838) // NAND::OpenAsync -MKW_GUEST_ADDRESS(8019C990, 8019C8F0, 8019C8B0) // NAND::Private::OpenAsync -MKW_GUEST_ADDRESS(8019CA80, 8019C9E0, 8019C9A0) // NAND::Close -MKW_GUEST_ADDRESS(8019CAEC, 8019CA4C, 8019CA0C) // NAND::CloseAsync -MKW_GUEST_ADDRESS(8019CB74, 8019CAD4, 8019CA94) // NAND::SafeOpen -MKW_GUEST_ADDRESS(8019CF28, 8019CE88, 8019CE48) // NAND::SafeClose -MKW_GUEST_ADDRESS(8019D104, 8019D064, 8019D024) // NAND::Private::SafeOpenAsync -MKW_GUEST_ADDRESS(8019D720, 8019D680, 8019D640) // NAND::SafeCloseAsync -MKW_GUEST_ADDRESS(8019E18C, 8019E0EC, 8019E0AC) // NAND::Init -MKW_GUEST_ADDRESS(8019E390, 8019E2F0, 8019E2B0) // NAND::GetCurrentDir -MKW_GUEST_ADDRESS(8019E770, 8019E6D0, 8019E690) // NAND::GetType -MKW_GUEST_ADDRESS(8019E7B4, 8019E714, 8019E6D4) // NAND::Private::GetTypeAsync -MKW_GUEST_ADDRESS(8019EAD0, 8019EA30, 8019E9F0) // NAND::Check -MKW_GUEST_ADDRESS(8019F33C, 8019F29C, 8019F25C) // OS::GetConsoleType -MKW_GUEST_ADDRESS(801A00E0, 801A0040, 801A0000) // OS::ExceptionInit -MKW_GUEST_ADDRESS(801A04A0, 801A0400, 801A03C0) // OS::__PSInit -MKW_GUEST_ADDRESS(801A0620, 801A0580, 801A0540) // InsertAlarm -MKW_GUEST_ADDRESS(801A0870, 801A07D0, 801A0790) // OS::SetAlarm -MKW_GUEST_ADDRESS(801A08E0, 801A0840, 801A0800) // OS::SetPeriodicAlarm -MKW_GUEST_ADDRESS(801A1138, 801A1098, 801A1058) // __AIClockInit -MKW_GUEST_ADDRESS(801A1358, 801A12B8, 801A1278) // OS::__InitAudioSystem -MKW_GUEST_ADDRESS(801A1520, 801A1480, 801A1440) // OS::__StopAudioSystem -MKW_GUEST_ADDRESS(801A15EC, 801A154C, 801A150C) // DCEnable -MKW_GUEST_ADDRESS(801A1600, 801A1560, 801A1520) // DCInvalidateRange -MKW_GUEST_ADDRESS(801A162C, 801A158C, 801A154C) // DCFlushRange -MKW_GUEST_ADDRESS(801A165C, 801A15BC, 801A157C) // DCStoreRange -MKW_GUEST_ADDRESS(801A168C, 801A15EC, 801A15AC) // DCFlushRangeNoSync -MKW_GUEST_ADDRESS(801A16B8, 801A1618, 801A15D8) // DCStoreRangeNoSync -MKW_GUEST_ADDRESS(801A16E4, 801A1644, 801A1604) // DCZeroRange -MKW_GUEST_ADDRESS(801A1710, 801A1670, 801A1630) // ICInvalidateRange -MKW_GUEST_ADDRESS(801A1744, 801A16A4, 801A1664) // ICFlashInvalidate -MKW_GUEST_ADDRESS(801A1754, 801A16B4, 801A1674) // ICEnable -MKW_GUEST_ADDRESS(801A1768, 801A16C8, 801A1688) // __LCEnable -MKW_GUEST_ADDRESS(801A1834, 801A1794, 801A1754) // LCEnable -MKW_GUEST_ADDRESS(801A186C, 801A17CC, 801A178C) // LCDisable -MKW_GUEST_ADDRESS(801A1894, 801A17F4, 801A17B4) // LCLoadBlocks -MKW_GUEST_ADDRESS(801A18B8, 801A1818, 801A17D8) // LCStoreBlocks -MKW_GUEST_ADDRESS(801A18DC, 801A183C, 801A17FC) // LCStoreData -MKW_GUEST_ADDRESS(801A197C, 801A18DC, 801A189C) // LCQueueLength -MKW_GUEST_ADDRESS(801A1988, 801A18E8, 801A18A8) // LCQueueWait -MKW_GUEST_ADDRESS(801A1AE4, 801A1A44, 801A1A04) // OS::__CacheInit -MKW_GUEST_ADDRESS(801A1E70, 801A1DD0, 801A1D90) // OS::SetCurrentContext -MKW_GUEST_ADDRESS(801A1ED8, 801A1E38, 801A1DF8) // OS::SaveContext -MKW_GUEST_ADDRESS(801A1F58, 801A1EB8, 801A1E78) // OS::LoadContext -MKW_GUEST_ADDRESS(801A2098, 801A1FF8, 801A1FB8) // OS::ClearContext -MKW_GUEST_ADDRESS(801A20BC, 801A201C, 801A1FDC) // OS::InitContext -MKW_GUEST_ADDRESS(801A25D0, 801A2530, 801A24F0) // OS::Report -MKW_GUEST_ADDRESS(801A2660, 801A25C0, 801A2580) // OS::Panic -MKW_GUEST_ADDRESS(801A4EC4, 801A4E24, 801A4DE4) // OS::Fatal -MKW_GUEST_ADDRESS(801A6000, 801A5F60, 801A5F20) -MKW_GUEST_ADDRESS(801A65AC, 801A650C, 801A64CC) // OS::DisableInterrupts -MKW_GUEST_ADDRESS(801A65C0, 801A6520, 801A64E0) // OS::EnableInterrupts -MKW_GUEST_ADDRESS(801A65D4, 801A6534, 801A64F4) // OS::RestoreInterrupts -MKW_GUEST_ADDRESS(801A65F8, 801A6558, 801A6518) // OS::__SetInterruptHandler -MKW_GUEST_ADDRESS(801A661C, 801A657C, 801A653C) // OS::__InterruptInit -MKW_GUEST_ADDRESS(801A66E0, 801A6640, 801A6600) // SetInterruptMask -MKW_GUEST_ADDRESS(801A693C, 801A689C, 801A685C) // OS::__MaskInterrupts -MKW_GUEST_ADDRESS(801A69BC, 801A691C, 801A68DC) // OS::__UnmaskInterrupts -MKW_GUEST_ADDRESS(801A7000, 801A6F60, 801A6F20) -MKW_GUEST_ADDRESS(801A72FC, 801A725C, 801A721C) // OS::InitMessageQueue -MKW_GUEST_ADDRESS(801A735C, 801A72BC, 801A727C) // OS::SendMessage -MKW_GUEST_ADDRESS(801A7424, 801A7384, 801A7344) // OS::ReceiveMessage -MKW_GUEST_ADDRESS(801A7500, 801A7460, 801A7420) // OS::JamMessage -MKW_GUEST_ADDRESS(801A7DFC, 801A7D5C, 801A7D1C) // OS::__InitMemoryProtection -MKW_GUEST_ADDRESS(801A7EE4, 801A7E44, 801A7E04) // OS::LockMutex -MKW_GUEST_ADDRESS(801A7FC0, 801A7F20, 801A7EE0) // OS::UnlockMutex -MKW_GUEST_ADDRESS(801A8088, 801A7FE8, 801A7FA8) // OS::__UnlockAllMutex -MKW_GUEST_ADDRESS(801A8A50, 801A89B0, 801A8970) // OS::GetResetCode -MKW_GUEST_ADDRESS(801A8A80, 801A89E0, 801A89A0) // OS::ResetSystem -MKW_GUEST_ADDRESS(801A961C, 801A957C, 801A953C) // OS::__ThreadInit -MKW_GUEST_ADDRESS(801A98B0, 801A9810, 801A97D0) // OS::GetCurrentThread -MKW_GUEST_ADDRESS(801A9C08, 801A9B68, 801A9B28) // SelectThread -MKW_GUEST_ADDRESS(801A9E84, 801A9DE4, 801A9DA4) // OS::CreateThread -MKW_GUEST_ADDRESS(801AA0F0, 801AA050, 801AA010) // RVL::OS::ExitThread -MKW_GUEST_ADDRESS(801AA1D4, 801AA134, 801AA0F4) // OS::CancelThread -MKW_GUEST_ADDRESS(801AA3AC, 801AA30C, 801AA2CC) // OS::JoinThread -MKW_GUEST_ADDRESS(801AA4EC, 801AA44C, 801AA40C) // OS::DetachThread -MKW_GUEST_ADDRESS(801AA58C, 801AA4EC, 801AA4AC) // OS::ResumeThread -MKW_GUEST_ADDRESS(801AA6A8, 801AA608, 801AA5C8) -MKW_GUEST_ADDRESS(801AA9B8, 801AA918, 801AA8D8) // OS::SleepThread -MKW_GUEST_ADDRESS(801AAAA4, 801AAA04, 801AA9C4) // OS::WakeupThread -MKW_GUEST_ADDRESS(801AACA8, 801AAC08, 801AABC8) // OS::SleepTicks -MKW_GUEST_ADDRESS(801AAD5C, 801AACBC, 801AAC7C) // OS::GetTime -MKW_GUEST_ADDRESS(801AAD7C, 801AACDC, 801AAC9C) // OS::__GetSystemTime -MKW_GUEST_ADDRESS(801AADE0, 801AAD40, 801AAD00) // OS::__TimeToSystemTime -MKW_GUEST_ADDRESS(801AB75C, 801AB6BC, 801AB67C) // OS::SetPowerCallback -MKW_GUEST_ADDRESS(801AB848, 801AB7A8, 801AB768) // OS::__InitSTM -MKW_GUEST_ADDRESS(801ABC0C, 801ABB6C, 801ABB2C) // OS::__DefaultPowerCallback -MKW_GUEST_ADDRESS(801AD1D4, 801AD134, 801AD0F4) // OS::CheckInstall -MKW_GUEST_ADDRESS(801AE4A0, 801AE400, 801AE3C0) // OS::IsTitleInstalled -MKW_GUEST_ADDRESS(801AE58C, 801AE4EC, 801AE4AC) // exit -MKW_GUEST_ADDRESS(801AF0DC, 801AF03C, 801AEFFC) // PAD::Reset -MKW_GUEST_ADDRESS(801AF1E4, 801AF144, 801AF104) // PAD::Recalibrate -MKW_GUEST_ADDRESS(801AF2F0, 801AF250, 801AF210) // PAD::Init -MKW_GUEST_ADDRESS(801AF44C, 801AF3AC, 801AF36C) // PAD::Read -MKW_GUEST_ADDRESS(801AF908, 801AF868, 801AF828) // PAD::ControlMotor -MKW_GUEST_ADDRESS(801B0220, 801B0180, 801B0140) // SCCheckStatus -MKW_GUEST_ADDRESS(801B1BE4, 801B1B44, 801B1B04) // SCGetAspectRatio -MKW_GUEST_ADDRESS(801B1CAC, 801B1C0C, 801B1BCC) // SCGetEuRgb60Mode -MKW_GUEST_ADDRESS(801B1ED0, 801B1E30, 801B1DF0) -MKW_GUEST_ADDRESS(801B1EDC, 801B1E3C, 801B1DFC) -MKW_GUEST_ADDRESS(801B1EE8, 801B1E48, 801B1E08) -MKW_GUEST_ADDRESS(801B1EF4, 801B1E54, 801B1E14) // SCSetBtCmpDevInfoArray -MKW_GUEST_ADDRESS(801B1F00, 801B1E60, 801B1E20) // SCGetBtDpdSensibility -MKW_GUEST_ADDRESS(801B1F68, 801B1EC8, 801B1E88) // SCGetWpadMotorMode -MKW_GUEST_ADDRESS(801B1FBC, 801B1F1C, 801B1EDC) // SCSetWpadMotorMode -MKW_GUEST_ADDRESS(801B1FC4, 801B1F24, 801B1EE4) // SCGetWpadSensorBarPosition -MKW_GUEST_ADDRESS(801B2018, 801B1F78, 801B1F38) // SCGetWpadSpeakerVolume -MKW_GUEST_ADDRESS(801B206C, 801B1FCC, 801B1F8C) // SCSetWpadSpeakerVolume -MKW_GUEST_ADDRESS(801B23A0, 801B2300, 801B22C0) // SCGetProductArea -MKW_GUEST_ADDRESS(801B2424, 801B2384, 801B2344) // SCGetProductCode -MKW_GUEST_ADDRESS(801B2460, 801B23C0, 801B2380) // SCGetProductSN -MKW_GUEST_ADDRESS(801B24C8, 801B2428, 801B23E8) // SCGetProductGameRegion -MKW_GUEST_ADDRESS(801B2DE0, 801B2D40, 801B2D00) // SIInit -MKW_GUEST_ADDRESS(801B3ACC, 801B3A2C, 801B39EC) // SISetSamplingRate -MKW_GUEST_ADDRESS(801B90F4, 801B9054, 801B9014) // VISetPreRetraceCallback -MKW_GUEST_ADDRESS(801B9138, 801B9098, 801B9058) // VISetPostRetraceCallback -MKW_GUEST_ADDRESS(801B9294, 801B91F4, 801B91B4) // __VIInit -MKW_GUEST_ADDRESS(801B94A4, 801B9404, 801B93C4) // VIInit -MKW_GUEST_ADDRESS(801B9934, 801B9894, 801B9854) // VIInit_caseD_0 -MKW_GUEST_ADDRESS(801B993C, 801B989C, 801B985C) // VIInit_caseD_1 -MKW_GUEST_ADDRESS(801B9944, 801B98A4, 801B9864) // VIInit_caseD_2 -MKW_GUEST_ADDRESS(801B99EC, 801B994C, 801B990C) // VIWaitForRetrace -MKW_GUEST_ADDRESS(801B9F6C, 801B9ECC, 801B9E8C) // VIConfigure -MKW_GUEST_ADDRESS(801BA9A4, 801BA904, 801BA8C4) // VIFlush -MKW_GUEST_ADDRESS(801BAAB8, 801BAA18, 801BA9D8) // VISetNextFrameBuffer -MKW_GUEST_ADDRESS(801BAB24, 801BAA84, 801BAA44) // VIGetNextFrameBuffer -MKW_GUEST_ADDRESS(801BAB2C, 801BAA8C, 801BAA4C) // VISetBlack -MKW_GUEST_ADDRESS(801BABA4, 801BAB04, 801BAAC4) // VIGetRetraceCount -MKW_GUEST_ADDRESS(801BABAC, 801BAB0C, 801BAACC) // VIGetNextField -MKW_GUEST_ADDRESS(801BAC48, 801BABA8, 801BAB68) // VIGetCurrentLine -MKW_GUEST_ADDRESS(801BAD38, 801BAC98, 801BAC58) // VIGetDTVStatus -MKW_GUEST_ADDRESS(801D8D30, 801D8C90, 801D8C50) // NHTTPStartup -MKW_GUEST_ADDRESS(801D9E94, 801D9DF4, 801D9DB4) // NHTTPi_GetSystemInfoP -MKW_GUEST_ADDRESS(8020FF9C, 8020FEFC, 8020FEBC) // EGG::AsyncDisplay::endRender -MKW_GUEST_ADDRESS(80218C2C, 80218B8C, 80218B4C) // EGG::Decomp::decodeSZS -MKW_GUEST_ADDRESS(80219FB4, 80219F14, 80219ED4) // EGG::Display::copyEFBtoXFB -MKW_GUEST_ADDRESS(8021B344, 8021B2A4, 8021B264) // EGG::DrawGX::SetVtxState_switch -MKW_GUEST_ADDRESS(8021B688, 8021B5E8, 8021B5A8) -MKW_GUEST_ADDRESS(8022E2BC, 8022DF38, 8022E1DC) // EGG::LightTexture::SetupTevFinish -MKW_GUEST_ADDRESS(8023BD38, 8023B9B4, 8023BC58) // EGG::ScnRenderer::CreatePath -MKW_GUEST_ADDRESS(8023E53C, 8023E1B8, 8023E45C) // EGG::Screen::SetTVModeDefault -MKW_GUEST_ADDRESS(80242D7C, 80241EC0, 80242C9C) // EGG::TaskThread::Run -MKW_GUEST_ADDRESS(8024373C, 80242880, 8024365C) // EGG::Thread::Run -MKW_GUEST_ADDRESS(80244DE0, 80244D40, 80244D00) -MKW_GUEST_ADDRESS(80244EA0, 80244E00, 80244DC0) -MKW_GUEST_ADDRESS(802574A0, 80257180, 80256E40) -MKW_GUEST_ADDRESS(802574E0, 802571C0, 80256E80) -MKW_GUEST_ADDRESS(80257520, 80257200, 80256EC0) -MKW_GUEST_ADDRESS(80257540, 80257220, 80256EE0) -MKW_GUEST_ADDRESS(8027F820, 8027B4E0, 8027F1C0) -MKW_GUEST_ADDRESS(8029CEB0, 80298B70, 8029C850) -MKW_GUEST_ADDRESS(8029CEF8, 80298BB8, 8029C898) -MKW_GUEST_ADDRESS(802A3EE8, 8029FB80, 802A3888) -MKW_GUEST_ADDRESS(802A3EF4, 8029FB8C, 802A3894) -MKW_GUEST_ADDRESS(802A3F0C, 8029FBA4, 802A38AC) -MKW_GUEST_ADDRESS(802F81A0, 802F3E20, 802F7B20) -MKW_GUEST_ADDRESS(802F8200, 802F3E80, 802F7B80) -MKW_GUEST_ADDRESS(80343230, 8033EEB0, 80342BB0) -MKW_GUEST_ADDRESS(803434E0, 8033F160, 80342E60) -MKW_GUEST_ADDRESS(80343740, 8033F3C0, 803430C0) -MKW_GUEST_ADDRESS(803437C0, 8033F440, 80343140) -MKW_GUEST_ADDRESS(80343DC0, 8033FA40, 80343740) -MKW_GUEST_ADDRESS(80343DE4, 8033FA64, 80343764) -MKW_GUEST_ADDRESS(80344090, 8033FD10, 80343A10) -MKW_GUEST_ADDRESS(80344094, 8033FD14, 80343A14) -MKW_GUEST_ADDRESS(80344098, 8033FD18, 80343A18) -MKW_GUEST_ADDRESS(803440A4, 8033FD24, 80343A24) -MKW_GUEST_ADDRESS(803440A8, 8033FD28, 80343A28) -MKW_GUEST_ADDRESS(803440AC, 8033FD2C, 80343A2C) -MKW_GUEST_ADDRESS(80344110, 8033FD90, 80343A90) -MKW_GUEST_ADDRESS(80344710, 80340390, 80344090) -MKW_GUEST_ADDRESS(80346D20, 803429A0, 803466A0) -MKW_GUEST_ADDRESS(80347130, 80342DB0, 80346AB0) -MKW_GUEST_ADDRESS(80347498, 80343118, 80346E18) -MKW_GUEST_ADDRESS(803477B0, 80343430, 80347130) -MKW_GUEST_ADDRESS(803478B0, 80343530, 80347230) -MKW_GUEST_ADDRESS(80350864, 8034C4E4, 803501E4) -MKW_GUEST_ADDRESS(80350866, 8034C4E6, 803501E6) -MKW_GUEST_ADDRESS(80350872, 8034C4F2, 803501F2) -MKW_GUEST_ADDRESS(8035087C, 8034C4FC, 803501FC) -MKW_GUEST_ADDRESS(80350890, 8034C510, 80350210) -MKW_GUEST_ADDRESS(80385800, 80381480, 80385180) -MKW_GUEST_ADDRESS(80385802, 80381482, 80385182) -MKW_GUEST_ADDRESS(80385804, 80381484, 80385184) -MKW_GUEST_ADDRESS(80385920, 803815A0, 803852A0) // dev/fs_fd -MKW_GUEST_ADDRESS(80385928, 803815A8, 803852A8) -MKW_GUEST_ADDRESS(80385AA8, 80381728, 80385428) -MKW_GUEST_ADDRESS(80385AE0, 80381760, 80385460) -MKW_GUEST_ADDRESS(80386000, 80381C80, 80385980) // SystemManager -MKW_GUEST_ADDRESS(80386298, 80381F18, 80385C18) -MKW_GUEST_ADDRESS(80386448, 803820C8, 80385DC8) -MKW_GUEST_ADDRESS(8038644C, 803820CC, 80385DCC) -MKW_GUEST_ADDRESS(8038647C, 803820FC, 80385DFC) -MKW_GUEST_ADDRESS(80386480, 80382100, 80385E00) -MKW_GUEST_ADDRESS(80386524, 803821A4, 80385EA4) -MKW_GUEST_ADDRESS(80386528, 803821A8, 80385EA8) -MKW_GUEST_ADDRESS(80386608, 80382288, 80385F88) -MKW_GUEST_ADDRESS(80386610, 80382290, 80385F90) -MKW_GUEST_ADDRESS(80386614, 80382294, 80385F94) -MKW_GUEST_ADDRESS(80386618, 80382298, 80385F98) -MKW_GUEST_ADDRESS(8038661C, 8038229C, 80385F9C) -MKW_GUEST_ADDRESS(80386620, 803822A0, 80385FA0) -MKW_GUEST_ADDRESS(80386624, 803822A4, 80385FA4) -MKW_GUEST_ADDRESS(80386664, 803822E4, 80385FE4) -MKW_GUEST_ADDRESS(80386668, 803822E8, 80385FE8) -MKW_GUEST_ADDRESS(80386670, 803822F0, 80385FF0) -MKW_GUEST_ADDRESS(8038667C, 803822FC, 80385FFC) -MKW_GUEST_ADDRESS(803866A0, 80382320, 80386020) -MKW_GUEST_ADDRESS(803866A8, 80382328, 80386028) -MKW_GUEST_ADDRESS(803866F0, 80382370, 80386070) -MKW_GUEST_ADDRESS(80386720, 803823A0, 803860A0) -MKW_GUEST_ADDRESS(80386724, 803823A4, 803860A4) -MKW_GUEST_ADDRESS(80386725, 803823A5, 803860A5) -MKW_GUEST_ADDRESS(80386770, 803823F0, 803860F0) -MKW_GUEST_ADDRESS(80386774, 803823F4, 803860F4) -MKW_GUEST_ADDRESS(8038677C, 803823FC, 803860FC) -MKW_GUEST_ADDRESS(80386780, 80382400, 80386100) -MKW_GUEST_ADDRESS(80386784, 80382404, 80386104) -MKW_GUEST_ADDRESS(803867B0, 80382430, 80386130) -MKW_GUEST_ADDRESS(803867B1, 80382431, 80386131) -MKW_GUEST_ADDRESS(803867C0, 80382440, 80386140) -MKW_GUEST_ADDRESS(803867C4, 80382444, 80386144) -MKW_GUEST_ADDRESS(803867D0, 80382450, 80386150) -MKW_GUEST_ADDRESS(803867D8, 80382458, 80386158) -MKW_GUEST_ADDRESS(803867EC, 8038246C, 8038616C) -MKW_GUEST_ADDRESS(803867F0, 80382470, 80386170) -MKW_GUEST_ADDRESS(80386848, 803824C8, 803861C8) -MKW_GUEST_ADDRESS(803868A0, 80382520, 80386220) -MKW_GUEST_ADDRESS(803868F8, 80382578, 80386278) -MKW_GUEST_ADDRESS(80386918, 80382598, 80386298) -MKW_GUEST_ADDRESS(8038691C, 8038259C, 8038629C) -MKW_GUEST_ADDRESS(80386920, 803825A0, 803862A0) -MKW_GUEST_ADDRESS(80386934, 803825B4, 803862B4) -MKW_GUEST_ADDRESS(80386938, 803825B8, 803862B8) -MKW_GUEST_ADDRESS(8038693C, 803825BC, 803862BC) -MKW_GUEST_ADDRESS(80386940, 803825C0, 803862C0) -MKW_GUEST_ADDRESS(80386948, 803825C8, 803862C8) -MKW_GUEST_ADDRESS(803869E0, 80382660, 80386360) -MKW_GUEST_ADDRESS(80386B38, 803827B8, 803864B8) -MKW_GUEST_ADDRESS(80386B44, 803827C4, 803864C4) -MKW_GUEST_ADDRESS(80386BA0, 80382820, 80386520) -MKW_GUEST_ADDRESS(80386BA8, 80382828, 80386528) -MKW_GUEST_ADDRESS(80386BB4, 80382834, 80386534) -MKW_GUEST_ADDRESS(80386BB8, 80382838, 80386538) -MKW_GUEST_ADDRESS(80386BC0, 80382840, 80386540) -MKW_GUEST_ADDRESS(80386BE4, 80382864, 80386564) -MKW_GUEST_ADDRESS(80386F14, 80382B94, 80386894) -MKW_GUEST_ADDRESS(80386F20, 80382BA0, 803868A0) -MKW_GUEST_ADDRESS(80386F24, 80382BA4, 803868A4) -MKW_GUEST_ADDRESS(80386F60, 80382BD8, 803868E0) -MKW_GUEST_ADDRESS(80388588, 80384208, 80387F08) -MKW_GUEST_ADDRESS(8038858C, 8038420C, 80387F0C) -MKW_GUEST_ADDRESS(803886C8, 80384348, 80388048) -MKW_GUEST_ADDRESS(80388B80, 80384800, 80388500) -MKW_GUEST_ADDRESS(80388BA0, 80384820, 80388520) -MKW_GUEST_ADDRESS(80388BC0, 80384840, 80388540) -MKW_GUEST_ADDRESS(80388BE0, 80384860, 80388560) -MKW_GUEST_ADDRESS(80388DD0, 80384A48, 80388750) -MKW_GUEST_ADDRESS(80388DE0, 80384A58, 80388760) -MKW_GUEST_ADDRESS(80388DF4, 80384A6C, 80388774) -MKW_GUEST_ADDRESS(80529D68, 805258F4, 805296E8) // MovieManager::PrepareAsync -MKW_GUEST_ADDRESS(80550CC0, 8054AD68, 80550640) // THP::PlayerOpen -MKW_GUEST_ADDRESS(80550F48, 8054AFF0, 805508C8) // THP::PlayerClose -MKW_GUEST_ADDRESS(80550F9C, 8054B044, 8055091C) // THP::PlayerCalcNeedMemory -MKW_GUEST_ADDRESS(80551054, 8054B0FC, 805509D4) // THP::PlayerSetBuffer -MKW_GUEST_ADDRESS(80551378, 8054B420, 80550CF8) // THP::PlayerPrepare -MKW_GUEST_ADDRESS(80551658, 8054B700, 80550FD8) // THP::PlayerStop -MKW_GUEST_ADDRESS(80551D38, 8054BDE0, 805516B8) // THP::PlayerGetVideoInfo -MKW_GUEST_ADDRESS(805529A8, 8054CA50, 80552328) // THP::VideoDecoder -MKW_GUEST_ADDRESS(80552A74, 8054CB1C, 805523F4) // THP::VideoDecoderOnMemory -MKW_GUEST_ADDRESS(8055531C, 8054F2FC, 80554C9C) // RelProlog -MKW_GUEST_ADDRESS(805653D0, 80561050, 80564D50) -MKW_GUEST_ADDRESS(80601C64, 805DD384, 806013D8) // Page::CheckActions -MKW_GUEST_ADDRESS(8061E348, 805EE30C, 8061DABC) // Pages::RegisterFriend::OnDigitClick -MKW_GUEST_ADDRESS(8061E3B4, 805EE378, 8061DB28) // Pages::RegisterFriend::OnBackSpaceClick -MKW_GUEST_ADDRESS(8061E804, 805EE7C8, 8061DF78) // Pages::RegisterFriend::GetRuntimeTypeInfo -MKW_GUEST_ADDRESS(8088F400, 8088AFD0, 8088EA6C) -MKW_GUEST_ADDRESS(8088F704, 8088B2D4, 8088ED70) -MKW_GUEST_ADDRESS(8088FDB8, 8088B960, 8088F418) -MKW_GUEST_ADDRESS(808B4C20, 808B0570, 808B3D80) -MKW_GUEST_ADDRESS(809BEBA0, 809BA3E0, 809BDC00) -MKW_GUEST_ADDRESS(809BEBA4, 809BA3E4, 809BDC04) -MKW_GUEST_ADDRESS(809BEBA5, 809BA3E5, 809BDC05) -MKW_GUEST_ADDRESS(809BEBA6, 809BA3E6, 809BDC06) -MKW_GUEST_ADDRESS(809BEBA7, 809BA3E7, 809BDC07) -MKW_GUEST_ADDRESS(809BECF0, 809BA530, 809BDD50) -MKW_GUEST_ADDRESS(809C1830, 809BD070, 809C0890) -MKW_GUEST_ADDRESS(809C183C, 809BD07C, 809C089C) -MKW_GUEST_ADDRESS(809C2898, 809BDC58, 809C18F8) diff --git a/runtime/include/guest_abi/guest_region.h b/runtime/include/guest_abi/guest_region.h index e21f955..1836717 100644 --- a/runtime/include/guest_abi/guest_region.h +++ b/runtime/include/guest_abi/guest_region.h @@ -7,8 +7,8 @@ // MKW_GADDR(801A9E84) address of that identity in the running region // MKW_GADDR_CT(801A9E84) same, as a constant expression; translated code only // -// A PAL address missing from guest_address_table.inc does not compile; regenerate the table -// with tools/region/gen_guest_address_table.py. +// guest_versions.inc maps PAL ranges to the other regions. A PAL address outside every range +// of a region does not compile. #include #include @@ -28,39 +28,72 @@ struct Row { constexpr uint32_t In(Id region) const { return address[static_cast(region)]; } }; -inline constexpr Row kRows[] = { -#define MKW_GUEST_ADDRESS(pal, ntscU, ntscJ) {{0x##pal##u, 0x##ntscU##u, 0x##ntscJ##u}}, -#include "guest_abi/guest_address_table.inc" -#undef MKW_GUEST_ADDRESS +struct Range { + Id region; + uint32_t first; + uint32_t last; + int32_t delta; }; -inline constexpr size_t kRowCount = sizeof(kRows) / sizeof(kRows[0]); -constexpr bool RowsAreSorted() { - for (size_t i = 1; i < kRowCount; ++i) { - if (kRows[i - 1].address[0] >= kRows[i].address[0]) { +inline constexpr Range kRanges[] = { +#define MKW_REGION_RANGE(region, first, last, delta) {Id::region, 0x##first##u, 0x##last##u, delta}, +#include "guest_abi/guest_versions.inc" +#undef MKW_REGION_RANGE +}; +inline constexpr size_t kRangeCount = sizeof(kRanges) / sizeof(kRanges[0]); + +constexpr bool Precedes(Id region, uint32_t address, const Range& range) { + return region < range.region || (region == range.region && address < range.first); +} + +constexpr bool RangesAreOrdered() { + for (size_t i = 0; i < kRangeCount; ++i) { + const Range& range = kRanges[i]; + if (range.region == Id::Pal || range.first > range.last) { + return false; + } + if (i != 0 && !Precedes(kRanges[i - 1].region, kRanges[i - 1].last, range)) { return false; } } return true; } -static_assert(RowsAreSorted(), "guest_address_table.inc must be sorted by PAL address without duplicates"); +static_assert(RangesAreOrdered(), "guest_versions.inc ranges must be sorted by region and PAL address without overlaps"); -constexpr const Row* Find(uint32_t pal) { +struct Mapping { + bool found; + uint32_t address; +}; + +constexpr Mapping Map(uint32_t pal, Id region) { + if (region == Id::Pal) { + return {true, pal}; + } size_t lo = 0; - size_t hi = kRowCount; + size_t hi = kRangeCount; while (lo < hi) { const size_t mid = lo + (hi - lo) / 2; - if (kRows[mid].address[0] < pal) { - lo = mid + 1; - } else { + if (Precedes(region, pal, kRanges[mid])) { hi = mid; + } else { + lo = mid + 1; } } - return lo < kRowCount && kRows[lo].address[0] == pal ? &kRows[lo] : nullptr; + if (lo == 0) { + return {false, 0}; + } + const Range& range = kRanges[lo - 1]; + if (range.region != region || pal > range.last) { + return {false, 0}; + } + return {true, static_cast(static_cast(pal) + range.delta)}; } -constexpr const Row& RowOf(uint32_t pal) { - return Find(pal) ? *Find(pal) : throw "PAL address missing from guest_abi/guest_address_table.inc"; +constexpr Row RowOf(uint32_t pal) { + const Mapping ntscU = Map(pal, Id::NtscU); + const Mapping ntscJ = Map(pal, Id::NtscJ); + return ntscU.found && ntscJ.found ? Row{{pal, ntscU.address, ntscJ.address}} + : throw "PAL address outside guest_abi/guest_versions.inc"; } } // namespace GuestRegion @@ -94,15 +127,11 @@ inline bool Is(uint32_t target) noexcept { // For hand-written registrations, which name the PAL address. inline uint32_t Translate(uint32_t pal) noexcept { - const Id region = Current(); - if (region == Id::Pal) { - return pal; - } - const Row* row = Find(pal); - if (!row) { + const Mapping mapping = Map(pal, Current()); + if (!mapping.found) { FatalUnknownAddress(pal); } - return row->In(region); + return mapping.address; } struct Facts { diff --git a/runtime/include/guest_abi/guest_versions.inc b/runtime/include/guest_abi/guest_versions.inc new file mode 100644 index 0000000..8ea9860 --- /dev/null +++ b/runtime/include/guest_abi/guest_versions.inc @@ -0,0 +1,416 @@ +// PAL address ranges -> address in each other region, in the style of Retro Rewind's +// versions.txt: MKW_REGION_RANGE(region, first PAL, last PAL (inclusive), delta). +// PAL maps to itself. Code ranges come from mkw-sp's port.py chunk table (MIT, Pablo Stebler), +// data ranges from Retro Rewind's versions.txt plus the verified data_addresses.txt anchors. +// An address outside every range has no known counterpart and fails to compile. + +MKW_REGION_RANGE(NtscU, 80000000, 8000802F, +0x0) +MKW_REGION_RANGE(NtscU, 8000808C, 8000ADBB, -0x40) +MKW_REGION_RANGE(NtscU, 8000AF24, 8000B6B3, -0xA0) +MKW_REGION_RANGE(NtscU, 8000B6B4, 8000C173, +0x15994) +MKW_REGION_RANGE(NtscU, 8000C174, 80021BA7, -0xB60) +MKW_REGION_RANGE(NtscU, 80021BA8, 80225F1B, -0xA0) +MKW_REGION_RANGE(NtscU, 802261F8, 802402DF, -0x384) +MKW_REGION_RANGE(NtscU, 802402E0, 80240E17, +0x3F1C) +MKW_REGION_RANGE(NtscU, 80240E18, 80244DD3, -0xEBC) +MKW_REGION_RANGE(NtscU, 80244DDA, 80244EBF, -0xA0) +MKW_REGION_RANGE(NtscU, 80244EC0, 80244ECF, -0x80) +MKW_REGION_RANGE(NtscU, 802572BF, 802575DF, -0x320) +MKW_REGION_RANGE(NtscU, 80257E64, 80258184, -0x320) +MKW_REGION_RANGE(NtscU, 80276054, 8029CEFB, -0x4340) +MKW_REGION_RANGE(NtscU, 802A3D60, 802A407F, -0x4368) +MKW_REGION_RANGE(NtscU, 802A4080, 80386F27, -0x4380) +MKW_REGION_RANGE(NtscU, 80386F48, 80386F8F, -0x4388) +MKW_REGION_RANGE(NtscU, 80386FA0, 80388BE3, -0x4380) +MKW_REGION_RANGE(NtscU, 80388DD0, 80388DF7, -0x4388) +MKW_REGION_RANGE(NtscU, 80389140, 8038917B, -0x4380) +MKW_REGION_RANGE(NtscU, 80399200, 80399400, -0x4380) +MKW_REGION_RANGE(NtscU, 805103B4, 80510A8F, -0x4380) +MKW_REGION_RANGE(NtscU, 80510B84, 8052D297, -0x4474) +MKW_REGION_RANGE(NtscU, 8052D298, 8052D96B, +0x22568) +MKW_REGION_RANGE(NtscU, 8052D96C, 8053D97B, -0x4B48) +MKW_REGION_RANGE(NtscU, 8053D97C, 8053E36F, +0x12558) +MKW_REGION_RANGE(NtscU, 8053E370, 8054FB2B, -0x553C) +MKW_REGION_RANGE(NtscU, 8054FB2C, 80550547, +0xD9C) +MKW_REGION_RANGE(NtscU, 80550548, 805537CB, -0x5F58) +MKW_REGION_RANGE(NtscU, 80553894, 8055572B, -0x6020) +MKW_REGION_RANGE(NtscU, 8055572C, 8056AB6B, -0x4380) +MKW_REGION_RANGE(NtscU, 8056AB6C, 8056B63B, +0x4357C) +MKW_REGION_RANGE(NtscU, 8056B63C, 8057402F, -0x4E50) +MKW_REGION_RANGE(NtscU, 80574030, 805758AB, +0x3AB88) +MKW_REGION_RANGE(NtscU, 80575A44, 80583F2B, -0x6864) +MKW_REGION_RANGE(NtscU, 80583F2C, 8059B5A3, -0x6824) +MKW_REGION_RANGE(NtscU, 8059B5A4, 8059EAA3, +0x14FE8) +MKW_REGION_RANGE(NtscU, 8059EAA4, 805A0557, -0x9D24) +MKW_REGION_RANGE(NtscU, 805A068C, 805A1477, +0x1343C) +MKW_REGION_RANGE(NtscU, 805A1488, 805A1863, +0x1342C) +MKW_REGION_RANGE(NtscU, 805A1864, 805A9EDB, -0xB038) +MKW_REGION_RANGE(NtscU, 805A9EDC, 805AB573, -0xB030) +MKW_REGION_RANGE(NtscU, 805AB574, 805ABC8F, -0xAF70) +MKW_REGION_RANGE(NtscU, 805ABC90, 805ADD97, -0xAF68) +MKW_REGION_RANGE(NtscU, 805ADD98, 805B900F, -0xAF28) +MKW_REGION_RANGE(NtscU, 805B9010, 805B92FF, -0x4380) +MKW_REGION_RANGE(NtscU, 805B9300, 805BAB3F, +0x664F4) +MKW_REGION_RANGE(NtscU, 805BAB40, 805BB2B7, -0x5BC0) +MKW_REGION_RANGE(NtscU, 805BB2B8, 805BD2D7, +0x65D7C) +MKW_REGION_RANGE(NtscU, 805BD2D8, 805BD2E3, -0x697C) +MKW_REGION_RANGE(NtscU, 805BD2E4, 805BD39B, +0x65D70) +MKW_REGION_RANGE(NtscU, 805BD39C, 805BE5FF, -0x7CA4) +MKW_REGION_RANGE(NtscU, 805BE600, 805BE61B, -0x7C98) +MKW_REGION_RANGE(NtscU, 805BE66C, 805BE7F3, +0x64AA0) +MKW_REGION_RANGE(NtscU, 805BE7F4, 805BE84B, -0x7124) +MKW_REGION_RANGE(NtscU, 805BE84C, 805BED67, +0x64A48) +MKW_REGION_RANGE(NtscU, 805BED68, 805BED73, -0x7948) +MKW_REGION_RANGE(NtscU, 805BED74, 805BF2D7, +0x64A3C) +MKW_REGION_RANGE(NtscU, 805BF2D8, 805BF2DB, -0x613C) +MKW_REGION_RANGE(NtscU, 805BF3CC, 805BFE1B, -0x89FC) +MKW_REGION_RANGE(NtscU, 805BFE1C, 805C00BF, -0x89F0) +MKW_REGION_RANGE(NtscU, 805C00C0, 805C1B33, -0x8998) +MKW_REGION_RANGE(NtscU, 805C1B34, 805C35F7, -0x8994) +MKW_REGION_RANGE(NtscU, 805C35F8, 805C3BCB, +0x60810) +MKW_REGION_RANGE(NtscU, 805C3BCC, 805C4767, -0x8F68) +MKW_REGION_RANGE(NtscU, 805C4768, 805C579B, +0x5FC74) +MKW_REGION_RANGE(NtscU, 805C57B0, 805CADDB, -0x9FB0) +MKW_REGION_RANGE(NtscU, 805CADDC, 805CC0A7, +0x5A648) +MKW_REGION_RANGE(NtscU, 805CC1B4, 805CD94B, +0x5A5A4) +MKW_REGION_RANGE(NtscU, 805CD94C, 805D1887, -0xCB20) +MKW_REGION_RANGE(NtscU, 805D1888, 805D1E83, +0x56668) +MKW_REGION_RANGE(NtscU, 805D1E84, 805D7F77, -0xD11C) +MKW_REGION_RANGE(NtscU, 805D7F78, 805DBFDB, +0x50574) +MKW_REGION_RANGE(NtscU, 805DBFDC, 805DC033, +0x2A620) +MKW_REGION_RANGE(NtscU, 805DC034, 805DE837, +0x5051C) +MKW_REGION_RANGE(NtscU, 805DE838, 805DE843, +0x5C00) +MKW_REGION_RANGE(NtscU, 805DE844, 805E0C37, +0x50510) +MKW_REGION_RANGE(NtscU, 805E0C38, 805E6B4F, -0x15DDC) +MKW_REGION_RANGE(NtscU, 805E6B50, 805E745F, +0x4A5F8) +MKW_REGION_RANGE(NtscU, 805E7460, 805EA77F, -0x166EC) +MKW_REGION_RANGE(NtscU, 805EA780, 805EEB67, +0x472D8) +MKW_REGION_RANGE(NtscU, 805EEB68, 805F2D23, -0x1AAD4) +MKW_REGION_RANGE(NtscU, 805F2D24, 805F8B33, +0x4311C) +MKW_REGION_RANGE(NtscU, 805F8B34, 805FB5BB, -0x208E4) +MKW_REGION_RANGE(NtscU, 805FB5BC, 805FB81F, +0x40694) +MKW_REGION_RANGE(NtscU, 805FB820, 805FD517, -0x20B48) +MKW_REGION_RANGE(NtscU, 805FD518, 806012AF, +0x3E99C) +MKW_REGION_RANGE(NtscU, 806012B0, 80608D17, -0x248E0) +MKW_REGION_RANGE(NtscU, 80608D18, 8060A72B, -0x248D4) +MKW_REGION_RANGE(NtscU, 8060A72C, 8061186B, +0x35520) +MKW_REGION_RANGE(NtscU, 8061186C, 80616843, -0x2BA14) +MKW_REGION_RANGE(NtscU, 80616844, 8061AE6B, +0x30548) +MKW_REGION_RANGE(NtscU, 8061AE6C, 8061E897, -0x3003C) +MKW_REGION_RANGE(NtscU, 8061E898, 8061F6E7, +0x2CB1C) +MKW_REGION_RANGE(NtscU, 8061F6E8, 80620CB3, -0x30E8C) +MKW_REGION_RANGE(NtscU, 80620D7C, 80634F47, -0x30EB4) +MKW_REGION_RANGE(NtscU, 80634F48, 80637493, -0x30E98) +MKW_REGION_RANGE(NtscU, 80637494, 80637513, -0x30DF0) +MKW_REGION_RANGE(NtscU, 80637514, 80637A2F, +0x14CF0) +MKW_REGION_RANGE(NtscU, 80637AC0, 8063BCF7, -0x313A0) +MKW_REGION_RANGE(NtscU, 8063BE40, 806453E3, -0x31420) +MKW_REGION_RANGE(NtscU, 806453E4, 806467D3, +0x73A8) +MKW_REGION_RANGE(NtscU, 806467D4, 8064A3F3, -0x32810) +MKW_REGION_RANGE(NtscU, 8064A3F4, 8064AEE3, +0x3788) +MKW_REGION_RANGE(NtscU, 8064AEF8, 80651BEB, -0x33314) +MKW_REGION_RANGE(NtscU, 80651BEC, 806522FF, -0x3580) +MKW_REGION_RANGE(NtscU, 80652300, 80653207, -0x33A14) +MKW_REGION_RANGE(NtscU, 80653208, 8065B353, -0x4488) +MKW_REGION_RANGE(NtscU, 8065B4E8, 8065C0EB, -0x461C) +MKW_REGION_RANGE(NtscU, 8065C0EC, 8065FA13, +0xC88) +MKW_REGION_RANGE(NtscU, 8065FA4C, 8065FE4B, -0x7F7C) +MKW_REGION_RANGE(NtscU, 8065FE4C, 80662777, -0x7F3C) +MKW_REGION_RANGE(NtscU, 80662778, 80663193, -0x20E4) +MKW_REGION_RANGE(NtscU, 80663194, 80665537, -0x8958) +MKW_REGION_RANGE(NtscU, 80665538, 80668813, +0xDC50) +MKW_REGION_RANGE(NtscU, 80668814, 8067906B, -0x7764) +MKW_REGION_RANGE(NtscU, 8067906C, 8067937F, -0x2C08) +MKW_REGION_RANGE(NtscU, 80679380, 8067ABFF, -0x7A78) +MKW_REGION_RANGE(NtscU, 8067AC00, 806BF4C7, -0x4488) +MKW_REGION_RANGE(NtscU, 806BF4C8, 806BFB13, +0x22BE0) +MKW_REGION_RANGE(NtscU, 806BFB14, 806C050B, -0x4AD4) +MKW_REGION_RANGE(NtscU, 806C050C, 806C35A7, +0x221E8) +MKW_REGION_RANGE(NtscU, 806C35A8, 806C3AA3, -0x7B70) +MKW_REGION_RANGE(NtscU, 806C3AA4, 806C4ED3, +0x21CEC) +MKW_REGION_RANGE(NtscU, 806C4EF0, 806C63A7, +0x21CD0) +MKW_REGION_RANGE(NtscU, 806C63B0, 806C6B43, +0x21CC8) +MKW_REGION_RANGE(NtscU, 806C6B44, 806CCE8F, -0xABF4) +MKW_REGION_RANGE(NtscU, 806CCE90, 806CE81F, +0x1B97C) +MKW_REGION_RANGE(NtscU, 806CE828, 806D02BB, -0xC58C) +MKW_REGION_RANGE(NtscU, 806D02BC, 806D28F3, +0x19EE0) +MKW_REGION_RANGE(NtscU, 806D2908, 806D5C5B, -0xEBD0) +MKW_REGION_RANGE(NtscU, 806D5C60, 806D5ED7, +0x16B74) +MKW_REGION_RANGE(NtscU, 806D5ED8, 806DA913, -0xEE40) +MKW_REGION_RANGE(NtscU, 806DA914, 806DB183, +0x12144) +MKW_REGION_RANGE(NtscU, 806DB184, 806DDA83, -0xF6B0) +MKW_REGION_RANGE(NtscU, 806DDA84, 806DEB3F, +0xF844) +MKW_REGION_RANGE(NtscU, 806DEB40, 806DF7CF, -0x1076C) +MKW_REGION_RANGE(NtscU, 806DF7D0, 806DFD13, +0xEBB4) +MKW_REGION_RANGE(NtscU, 806DFD14, 806E3A8B, -0x10CB0) +MKW_REGION_RANGE(NtscU, 806E3A8C, 806E3E1F, +0xAE3C) +MKW_REGION_RANGE(NtscU, 806E3E20, 806E95AF, -0x11044) +MKW_REGION_RANGE(NtscU, 806E95B0, 806EC7BF, +0x56AC) +MKW_REGION_RANGE(NtscU, 806EC7C0, 806ED53B, -0x1425C) +MKW_REGION_RANGE(NtscU, 806ED53C, 806F62FB, -0x14254) +MKW_REGION_RANGE(NtscU, 806F62FC, 806F7697, -0x4488) +MKW_REGION_RANGE(NtscU, 806F77C4, 806F7A53, +0x1C2B4) +MKW_REGION_RANGE(NtscU, 806F7AA8, 806F821F, +0x1C260) +MKW_REGION_RANGE(NtscU, 806F8220, 806F8933, -0x5010) +MKW_REGION_RANGE(NtscU, 806F8934, 806FA3FB, -0x4FBC) +MKW_REGION_RANGE(NtscU, 806FA3FC, 806FE23F, -0x4F68) +MKW_REGION_RANGE(NtscU, 806FE240, 806FE9DF, -0x4F10) +MKW_REGION_RANGE(NtscU, 806FE9E0, 807001A3, +0x15AA0) +MKW_REGION_RANGE(NtscU, 80700230, 80700473, +0x15A14) +MKW_REGION_RANGE(NtscU, 80700474, 8070E7B7, -0x69A4) +MKW_REGION_RANGE(NtscU, 8070E7B8, 8070F8B7, +0x76D0) +MKW_REGION_RANGE(NtscU, 8070F8B8, 807179C3, -0x7AA4) +MKW_REGION_RANGE(NtscU, 807179C4, 80717E33, -0x7A18) +MKW_REGION_RANGE(NtscU, 80717E34, 807182E7, -0xEAC) +MKW_REGION_RANGE(NtscU, 807182E8, 8071B86B, -0x7ECC) +MKW_REGION_RANGE(NtscU, 8071B86C, 80726573, -0x4430) +MKW_REGION_RANGE(NtscU, 80726574, 8072820B, +0x16068) +MKW_REGION_RANGE(NtscU, 8072821C, 807285C7, +0x16058) +MKW_REGION_RANGE(NtscU, 807285CC, 80729337, +0x16054) +MKW_REGION_RANGE(NtscU, 80729350, 80729B87, -0x720C) +MKW_REGION_RANGE(NtscU, 80729B88, 8072A893, -0x7204) +MKW_REGION_RANGE(NtscU, 8072A894, 8072B95B, -0x71FC) +MKW_REGION_RANGE(NtscU, 8072B95C, 8072DE63, -0x71EC) +MKW_REGION_RANGE(NtscU, 8072DFCC, 8072FF5F, +0x113C4) +MKW_REGION_RANGE(NtscU, 8072FF78, 80730197, +0x113AC) +MKW_REGION_RANGE(NtscU, 80730198, 80730A7F, -0x93B0) +MKW_REGION_RANGE(NtscU, 80730B40, 8073195F, +0x10A04) +MKW_REGION_RANGE(NtscU, 80731960, 80735947, -0xA1B8) +MKW_REGION_RANGE(NtscU, 80735948, 80738DB7, +0xCA1C) +MKW_REGION_RANGE(NtscU, 80738DB8, 8073C54B, -0xD628) +MKW_REGION_RANGE(NtscU, 8073C54C, 8073EDEF, +0x9288) +MKW_REGION_RANGE(NtscU, 8073EDF0, 8074C4A7, -0xFECC) +MKW_REGION_RANGE(NtscU, 8074C4A8, 8074D5B7, +0x20A04) +MKW_REGION_RANGE(NtscU, 8074D5B8, 807519C7, -0x5540) +MKW_REGION_RANGE(NtscU, 807519C8, 80754103, +0x1C5F4) +MKW_REGION_RANGE(NtscU, 80754104, 80758BDB, -0x7C7C) +MKW_REGION_RANGE(NtscU, 80758BDC, 8075DB23, +0x17B1C) +MKW_REGION_RANGE(NtscU, 8075DB3C, 8075E78B, -0xCBDC) +MKW_REGION_RANGE(NtscU, 8075E78C, 8075EAFB, +0x16ECC) +MKW_REGION_RANGE(NtscU, 8075EAFC, 80765C93, -0xCF4C) +MKW_REGION_RANGE(NtscU, 80765C94, 807678F3, +0xFD34) +MKW_REGION_RANGE(NtscU, 807678F4, 80768D1F, -0xEBAC) +MKW_REGION_RANGE(NtscU, 80768D20, 807693EB, +0xE908) +MKW_REGION_RANGE(NtscU, 8076960C, 8076C85B, +0xE85C) +MKW_REGION_RANGE(NtscU, 8076C85C, 8076EBDB, -0x126E8) +MKW_REGION_RANGE(NtscU, 8076EBE0, 8076F2DB, +0xC4D8) +MKW_REGION_RANGE(NtscU, 8076F2DC, 807726C3, -0x12DE8) +MKW_REGION_RANGE(NtscU, 80772704, 80773C13, +0x90B4) +MKW_REGION_RANGE(NtscU, 80773C1C, 8077439B, -0x14340) +MKW_REGION_RANGE(NtscU, 807743A0, 807787EF, -0x14294) +MKW_REGION_RANGE(NtscU, 807787F0, 8077902B, +0x4520) +MKW_REGION_RANGE(NtscU, 8077902C, 8077CE87, -0x14AD0) +MKW_REGION_RANGE(NtscU, 8077CEC8, 8077DF23, +0x684) +MKW_REGION_RANGE(NtscU, 8077DF24, 807829D7, -0x15B2C) +MKW_REGION_RANGE(NtscU, 807829D8, 80787D83, -0x4430) +MKW_REGION_RANGE(NtscU, 80787D84, 8078C95F, +0x48598) +MKW_REGION_RANGE(NtscU, 8078C960, 807A81B3, -0x900C) +MKW_REGION_RANGE(NtscU, 807A81B4, 807A9D6F, +0x2CDC0) +MKW_REGION_RANGE(NtscU, 807A9E50, 807A9E53, +0x2CCAC) +MKW_REGION_RANGE(NtscU, 807A9EB8, 807AF13F, -0xACA8) +MKW_REGION_RANGE(NtscU, 807AF140, 807B2EF7, +0x27A54) +MKW_REGION_RANGE(NtscU, 807B2EF8, 807D976B, -0xEA60) +MKW_REGION_RANGE(NtscU, 807D976C, 807D9B7F, +0x11E0) +MKW_REGION_RANGE(NtscU, 807D9B98, 807DA5BF, -0xEE8C) +MKW_REGION_RANGE(NtscU, 807DA5C0, 807DBCCB, +0x7B8) +MKW_REGION_RANGE(NtscU, 807DBCCC, 807DC8C7, -0x10598) +MKW_REGION_RANGE(NtscU, 807DC950, 807E093B, -0x10620) +MKW_REGION_RANGE(NtscU, 807E093C, 807E251F, +0x5BDB4) +MKW_REGION_RANGE(NtscU, 807E259C, 807E560F, -0x6090) +MKW_REGION_RANGE(NtscU, 807E5654, 807E6413, -0x6070) +MKW_REGION_RANGE(NtscU, 807E6414, 807E9C43, +0x57F28) +MKW_REGION_RANGE(NtscU, 807E9C50, 807EDD97, -0x98AC) +MKW_REGION_RANGE(NtscU, 807EDD98, 807EE23B, +0x53DD4) +MKW_REGION_RANGE(NtscU, 807EE250, 807EE467, -0x9D64) +MKW_REGION_RANGE(NtscU, 807EE474, 807EEA13, +0x53B9C) +MKW_REGION_RANGE(NtscU, 807EEA14, 807EF9F3, -0xA310) +MKW_REGION_RANGE(NtscU, 807EFD0C, 807F76EB, -0xA628) +MKW_REGION_RANGE(NtscU, 807F76EC, 807F7BA3, +0x4B1FC) +MKW_REGION_RANGE(NtscU, 807F7BC4, 807F890B, -0xAB00) +MKW_REGION_RANGE(NtscU, 807F8968, 807F927F, +0x4A438) +MKW_REGION_RANGE(NtscU, 807F9280, 807F9387, -0xB3F0) +MKW_REGION_RANGE(NtscU, 807F9580, 807FAB57, +0x4A320) +MKW_REGION_RANGE(NtscU, 807FAB58, 807FEB67, -0xCBC0) +MKW_REGION_RANGE(NtscU, 807FEB68, 807FFADF, +0x46310) +MKW_REGION_RANGE(NtscU, 807FFB20, 80805A0B, -0xDB78) +MKW_REGION_RANGE(NtscU, 80805A0C, 8080761B, +0x403E4) +MKW_REGION_RANGE(NtscU, 8080761C, 80809447, -0xF748) +MKW_REGION_RANGE(NtscU, 80809448, 8080AD1F, +0x3E5B8) +MKW_REGION_RANGE(NtscU, 8080AD20, 80811E47, -0x11020) +MKW_REGION_RANGE(NtscU, 80811E48, 80813BD3, +0x37490) +MKW_REGION_RANGE(NtscU, 80813BD4, 8081E283, -0x12DAC) +MKW_REGION_RANGE(NtscU, 8081E284, 8081EFEB, +0x2CDE0) +MKW_REGION_RANGE(NtscU, 8081EFEC, 8082E53F, -0x13B14) +MKW_REGION_RANGE(NtscU, 8082E540, 8082E853, +0x1D88C) +MKW_REGION_RANGE(NtscU, 8082E854, 8082F407, -0x13E28) +MKW_REGION_RANGE(NtscU, 8082F408, 8083349F, +0x1CCD8) +MKW_REGION_RANGE(NtscU, 808334E0, 80833AFF, -0x17F00) +MKW_REGION_RANGE(NtscU, 80833B00, 80838E5F, -0x17EF8) +MKW_REGION_RANGE(NtscU, 80838E60, 8083B0CB, +0x17358) +MKW_REGION_RANGE(NtscU, 8083B0CC, 8083CB43, -0x1A178) +MKW_REGION_RANGE(NtscU, 8083CB44, 8083D42B, +0x158E0) +MKW_REGION_RANGE(NtscU, 8083D42C, 8084233F, -0x1AA60) +MKW_REGION_RANGE(NtscU, 80842340, 808447AB, +0x109CC) +MKW_REGION_RANGE(NtscU, 808447AC, 8084A99F, -0x1CED8) +MKW_REGION_RANGE(NtscU, 8084A9A0, 8084D0DB, +0xA7E4) +MKW_REGION_RANGE(NtscU, 8084D0DC, 80851D2B, -0x1F614) +MKW_REGION_RANGE(NtscU, 80851D38, 80852C5F, +0x5B88) +MKW_REGION_RANGE(NtscU, 80852C60, 80853CA3, -0x20548) +MKW_REGION_RANGE(NtscU, 80853CA4, 808551EB, +0x4B50) +MKW_REGION_RANGE(NtscU, 808551EC, 8085C3CB, -0x21A90) +MKW_REGION_RANGE(NtscU, 8085C3CC, 8085E673, -0x2690) +MKW_REGION_RANGE(NtscU, 8085E674, 8085F0AB, -0x23D24) +MKW_REGION_RANGE(NtscU, 8085F0AC, 8085FFD3, -0x30C8) +MKW_REGION_RANGE(NtscU, 8085FFD4, 80860F2B, -0x24C4C) +MKW_REGION_RANGE(NtscU, 80860F2C, 80862E23, -0x4020) +MKW_REGION_RANGE(NtscU, 80863234, 8086708B, -0x4430) +MKW_REGION_RANGE(NtscU, 8086708C, 808676DF, -0x2354) +MKW_REGION_RANGE(NtscU, 808676E0, 808697BB, -0x4A84) +MKW_REGION_RANGE(NtscU, 808697BC, 8086A253, -0x4430) +MKW_REGION_RANGE(NtscU, 8086A254, 8086C097, +0xC4A0) +MKW_REGION_RANGE(NtscU, 8086C108, 8086C987, +0xC430) +MKW_REGION_RANGE(NtscU, 8086CA40, 80872CA3, +0xC378) +MKW_REGION_RANGE(NtscU, 80872CA4, 808739AF, -0xCE80) +MKW_REGION_RANGE(NtscU, 808739B0, 80875453, -0xCDC8) +MKW_REGION_RANGE(NtscU, 80875454, 8088344B, -0xCD58) +MKW_REGION_RANGE(NtscU, 8088344C, 8088F70F, -0x4430) +MKW_REGION_RANGE(NtscU, 8088FDB8, 8088FDBB, -0x4458) +MKW_REGION_RANGE(NtscU, 80890030, 80890215, -0x4470) +MKW_REGION_RANGE(NtscU, 80890490, 80890977, -0x4578) +MKW_REGION_RANGE(NtscU, 808913C0, 808913C3, -0x4448) +MKW_REGION_RANGE(NtscU, 80891750, 8089175F, -0x44D0) +MKW_REGION_RANGE(NtscU, 80891A28, 80891C28, -0x4518) +MKW_REGION_RANGE(NtscU, 80892F2C, 80892F96, -0x1B0) +MKW_REGION_RANGE(NtscU, 80893217, 8089321D, -0x4A30) +MKW_REGION_RANGE(NtscU, 808944DE, 80894769, -0x50E8) +MKW_REGION_RANGE(NtscU, 80894B98, 80894B9C, -0x1330) +MKW_REGION_RANGE(NtscU, 80895238, 808952B7, -0x58F8) +MKW_REGION_RANGE(NtscU, 80895A08, 80895C8C, -0x1930) +MKW_REGION_RANGE(NtscU, 80895CBC, 80895CF0, -0x5FA8) +MKW_REGION_RANGE(NtscU, 8089647A, 808966D4, -0x1CA0) +MKW_REGION_RANGE(NtscU, 80896820, 80897040, -0x6678) +MKW_REGION_RANGE(NtscU, 80897C63, 80897C67, -0x6DA0) +MKW_REGION_RANGE(NtscU, 80897DD3, 80897DEF, -0x6DA8) +MKW_REGION_RANGE(NtscU, 80898955, 80898959, -0x7388) +MKW_REGION_RANGE(NtscU, 80899692, 8089973A, -0x7730) +MKW_REGION_RANGE(NtscU, 808998B3, 808998CA, -0x3FB0) +MKW_REGION_RANGE(NtscU, 80899A36, 80899EEF, -0x7890) +MKW_REGION_RANGE(NtscU, 8089A194, 8089A1B7, -0x46D0) +MKW_REGION_RANGE(NtscU, 808A1D80, 808A1E6F, -0x4A08) +MKW_REGION_RANGE(NtscU, 808A22E0, 808A22EF, -0x46D0) +MKW_REGION_RANGE(NtscU, 808A4E00, 808A56FF, -0x49C0) +MKW_REGION_RANGE(NtscU, 808A587C, 808A5897, -0x2B20) +MKW_REGION_RANGE(NtscU, 808A5A30, 808A5DC3, -0x4AD8) +MKW_REGION_RANGE(NtscU, 808A7DE0, 808A85F3, -0x4CD8) +MKW_REGION_RANGE(NtscU, 808A98D0, 808A98DF, -0x5728) +MKW_REGION_RANGE(NtscU, 808A9AF8, 808A9AFF, +0x780) +MKW_REGION_RANGE(NtscU, 808A9C0A, 808A9CC8, -0x58C8) +MKW_REGION_RANGE(NtscU, 808A9FEC, 808AA1AF, -0x5928) +MKW_REGION_RANGE(NtscU, 808AAA04, 808AAA10, -0x5980) +MKW_REGION_RANGE(NtscU, 808ACB3F, 808ACB43, -0x5F10) +MKW_REGION_RANGE(NtscU, 808ACFDF, 808AD02B, -0x60C0) +MKW_REGION_RANGE(NtscU, 808AD3C4, 808AD3C7, -0x60C0) +MKW_REGION_RANGE(NtscU, 808AD48E, 808AD492, -0x2980) +MKW_REGION_RANGE(NtscU, 808AD9F7, 808AD9FC, -0x6320) +MKW_REGION_RANGE(NtscU, 808ADCBC, 808ADD2C, -0x2FA8) +MKW_REGION_RANGE(NtscU, 808AEB45, 808AEB55, -0x68A8) +MKW_REGION_RANGE(NtscU, 808AF8E0, 808AF95F, -0x6AC0) +MKW_REGION_RANGE(NtscU, 808AFC18, 808AFC1B, -0x46B8) +MKW_REGION_RANGE(NtscU, 808B30C8, 808B3108, -0x46B0) +MKW_REGION_RANGE(NtscU, 808B35A0, 808B35AF, -0x46B0) +MKW_REGION_RANGE(NtscU, 808B3984, 808B3987, -0x4850) +MKW_REGION_RANGE(NtscU, 808B3A90, 808B3A9F, -0x4850) +MKW_REGION_RANGE(NtscU, 808B4C20, 808B4DEF, -0x46B0) +MKW_REGION_RANGE(NtscU, 808B54B8, 808B550F, -0x4738) +MKW_REGION_RANGE(NtscU, 808B59F4, 808B5CCF, -0x48C0) +MKW_REGION_RANGE(NtscU, 808B5CD8, 808B5CDB, -0x48BC) +MKW_REGION_RANGE(NtscU, 808BB034, 808BB097, -0x60F8) +MKW_REGION_RANGE(NtscU, 808BBEC8, 808BE908, -0x6430) +MKW_REGION_RANGE(NtscU, 808BFAF0, 808BFAFF, -0x65B0) +MKW_REGION_RANGE(NtscU, 808C069C, 808C06FF, -0x66B0) +MKW_REGION_RANGE(NtscU, 808CB550, 808CB553, -0x5508) +MKW_REGION_RANGE(NtscU, 808CB700, 808CB70F, -0x5508) +MKW_REGION_RANGE(NtscU, 808D1DD0, 808D1E2B, -0x3A98) +MKW_REGION_RANGE(NtscU, 808D30D8, 808D324F, -0x4908) +MKW_REGION_RANGE(NtscU, 808D3698, 808D369B, +0x1AB0) +MKW_REGION_RANGE(NtscU, 808D36CC, 808D36CF, +0x1AB0) +MKW_REGION_RANGE(NtscU, 808D36D4, 808D36D7, +0x1AB0) +MKW_REGION_RANGE(NtscU, 808D3744, 808D3747, +0x1AB0) +MKW_REGION_RANGE(NtscU, 808D374C, 808D374F, +0x1AB0) +MKW_REGION_RANGE(NtscU, 808D3C78, 808D3D1B, +0x1610) +MKW_REGION_RANGE(NtscU, 808D3E14, 808D3F2F, -0x4F68) +MKW_REGION_RANGE(NtscU, 808D9A58, 808D9A98, -0x60F0) +MKW_REGION_RANGE(NtscU, 808D9BC8, 808D9C5F, -0x36C0) +MKW_REGION_RANGE(NtscU, 808D9DB0, 808D9F97, -0x6220) +MKW_REGION_RANGE(NtscU, 808DA070, 808DA07F, -0x6220) +MKW_REGION_RANGE(NtscU, 808DA318, 808DA367, -0x63B8) +MKW_REGION_RANGE(NtscU, 808DA5DC, 808DA63F, -0x64C0) +MKW_REGION_RANGE(NtscU, 808DAD60, 808DAD6F, -0x6778) +MKW_REGION_RANGE(NtscU, 808DC540, 808DC54F, -0x4138) +MKW_REGION_RANGE(NtscU, 808E2BBC, 808E2BBE, +0x0) +MKW_REGION_RANGE(NtscU, 809BD6E0, 809C186B, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C1874, 809C1877, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C18F8, 809C18FB, -0x47E8) +MKW_REGION_RANGE(NtscU, 809C1918, 809C191B, -0x47E8) +MKW_REGION_RANGE(NtscU, 809C1980, 809C198F, -0x4610) +MKW_REGION_RANGE(NtscU, 809C19A0, 809C19BB, -0x4820) +MKW_REGION_RANGE(NtscU, 809C1E38, 809C1E3B, -0x4930) +MKW_REGION_RANGE(NtscU, 809C1F50, 809C20EF, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C20F0, 809C20F7, -0x47C8) +MKW_REGION_RANGE(NtscU, 809C20F8, 809C20FB, -0x47A8) +MKW_REGION_RANGE(NtscU, 809C2100, 809C2107, -0x47D0) +MKW_REGION_RANGE(NtscU, 809C2108, 809C210B, -0x47B0) +MKW_REGION_RANGE(NtscU, 809C210C, 809C210F, -0x47D0) +MKW_REGION_RANGE(NtscU, 809C2110, 809C211B, -0x47D8) +MKW_REGION_RANGE(NtscU, 809C21D0, 809C21D3, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C21D4, 809C21D7, +0xB840) +MKW_REGION_RANGE(NtscU, 809C21D8, 809C21DB, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C2328, 809C232B, -0x47C8) +MKW_REGION_RANGE(NtscU, 809C26B8, 809C26BB, -0x4700) +MKW_REGION_RANGE(NtscU, 809C27F0, 809C289B, -0x4C40) +MKW_REGION_RANGE(NtscU, 809C28B8, 809C28BB, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C2BE8, 809C2BEB, -0x4850) +MKW_REGION_RANGE(NtscU, 809C2CB8, 809C2CBB, -0x47E0) +MKW_REGION_RANGE(NtscU, 809C2EF0, 809C2EF3, -0x47C0) +MKW_REGION_RANGE(NtscU, 809C2F38, 809C361B, -0x47F8) +MKW_REGION_RANGE(NtscU, 809C3670, 809C38CF, -0x4808) +MKW_REGION_RANGE(NtscU, 809C4330, 809C4333, -0x4840) +MKW_REGION_RANGE(NtscU, 809C4680, 809C4683, -0x48C0) +MKW_REGION_RANGE(NtscU, 809C4730, 809C474F, -0x47B0) +MKW_REGION_RANGE(NtscU, 809C496C, 809C496F, -0x4820) + +MKW_REGION_RANGE(NtscJ, 80000000, 80008023, +0x0) +MKW_REGION_RANGE(NtscJ, 800080E8, 8000ADBF, -0xA4) +MKW_REGION_RANGE(NtscJ, 8000AF08, 80021BAB, -0xDC) +MKW_REGION_RANGE(NtscJ, 80021BAC, 80244EBF, -0xE0) +MKW_REGION_RANGE(NtscJ, 802572BF, 802575DF, -0x660) +MKW_REGION_RANGE(NtscJ, 80257F40, 80258184, -0x660) +MKW_REGION_RANGE(NtscJ, 80276054, 802A407F, -0x660) +MKW_REGION_RANGE(NtscJ, 802A4080, 8038917B, -0x680) +MKW_REGION_RANGE(NtscJ, 80399200, 80399400, -0x680) +MKW_REGION_RANGE(NtscJ, 805103B4, 805CC0A7, -0x680) +MKW_REGION_RANGE(NtscJ, 805CC1B4, 805FA33B, -0x724) +MKW_REGION_RANGE(NtscJ, 805FA344, 805FF6E7, -0x724) +MKW_REGION_RANGE(NtscJ, 805FFD70, 806003E7, -0x848) +MKW_REGION_RANGE(NtscJ, 80600C78, 80620CB3, -0x88C) +MKW_REGION_RANGE(NtscJ, 80620D7C, 80637A23, -0x8B4) +MKW_REGION_RANGE(NtscJ, 80637A80, 8063BCF7, -0x914) +MKW_REGION_RANGE(NtscJ, 8063BD28, 8063BD2F, -0x920) +MKW_REGION_RANGE(NtscJ, 8063BD38, 8063BD3F, -0x920) +MKW_REGION_RANGE(NtscJ, 8063BE40, 8088F70F, -0x994) +MKW_REGION_RANGE(NtscJ, 8088F720, 8088FDBB, -0x9A0) +MKW_REGION_RANGE(NtscJ, 80890208, 80890977, -0x9B0) +MKW_REGION_RANGE(NtscJ, 808913C0, 808913C3, -0x9B0) +MKW_REGION_RANGE(NtscJ, 80891750, 8089175F, -0x9B0) +MKW_REGION_RANGE(NtscJ, 80891A60, 80891A6F, -0x9B0) +MKW_REGION_RANGE(NtscJ, 80891B28, 80891C28, -0x9B0) +MKW_REGION_RANGE(NtscJ, 80892F2C, 80897DEF, -0x9B0) +MKW_REGION_RANGE(NtscJ, 80898955, 80898959, -0xE60) +MKW_REGION_RANGE(NtscJ, 80899692, 808B5CCF, -0xEA0) +MKW_REGION_RANGE(NtscJ, 808B5CD8, 808B5CDB, -0xE9C) +MKW_REGION_RANGE(NtscJ, 808BB034, 808BB097, -0xEB0) +MKW_REGION_RANGE(NtscJ, 808BBEC8, 808DA617, -0xEB0) +MKW_REGION_RANGE(NtscJ, 808DC540, 808DC54F, -0xEB0) +MKW_REGION_RANGE(NtscJ, 808E2BBC, 808E2BBE, +0x0) +MKW_REGION_RANGE(NtscJ, 809BD6E8, 809C474B, -0xFA0) +MKW_REGION_RANGE(NtscJ, 809C496C, 809C496F, -0xFA0) diff --git a/runtime/include/guest_function_imports.h b/runtime/include/guest_function_imports.h index f644f97..2b32810 100644 --- a/runtime/include/guest_function_imports.h +++ b/runtime/include/guest_function_imports.h @@ -1,13 +1,21 @@ #pragma once -// Base translations the runtime calls directly, named by PAL identity. runtime/game binds each -// to the translated region's symbol. +// Base translations the runtime calls directly, named by PAL identity and resolved through the +// function registry on first use. // MKW_GUEST_FUNC(801A0620)(ctx); #include "guest_abi/cpu_context.h" +#include "guest_abi/guest_region.h" -#define MKW_GUEST_FUNC(pal) (*::mkw_guest_function_##pal) +namespace GuestFunctions { +using Entry = void (*)(CpuContext*); -#define MKW_GUEST_FUNCTION_IMPORT(pal, ntscU, ntscJ) extern "C" void (*const mkw_guest_function_##pal)(CpuContext*); -#include "guest_function_imports.inc" -#undef MKW_GUEST_FUNCTION_IMPORT +// The base translation at a guest address, also where a native or mod overrides it. +Entry BaseTranslation(uint32_t address); +} // namespace GuestFunctions + +#define MKW_GUEST_FUNC(pal) \ + (*[] { \ + static const ::GuestFunctions::Entry entry = ::GuestFunctions::BaseTranslation(MKW_GADDR(pal)); \ + return entry; \ + }()) diff --git a/runtime/include/guest_function_imports.inc b/runtime/include/guest_function_imports.inc deleted file mode 100644 index 4768345..0000000 --- a/runtime/include/guest_function_imports.inc +++ /dev/null @@ -1,13 +0,0 @@ -// AUTO-GENERATED by tools/region/gen_guest_address_table.py - DO NOT EDIT. -// Base translations the runtime calls directly: MKW_GUEST_FUNCTION_IMPORT(PAL, NTSC-U, NTSC-J). -MKW_GUEST_FUNCTION_IMPORT(8012B830, 8012B790, 8012B750) // AXFXReverbStdExpCallback -MKW_GUEST_FUNCTION_IMPORT(801A0620, 801A0580, 801A0540) // InsertAlarm -MKW_GUEST_FUNCTION_IMPORT(801A1ED8, 801A1E38, 801A1DF8) // OS::SaveContext -MKW_GUEST_FUNCTION_IMPORT(801A961C, 801A957C, 801A953C) // OS::__ThreadInit -MKW_GUEST_FUNCTION_IMPORT(801AADE0, 801AAD40, 801AAD00) // OS::__TimeToSystemTime -MKW_GUEST_FUNCTION_IMPORT(801D8D30, 801D8C90, 801D8C50) // NHTTPStartup -MKW_GUEST_FUNCTION_IMPORT(801D9E94, 801D9DF4, 801D9DB4) // NHTTPi_GetSystemInfoP -MKW_GUEST_FUNCTION_IMPORT(8055531C, 8054F2FC, 80554C9C) // RelProlog -MKW_GUEST_FUNCTION_IMPORT(80601C64, 805DD384, 806013D8) // Page::CheckActions -MKW_GUEST_FUNCTION_IMPORT(8061E348, 805EE30C, 8061DABC) // Pages::RegisterFriend::OnDigitClick -MKW_GUEST_FUNCTION_IMPORT(8061E3B4, 805EE378, 8061DB28) // Pages::RegisterFriend::OnBackSpaceClick diff --git a/runtime/src/abi_bridge.cpp b/runtime/src/abi_bridge.cpp index fd1a70d..e339244 100644 --- a/runtime/src/abi_bridge.cpp +++ b/runtime/src/abi_bridge.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "guest_function_imports.h" #include "guest_small_data.h" #include "runtime_log.h" @@ -425,6 +426,31 @@ const TranslatedFunctionInfo* TranslatedFunctionRegistry::FindByAddressPtrSlow(u return nullptr; } +GuestFunctions::Entry GuestFunctions::BaseTranslation(uint32_t address) { + std::unique_lock lock(RegistryMutex(), std::defer_lock); + if (!RegistryFrozen().load(std::memory_order_acquire)) { + lock.lock(); + } + for (const auto& entry : Registry()) { + if (entry.address == address && entry.kind == FunctionKind::BaseTranslated && entry.rawCpuInvoker) { + return entry.rawCpuInvoker; + } + } + if (lock.owns_lock()) { + lock.unlock(); + } + RT_LOG(RT_TAG_RUNTIME) << "ERROR: no base translation registered at 0x" << std::hex << address << std::dec + << std::endl; + std::ostringstream message; + message << "The runtime calls the translated function at guest address 0x" << std::hex << address + << ", but it was not translated."; + RuntimeCrash::WriteCrashArtifacts("missing_guest_function", message.str(), &address); + SetRuntimeExitCode(EXIT_FAILURE); + ShowRuntimeFatalPopup("Missing translated function", message.str()); + MarkFatalErrorReported(); + std::exit(EXIT_FAILURE); +} + const RawDispatchRecord* TranslatedFunctionRegistry::FindRawByAddressPtrSlow(uint32_t address) { if (!RegistryFrozen().load(std::memory_order_acquire)) { return nullptr; diff --git a/runtime/src/guest_region.cpp b/runtime/src/guest_region.cpp index d1ee90f..66fb1ae 100644 --- a/runtime/src/guest_region.cpp +++ b/runtime/src/guest_region.cpp @@ -6,7 +6,7 @@ namespace GuestRegion { void FatalUnknownAddress(uint32_t pal) noexcept { - std::fprintf(stderr, "Guest region: PAL address 0x%08X has no %s address in guest_address_table.inc\n", + std::fprintf(stderr, "Guest region: PAL address 0x%08X has no %s address in guest_versions.inc\n", pal, CurrentFacts().gameId); std::fflush(stderr); std::abort(); diff --git a/tools/region/gen_guest_address_table.py b/tools/region/gen_guest_address_table.py deleted file mode 100644 index 09e096d..0000000 --- a/tools/region/gen_guest_address_table.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python3 -"""Generate runtime/include/guest_abi/guest_address_table.inc and runtime/include/guest_function_imports.inc. - -The runtime names every guest address by its PAL (RMCP01) address. This scans the runtime for -those identities and writes one row per identity with its NTSC-U and NTSC-J address: - - MKW_GUEST_ADDRESS(, , ) - -Identities the runtime calls through MKW_GUEST_FUNC also get a MKW_GUEST_FUNCTION_IMPORT row. - -Code addresses go through each region's chunk table (projects//region_port.json) and must -be a function entry in that region's validated MAP.txt, or sit at the same offset inside the same -validated function. Data addresses come from projects//data_addresses.txt. An identity -that does not resolve aborts the generation. - -Usage: python -I tools/region/gen_guest_address_table.py -""" -import bisect -import json -import os -import re -import sys - -ROOT = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")) -RUNTIME = os.path.join(ROOT, "runtime") -OUT = os.path.join(RUNTIME, "include", "guest_abi", "guest_address_table.inc") -IMPORTS_OUT = os.path.join(RUNTIME, "include", "guest_function_imports.inc") - -PAL_TEXT = [(0x80004000, 0x80006460), (0x800072C0, 0x80244DE0), (0x805103B4, 0x8088F400)] - -# Column order is the GuestRegion::Id order in guest_abi/guest_region.h. -REGIONS = ["mkwii-ntsc-u", "mkwii-ntsc-j"] - -HEX = r"([0-9A-Fa-f]{8})(?![0-9A-Fa-f])" -TOKEN_PATTERNS = [re.compile(p) for p in ( - r"PPC_NATIVE_OVERRIDE(?:_VOID)?\s*\(\s*" + HEX, - r"GX_FATAL_STUB\s*\(\s*" + HEX, - r"MKW_GADDR\s*\(\s*" + HEX, - r"MKW_GADDR_CT\s*\(\s*" + HEX, - r"MKW_GUEST_FUNC\s*\(\s*" + HEX, - r"MKW_KNOWN_TYPED_NATIVE\s*\(\s*" + HEX, - r"MKW_KNOWN_NATIVE_CPU_CALL\s*\(\s*" + HEX, - r"REGISTER_NATIVE_FUNCTION(?:_AS)?\s*\(\s*0x" + HEX, - r"REGISTER_TRANSLATED_FUNCTION\s*\(\s*0x" + HEX, - r"GuestRegion::(?:Is|Address)<0x" + HEX, -)] -IMPORT_PATTERN = re.compile(r"MKW_GUEST_FUNC\s*\(\s*" + HEX) -COMMENTS = re.compile(r"//[^\n]*|/\*.*?\*/", re.S) -LABEL_NAME = re.compile(r"(_switch$|_caseD_|^0x)") - - -def scan_identities(): - found, imports = set(), set() - for directory, _, files in os.walk(RUNTIME): - if directory.startswith(os.path.join(RUNTIME, "third_party")): - continue - for name in files: - path = os.path.join(directory, name) - if not name.endswith((".cpp", ".h", ".hpp", ".inc")) or path in (OUT, IMPORTS_OUT): - continue - with open(path, encoding="utf-8", errors="replace") as f: - text = COMMENTS.sub("", f.read()) - for pattern in TOKEN_PATTERNS: - found.update(int(m.group(1), 16) for m in pattern.finditer(text)) - imports.update(int(m.group(1), 16) for m in IMPORT_PATTERN.finditer(text)) - return sorted(found), sorted(imports) - - -def is_text(address): - return any(start <= address < end for start, end in PAL_TEXT) - - -def load_map(path): - entries = [] - with open(path, encoding="utf-8") as f: - for line in f: - line = line.strip() - if line and not line.startswith("#"): - address, _, name = line.partition(" ") - entries.append((int(address, 16), name.strip())) - entries.sort() - return entries - - -def load_chunks(project): - with open(os.path.join(ROOT, "projects", project, "region_port.json"), encoding="utf-8") as f: - return [tuple(int(v, 16) for v in chunk) for chunk in json.load(f)["chunks"]] - - -def load_data_table(project): - table = {} - with open(os.path.join(ROOT, "projects", project, "data_addresses.txt"), encoding="utf-8") as f: - for line in f: - parts = line.split("#", 1)[0].split() - if len(parts) >= 2 and parts[1] != "?": - table[int(parts[0], 16)] = int(parts[1], 16) - return table - - -def containing_function(entries, addresses, address): - i = bisect.bisect_right(addresses, address) - 1 - while i >= 0 and LABEL_NAME.search(entries[i][1]): - i -= 1 - if i < 0: - return None, None - return entries[i][1], address - entries[i][0] - - -def port_region(project, identities, pal_entries): - chunks = load_chunks(project) - data = load_data_table(project) - target_entries = load_map(os.path.join(ROOT, "projects", project, "MAP.txt")) - target_starts = {a for a, _ in target_entries} - target_by_name = {} - for address, name in target_entries: - target_by_name.setdefault(name, address) - pal_addresses = [a for a, _ in pal_entries] - - mapping, problems = {}, [] - for pal in identities: - if not is_text(pal): - if pal in data: - mapping[pal] = data[pal] - else: - problems.append(f"{pal:08X}: data address missing from projects/{project}/data_addresses.txt") - continue - ported = next((pal - s + d for s, e, d in chunks if s <= pal < e), None) - if ported is None: - problems.append(f"{pal:08X}: code address outside every chunk") - continue - if ported not in target_starts: - name, offset = containing_function(pal_entries, pal_addresses, pal) - start = target_by_name.get(name) if name else None - if start is None or start + offset != ported: - problems.append(f"{pal:08X} -> {ported:08X}: not a validated entry of {project}/MAP.txt " - f"(containing function {name} not confirmed at the same offset)") - continue - mapping[pal] = ported - return mapping, problems - - -def write(path, macro, header, rows, columns, names): - lines = ["// AUTO-GENERATED by tools/region/gen_guest_address_table.py - DO NOT EDIT."] + header - for pal in rows: - row = ", ".join([f"{pal:08X}"] + [f"{column[pal]:08X}" for column in columns]) - name = names.get(pal) - lines.append(f"{macro}({row})" + (f" // {name}" if name and not name.startswith("0x") else "")) - with open(path, "w", encoding="utf-8", newline="\n") as f: - f.write("\n".join(lines) + "\n") - - -def main(): - identities, imports = scan_identities() - pal_entries = load_map(os.path.join(ROOT, "projects", "mkwii", "MAP.txt")) - names = dict(pal_entries) - columns, failed = [], False - for project in REGIONS: - mapping, problems = port_region(project, identities, pal_entries) - if problems: - failed = True - print(f"{project}: {len(problems)} identities did not resolve:") - for problem in problems: - print(" " + problem) - columns.append(mapping) - if failed: - return 1 - - write(OUT, "MKW_GUEST_ADDRESS", [ - "// PAL identity -> address in each region: MKW_GUEST_ADDRESS(PAL, NTSC-U, NTSC-J).", - "// Sorted by PAL address; guest_abi/guest_region.h relies on that.", - ], identities, columns, names) - write(IMPORTS_OUT, "MKW_GUEST_FUNCTION_IMPORT", [ - "// Base translations the runtime calls directly: MKW_GUEST_FUNCTION_IMPORT(PAL, NTSC-U, NTSC-J).", - ], imports, columns, names) - code = sum(1 for a in identities if is_text(a)) - print(f"wrote {len(identities)} identities ({code} code, {len(identities) - code} data), " - f"{len(imports)} function imports") - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/translator/src/Translator.Core/GuestAddressTable.cs b/translator/src/Translator.Core/GuestAddressTable.cs index c0e3d40..871ee97 100644 --- a/translator/src/Translator.Core/GuestAddressTable.cs +++ b/translator/src/Translator.Core/GuestAddressTable.cs @@ -2,7 +2,7 @@ using System.Text.RegularExpressions; namespace Translator.Core; -/// Column order of runtime/include/guest_abi/guest_address_table.inc. +/// Region index the runtime uses (GuestRegion::Id in guest_abi/guest_region.h). public enum GuestRegion { Pal = 0, @@ -28,53 +28,84 @@ public static class GuestRegions } /// -/// The runtime names guest addresses by their PAL address. This is the table it resolves them -/// through, read from the same file the C++ includes. +/// The runtime names guest addresses by their PAL address. This is the range map it resolves +/// them through (Retro Rewind versions.txt style), read from the same file the C++ includes. /// public sealed partial class GuestAddressTable { - private readonly Dictionary _rows; + private readonly Dictionary _ranges; - private GuestAddressTable(Dictionary rows, string sourcePath) + private readonly record struct Range(uint First, uint Last, int Delta); + + private GuestAddressTable(Dictionary ranges, string sourcePath) { - _rows = rows; + _ranges = ranges; SourcePath = sourcePath; } public string SourcePath { get; } - public int Count => _rows.Count; + public int Count => _ranges.Values.Sum(static ranges => ranges.Length); - /// The table beside a runtime whose native sources live in . + /// The map beside a runtime whose native sources live in . public static string DefaultPath(string nativeSourceDirectory) => - Path.GetFullPath(Path.Combine(nativeSourceDirectory, "..", "include", "guest_abi", "guest_address_table.inc")); + Path.GetFullPath(Path.Combine(nativeSourceDirectory, "..", "include", "guest_abi", "guest_versions.inc")); public static GuestAddressTable Load(string path) { if (!File.Exists(path)) - throw new FileNotFoundException("The runtime's guest address table was not found.", path); - var rows = new Dictionary(); + throw new FileNotFoundException("The runtime's guest address map was not found.", path); + var ranges = new Dictionary>(); foreach (var line in File.ReadLines(path)) { - var match = RowPattern().Match(line); - if (!match.Success) continue; - var pal = Convert.ToUInt32(match.Groups["pal"].Value, 16); - if (!rows.TryAdd(pal, [pal, Convert.ToUInt32(match.Groups["u"].Value, 16), Convert.ToUInt32(match.Groups["j"].Value, 16)])) - throw new InvalidDataException($"{path} lists PAL address 0x{pal:X8} twice."); + if (!line.TrimStart().StartsWith("MKW_REGION_RANGE", StringComparison.Ordinal)) continue; + var match = RangePattern().Match(line); + if (!match.Success) + throw new InvalidDataException($"{path} has a malformed range: {line.Trim()}"); + var regionName = match.Groups["region"].Value; + if (!Enum.TryParse(regionName, out var region) || !Enum.IsDefined(region) || + region == GuestRegion.Pal || char.IsDigit(regionName[0])) + throw new InvalidDataException($"{path} has a range for unknown region '{regionName}'."); + var magnitude = Convert.ToInt64(match.Groups["delta"].Value, 16); + if (magnitude > int.MaxValue) + throw new InvalidDataException($"{path} has an out-of-range delta: {line.Trim()}"); + var range = new Range( + Convert.ToUInt32(match.Groups["first"].Value, 16), + Convert.ToUInt32(match.Groups["last"].Value, 16), + (match.Groups["sign"].Value == "-" ? -1 : 1) * (int)magnitude); + if (range.First > range.Last) + throw new InvalidDataException($"{path} has an empty range at 0x{range.First:X8}."); + if (!ranges.TryGetValue(region, out var list)) + ranges[region] = list = []; + if (list.Count != 0 && list[^1].Last >= range.First) + throw new InvalidDataException($"{path} ranges for {region} overlap or are unsorted at 0x{range.First:X8}."); + list.Add(range); } - if (rows.Count == 0) - throw new InvalidDataException($"{path} has no MKW_GUEST_ADDRESS rows."); - return new GuestAddressTable(rows, path); + if (ranges.Count == 0) + throw new InvalidDataException($"{path} has no MKW_REGION_RANGE rows."); + return new GuestAddressTable(ranges.ToDictionary(static pair => pair.Key, static pair => pair.Value.ToArray()), path); } public uint Map(uint pal, GuestRegion region) { - if (_rows.TryGetValue(pal, out var row)) - return row[(int)region]; - throw new InvalidDataException( - $"PAL address 0x{pal:X8} is missing from {SourcePath}; regenerate it with tools/region/gen_guest_address_table.py."); + if (region == GuestRegion.Pal) + return pal; + if (_ranges.TryGetValue(region, out var ranges)) + { + var lo = 0; + var hi = ranges.Length; + while (lo < hi) + { + var mid = lo + (hi - lo) / 2; + if (pal < ranges[mid].First) hi = mid; + else lo = mid + 1; + } + if (lo > 0 && pal <= ranges[lo - 1].Last) + return (uint)(pal + (long)ranges[lo - 1].Delta); + } + throw new InvalidDataException($"PAL address 0x{pal:X8} has no {region} address in {SourcePath}."); } - [GeneratedRegex(@"^\s*MKW_GUEST_ADDRESS\(\s*(?[0-9A-Fa-f]{8})\s*,\s*(?[0-9A-Fa-f]{8})\s*,\s*(?[0-9A-Fa-f]{8})\s*\)", RegexOptions.CultureInvariant)] - private static partial Regex RowPattern(); + [GeneratedRegex(@"^\s*MKW_REGION_RANGE\(\s*(?\w+)\s*,\s*(?[0-9A-Fa-f]{8})\s*,\s*(?[0-9A-Fa-f]{8})\s*,\s*(?[+-])0x(?[0-9A-Fa-f]{1,8})\s*\)\s*(//.*)?$", RegexOptions.CultureInvariant)] + private static partial Regex RangePattern(); } diff --git a/translator/src/Translator.Core/RuntimeNativeIndex.cs b/translator/src/Translator.Core/RuntimeNativeIndex.cs index 33f13e6..74c6fee 100644 --- a/translator/src/Translator.Core/RuntimeNativeIndex.cs +++ b/translator/src/Translator.Core/RuntimeNativeIndex.cs @@ -46,7 +46,7 @@ public sealed record RuntimeNativeIndex( /// /// The index is keyed by the PAL addresses the runtime sources name; this is the same index - /// keyed by 's addresses. Every address must be in the table, PAL too. + /// keyed by 's addresses. Every address must have a counterpart in that region. /// public RuntimeNativeIndex ForRegion(GuestAddressTable table, GuestRegion region) => new( Registrations.Select(entry => entry with { Address = table.Map(entry.Address, region) }).ToArray(), diff --git a/translator/tests/Translator.Tests/GuestAddressTableTests.cs b/translator/tests/Translator.Tests/GuestAddressTableTests.cs index 9b9f8f9..4e972aa 100644 --- a/translator/tests/Translator.Tests/GuestAddressTableTests.cs +++ b/translator/tests/Translator.Tests/GuestAddressTableTests.cs @@ -1,3 +1,4 @@ +using System.Text.RegularExpressions; using Translator.Core; using Translator.Core.Analysis; using Xunit; @@ -22,24 +23,32 @@ public sealed class GuestAddressTableTests Assert.Throws(() => GuestRegions.FromGameId(gameId)); [Fact] - public void MapsEachColumnAndRejectsUnknownAndDuplicateRows() + public void MapsRangesAndRejectsUnknownAndOverlappingRanges() { WithTable(""" // comment - MKW_GUEST_ADDRESS(801A9E84, 801A9DE4, 801A9DA4) // OSCreateThread - MKW_GUEST_ADDRESS(80386664, 80382304, 80385FE4) + MKW_REGION_RANGE(NtscU, 801A9000, 801A9FFF, -0xA0) + MKW_REGION_RANGE(NtscU, 80386000, 80386FFF, -0x4360) + MKW_REGION_RANGE(NtscJ, 801A9000, 801A9FFF, -0xE0) + MKW_REGION_RANGE(NtscJ, 80386000, 80386FFF, -0x680) """, table => { - Assert.Equal(2, table.Count); + Assert.Equal(4, table.Count); Assert.Equal(0x801A9E84u, table.Map(0x801A9E84, GuestRegion.Pal)); Assert.Equal(0x801A9DE4u, table.Map(0x801A9E84, GuestRegion.NtscU)); Assert.Equal(0x80385FE4u, table.Map(0x80386664, GuestRegion.NtscJ)); - Assert.Throws(() => table.Map(0x80000000, GuestRegion.Pal)); + Assert.Equal(0x80000000u, table.Map(0x80000000, GuestRegion.Pal)); + Assert.Throws(() => table.Map(0x80000000, GuestRegion.NtscU)); + Assert.Throws(() => table.Map(0x801AA000, GuestRegion.NtscJ)); }); WithTable(""" - MKW_GUEST_ADDRESS(801A9E84, 801A9DE4, 801A9DA4) - MKW_GUEST_ADDRESS(801a9e84, 801A9DE4, 801A9DA4) + MKW_REGION_RANGE(NtscU, 801A9000, 801A9FFF, -0xA0) + MKW_REGION_RANGE(NtscU, 801A9FFF, 801AAFFF, -0xA0) """, _ => { }, expectFailure: true); + WithTable("MKW_REGION_RANGE(Pal, 801A9000, 801A9FFF, +0x0)\n", _ => { }, expectFailure: true); + WithTable("MKW_REGION_RANGE(1, 801A9000, 801A9FFF, +0x0)\n", _ => { }, expectFailure: true); + WithTable("MKW_REGION_RANGE(NtscU, 801A9000, 801A9FFF, 0xA0)\n", _ => { }, expectFailure: true); + WithTable("MKW_REGION_RANGE(NtscU, 801A9000, 801A9FFF, -0x80000000)\n", _ => { }, expectFailure: true); WithTable("// no rows\n", _ => { }, expectFailure: true); } @@ -53,8 +62,8 @@ public sealed class GuestAddressTableTests [new RuntimeNativeAbiEntry(0x801A9E84, ["r3"], [])], [new RuntimeNativeEffectEntry(0x801A9E84, contract, true)]); WithTable(""" - MKW_GUEST_ADDRESS(801A9E84, 801A9DE4, 801A9DA4) - MKW_GUEST_ADDRESS(80386664, 80382304, 80385FE4) + MKW_REGION_RANGE(NtscU, 801A9000, 801A9FFF, -0xA0) + MKW_REGION_RANGE(NtscU, 80386000, 80386FFF, -0x4360) """, table => { var ntscU = index.ForRegion(table, GuestRegion.NtscU); @@ -67,9 +76,9 @@ public sealed class GuestAddressTableTests }); } - // Every address the runtime registers must have a row, or a regional build cannot place it. + // Every address the runtime registers must have a counterpart, or a regional build cannot place it. [Fact] - public void RepositoryTableCoversEveryRuntimeRegistration() + public void RepositoryMapCoversEveryRuntimeRegistration() { var root = ProjectPathsForTests.FindRepositoryRoot(); var sources = Path.Combine(root, "runtime", "src"); @@ -80,29 +89,92 @@ public sealed class GuestAddressTableTests Assert.Equal(index.Registrations.Length, index.ForRegion(table, region).Registrations.Length); } - // Distinct PAL identities must stay distinct and in the same order in every region. - [Fact] - public void RepositoryTableIsInjectiveAndOrderedPerRegion() + // Every function both MAPs name uniquely, and every verified data address, must port exactly. + [Theory] + [InlineData(GuestRegion.NtscU, "mkwii-ntsc-u")] + [InlineData(GuestRegion.NtscJ, "mkwii-ntsc-j")] + public void RepositoryMapAgreesWithRegionMapsAndDataAnchors(GuestRegion region, string project) { var root = ProjectPathsForTests.FindRepositoryRoot(); - var path = Path.Combine(root, "runtime", "include", "guest_abi", "guest_address_table.inc"); - var rows = File.ReadLines(path) - .Where(static line => line.StartsWith("MKW_GUEST_ADDRESS(", StringComparison.Ordinal)) - .Select(static line => line["MKW_GUEST_ADDRESS(".Length..line.IndexOf(')')] - .Split(',').Select(static value => Convert.ToUInt32(value.Trim(), 16)).ToArray()) - .ToArray(); - Assert.NotEmpty(rows); - for (var column = 0; column < 3; column++) + var table = GuestAddressTable.Load(GuestAddressTable.DefaultPath(Path.Combine(root, "runtime", "src"))); + var pal = UniqueNames(Path.Combine(root, "projects", "mkwii", "MAP.txt")); + var target = UniqueNames(Path.Combine(root, "projects", project, "MAP.txt")); + var compared = 0; + foreach (var (name, address) in pal) { - for (var i = 1; i < rows.Length; i++) - Assert.True(rows[i - 1][column] < rows[i][column], - $"column {column} row {i}: 0x{rows[i - 1][column]:X8} >= 0x{rows[i][column]:X8}"); + if (!target.TryGetValue(name, out var expected)) + continue; + Assert.True(expected == table.Map(address, region), $"{name} 0x{address:X8} should port to 0x{expected:X8}"); + compared++; } + Assert.True(compared > 15000, $"only {compared} functions compared"); + + foreach (var line in File.ReadLines(Path.Combine(root, "projects", project, "data_addresses.txt"))) + { + var parts = line.Split('#')[0].Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length < 2 || parts[1] == "?" || parts[0].Length != 8) + continue; + var address = Convert.ToUInt32(parts[0], 16); + Assert.Equal(Convert.ToUInt32(parts[1], 16), table.Map(address, region)); + } + } + + // Guest functions the runtime calls directly must be real functions in every region. + [Fact] + public void RuntimeGuestCallsAreFunctionEntriesInEveryRegion() + { + var root = ProjectPathsForTests.FindRepositoryRoot(); + var table = GuestAddressTable.Load(GuestAddressTable.DefaultPath(Path.Combine(root, "runtime", "src"))); + var thirdParty = $"{Path.DirectorySeparatorChar}third_party{Path.DirectorySeparatorChar}"; + var calls = Directory.EnumerateFiles(Path.Combine(root, "runtime"), "*.*", SearchOption.AllDirectories) + .Where(path => (path.EndsWith(".cpp", StringComparison.Ordinal) || path.EndsWith(".h", StringComparison.Ordinal)) && + !path.Contains(thirdParty, StringComparison.Ordinal)) + .SelectMany(static path => Regex.Matches(File.ReadAllText(path), @"MKW_GUEST_FUNC\(\s*([0-9A-Fa-f]{8})\s*\)") + .Select(static match => Convert.ToUInt32(match.Groups[1].Value, 16))) + .Distinct() + .ToArray(); + Assert.NotEmpty(calls); + var entries = new Dictionary> + { + [GuestRegion.Pal] = MapEntries(Path.Combine(root, "projects", "mkwii", "MAP.txt")), + [GuestRegion.NtscU] = MapEntries(Path.Combine(root, "projects", "mkwii-ntsc-u", "MAP.txt")), + [GuestRegion.NtscJ] = MapEntries(Path.Combine(root, "projects", "mkwii-ntsc-j", "MAP.txt")), + }; + foreach (var pal in calls) + { + foreach (var (region, starts) in entries) + { + var address = table.Map(pal, region); + Assert.True(starts.Contains(address), $"MKW_GUEST_FUNC({pal:X8}) is not a {region} function entry (0x{address:X8})"); + } + } + } + + private static HashSet MapEntries(string mapPath) => + File.ReadLines(mapPath) + .Select(static line => line.Trim()) + .Where(static line => line.Length >= 8 && !line.StartsWith('#')) + .Select(static line => Convert.ToUInt32(line[..8], 16)) + .ToHashSet(); + + private static Dictionary UniqueNames(string mapPath) + { + var entries = File.ReadLines(mapPath) + .Select(static line => line.Trim()) + .Where(static line => line.Length > 9 && !line.StartsWith('#')) + .Select(static line => (Address: Convert.ToUInt32(line[..8], 16), Name: line[9..].Trim())) + .Where(static entry => !entry.Name.StartsWith("0x", StringComparison.Ordinal) && + !entry.Name.StartsWith("FUN_", StringComparison.Ordinal) && + !entry.Name.StartsWith("fn_", StringComparison.Ordinal)) + .ToArray(); + return entries.GroupBy(static entry => entry.Name) + .Where(static group => group.Count() == 1) + .ToDictionary(static group => group.Key, static group => group.Single().Address); } private static void WithTable(string contents, Action check, bool expectFailure = false) { - var path = Path.Combine(Path.GetTempPath(), $"mkw-guest-table-{Guid.NewGuid():N}.inc"); + var path = Path.Combine(Path.GetTempPath(), $"mkw-guest-versions-{Guid.NewGuid():N}.inc"); File.WriteAllText(path, contents); try {