From e3531d17d700339828d7bab192c66fba5fcbac86 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Sat, 3 Jun 2017 14:45:52 -0700 Subject: [PATCH] Update free DSP ROM and coefficients to support GBA ucode - coef: Explicitly set 23 different values that are used by GBA UCode, and tweaked overall parameters to more closely match those 23 values. - irom: Moved a few functions to their proper places, updated BootUCode to configure DMA transfers using AX registers as well as IX registers (the GBA UCode uses this to do two sequential transfers in one call), and added partial functions used by GBA UCode. All functions were reverse-engineered solely based off of observed effects on the virtual machine: register states before-and-after, dmem interactions, and DMA transfers. The specific coefficients were observed being read from dmem, and must be exactly those values to function properly. I have no knowledge of how the official ROM implements these functions, or how it is implemented overall. Tested with The Legend of Zelda: Four Swords Adventures, Final Fantasy Crystal Chronicles, and Billy Hatcher and the Giant Egg (to download ChuChu Rocket!). --- Data/Sys/GC/dsp_coef.bin | Bin 4096 -> 4096 bytes Data/Sys/GC/dsp_rom.bin | Bin 8192 -> 8192 bytes Source/Core/Core/DSP/DSPCore.cpp | 7 +- docs/DSP/free_dsp_rom/dsp_rom.ds | 159 +++++++++++++++++++---- docs/DSP/free_dsp_rom/dsp_rom_readme.txt | 13 ++ docs/DSP/free_dsp_rom/generate_coefs.py | 34 ++++- 6 files changed, 185 insertions(+), 28 deletions(-) diff --git a/Data/Sys/GC/dsp_coef.bin b/Data/Sys/GC/dsp_coef.bin index 1137fd741ec917caab4716a3ef5d8374ef246e5a..f919013c1259f02dd2379567b491e0125acd5601 100644 GIT binary patch literal 4096 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 F{~!J1b@c!M literal 4096 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 diff --git a/Data/Sys/GC/dsp_rom.bin b/Data/Sys/GC/dsp_rom.bin index 54e03da7c7a620df76054e8422f645a3c0b97da1..f36fefb45f5f150d44b373d502fde06cf79a520e 100644 GIT binary patch delta 344 zcmZp0XmFSy9$CR~|Nno6c?%eu7?`FsNHgtks9-qq{~yEA|NoihH*he_JHP~%Q3J~y zgNZJHh#G=LkHbVaKtydoq7w^5g)0~ifTgyoon$(|z```Q!F}R}2s5>ROa~emnC3K8 zFx^-C17^={sAIa%fC9A6X`B~3$-t<6R`WE_K%h<+k3NP*2Kk#z4nR|jX{9#$4(2C4g#1z5gJV!Fa16>G`BASE3S;qT>T Ym5i6T>%(BdARQ+a0}|XUz-ht@0KfEtp8x;= delta 218 zcmZp0XmFSy9_h<)|Nno6c?%eu7?`FsNHgtk@MSpi{~yEA|NoihH*he_JHP~%Q3J~y zgNZJHh#G=LkHbVaKtydoq7w^5wS5^5fTgyo{b4%Lz`!)O!JX;8+CMORPJ=IyeUj+_ z0}D_*c(MS?E`>gZPKHJXJ|>2L|4%YJ`G1b#>HqT#&;Flfc>e!1(9Gb;8yMv#Zcy8N hj!}wf;s&nGpP2WtfaqNuJ*=BQ2nz6R7T{dP3; known_roms = { + static const std::array known_roms = { {// Official Nintendo ROM {0x66f334fe, 0xf3b93527}, @@ -53,7 +53,10 @@ static bool VerifyRoms() {0xd9907f71, 0xb019c2fb}, // above with improved resampling coefficients - {0xd9907f71, 0xdb6880c1}}}; + {0xd9907f71, 0xdb6880c1}, + + // above with support for GBA ucode + {0x3aa4a793, 0xa4a575f5}}}; u32 hash_irom = HashAdler32((u8*)g_dsp.irom, DSP_IROM_BYTE_SIZE); u32 hash_drom = HashAdler32((u8*)g_dsp.coef, DSP_COEF_BYTE_SIZE); diff --git a/docs/DSP/free_dsp_rom/dsp_rom.ds b/docs/DSP/free_dsp_rom/dsp_rom.ds index b956aff65f..bf94ac49a4 100644 --- a/docs/DSP/free_dsp_rom/dsp_rom.ds +++ b/docs/DSP/free_dsp_rom/dsp_rom.ds @@ -57,40 +57,79 @@ param5: lr $AR0, @CMBL jmp 0x80b5 -wait_for_dsp_mbox: - lrs $AC0.M, @DMBH - andcf $AC0.M, #0x8000 - jlz wait_for_dsp_mbox+#IROM_BASE - ret - -wait_for_cpu_mbox: - lrs $AC0.M, @CMBH - andcf $AC0.M, #0x8000 - jlnz wait_for_cpu_mbox+#IROM_BASE - ret - wait_dma: lrs $AC0.M, @DSCR andcf $AC0.M, #0x0004 jlz wait_dma+#IROM_BASE ret -bootucode: +WARNPC 0x78 +ORG 0x78 +; called by GBA ucode +wait_for_cpu_mbox: + lrs $AC0.M, @CMBH + andcf $AC0.M, #0x8000 + jlnz wait_for_cpu_mbox+#IROM_BASE + ret + +WARNPC 0x7e +ORG 0x7e +; called by GBA ucode +wait_for_dsp_mbox: + lrs $AC0.M, @DMBH + andcf $AC0.M, #0x8000 + jlz wait_for_dsp_mbox+#IROM_BASE + ret + +WARNPC 0x8b +ORG 0x8b +; called by GBA ucode +dram_to_cpu: + srs @DSMAH, $AX0.H + srs @DSMAL, $AX0.L + si @DSCR, #0x1 + srs @DSPA, $AX1.H + srs @DSBL, $AX1.L + call wait_dma+#IROM_BASE + ret WARNPC 0xb5 ORG 0xb5 -sub_80b5: - set16 - clr $ACC1 - clr $ACC0 - lris $AC0.M, #0x2 - sr @DSCR, $AC0.M - sr @DSMAH, $IX0 - sr @DSMAL, $IX1 - sr @DSPA, $IX2 - sr @DSBL, $IX3 - call wait_dma+#IROM_BASE - jmpr $AR0 +bootucode: + set16 + clr $ACC0 + mrr $AC0.M, $AX1.L + andi $AC0.M, #0xffff + jz bootucode_ix+#IROM_BASE + +WARNPC 0xbc +ORG 0xbc +; called by GBA ucode +bootucode_ax: + lris $AC0.M, #0 + srs @DSCR, $AC0.M + srs @DSMAH, $AX0.H + srs @DSMAL, $AX0.L + srs @DSPA, $AX1.H + srs @DSBL, $AX1.L + call wait_dma+#IROM_BASE + +bootucode_ix: + mrr $AC0.M, $IX3 + andi $AC0.M, #0xffff + jz bootucode_epilogue+#IROM_BASE + lris $AC0.M, #0x2 + srs @DSCR, $AC0.M + sr @DSMAH, $IX0 + sr @DSMAL, $IX1 + sr @DSPA, $IX2 + sr @DSBL, $IX3 + call wait_dma+#IROM_BASE + +bootucode_epilogue: + clr $ACC1 + lr $AC1.M, @DSBL + jmpr $AR0 WARNPC 0xe7 ORG 0xe7 @@ -117,6 +156,21 @@ mix_two_add: mrr $AX0.L, $IX0 ret +WARNPC 0x1f4 +ORG 0x1f4 +; used by GBA ucode for joyboot length and is the end of some mixing function +; (for an example of hitting the full function, try running the main menu of +; Metroid Prime using the Nintendo DSP ROM). +sub_81f4: + asr16'ir $ACC1 : $AR1 + clr's $ACC0 : @$AR3, $AC1.M ; AC1.M is always #0x0 here. + ; necessary both to match register state of official ROM, and for the + ; following mul. could also be mrr $AX1.H, $AC0.M (before clearing ACC0). + mrr $AX1.H, $AX0.H + ; make the product register match. + mul's $AX1.L, $AX1.H : @$AR3, $AC1.L + ret + WARNPC 0x1f9 ORG 0x1f9 ; Args: @@ -158,6 +212,18 @@ mix_two_add_ramp: mrr $AX0.L, $IX1 ret +WARNPC 0x458 +ORG 0x458 +; used by GBA ucode for joyboot length +sub_8458: + ; AC1.L after = AC1.M before + 7. this looks really stupid, but matches + ; captured traces and seems to work. + addis $AC1.M, #0x7 + asr16 $ACC1 + srri @$AR3, $AC1.M ; or just #0x0. + srri @$AR3, $AC1.L + ret + WARNPC 0x45d ORG 0x45d mix_add_ramp: @@ -197,5 +263,48 @@ ____mix_add_ramp_end_loop: mrr $AR3, $IX2 ret +WARNPC 0x723 +ORG 0x723 +; called by GBA ucode +sub_8723: + ; in GBA-HLE, the nonce challenge is XOR'd with 0x6f646573, which happens + ; to match the values of the AX1.H register across these two calls. + xorr $AC1.M, $AX1.H + ; the value of @AR2 is always the same as AC1.M after + srrd @$AR2, $AC1.M + ret + +WARNPC 0x809 +ORG 0x809 +; called by GBA ucode +sub_8809: + ; AR2 is the only addressing register that corresponds to the dmem writes + ; could be AC1.L or AX0.L in the second call, but can't be AX0.L in the + ; third call. + srr @$AR2, $AC1.L + ; AC1.M after calling always look like either AC1.M | AC0.M or + ; AC1.M | AX0.H. TODO: Why pick AX0.H? + orr $AC1.M, $AX0.H + ; the second dmem write is incremented only in calls #3A and #3B. There, + ; IX2 is the only register set to 1, and it's specifically set to 1 in the + ; ucode. It's set to 0 in the first two calls. + addarn $AR2, $IX2 + ; obvious + srri @$AR2, $AC1.M + ret + +WARNPC 0x8e5 +ORG 0x8e5 +; used by GBA ucode for challenge nonce, logo palette/speed, and joyboot length +sub_88e5: + dar $AR1 ; always gets decremented, no effect on rest of function + lrri $AC1.M, @$AR2 + lrrd $AC1.L, @$AR2 + add $ACC0, $ACC1 ; signed addition + orr $AC0.M, $AX0.H + srri @$AR2, $AC0.M + srr @$AR2, $AC0.L + ret + WARNPC 0x1000 ORG 0x1000 diff --git a/docs/DSP/free_dsp_rom/dsp_rom_readme.txt b/docs/DSP/free_dsp_rom/dsp_rom_readme.txt index 7dc073a80b..8a3ff8c79b 100644 --- a/docs/DSP/free_dsp_rom/dsp_rom_readme.txt +++ b/docs/DSP/free_dsp_rom/dsp_rom_readme.txt @@ -1,3 +1,16 @@ +Legal GC/WII DSP IROM replacement (v0.3) +------------------------------------------------------- + +- coef: Explicitly set 23 different values that are used by GBA UCode, and + tweaked overall parameters to more closely match those 23 values. +- irom: Moved a few functions to their proper places, updated BootUCode to + configure DMA transfers using AX registers as well as IX registers (the GBA + UCode uses this to do two sequential transfers in one call), and added + partial functions used by GBA UCode. + +ligfx +2/june/2017 + Legal GC/WII DSP IROM replacement (v0.2.1) ------------------------------------------------------- diff --git a/docs/DSP/free_dsp_rom/generate_coefs.py b/docs/DSP/free_dsp_rom/generate_coefs.py index 9d3d9154b6..54aaf14d45 100644 --- a/docs/DSP/free_dsp_rom/generate_coefs.py +++ b/docs/DSP/free_dsp_rom/generate_coefs.py @@ -12,7 +12,7 @@ def convert_coefs(c): def pack_coefs(short_coefs): return b''.join(pack('>H', c) for c in short_coefs) -x = linspace(-2, 2, 512, endpoint=False) +x = linspace(-2, 2, 512, endpoint=True) w1 = hamming(512) w2 = kaiser(512, pi * 9/4) @@ -23,5 +23,37 @@ coef_3 = [sinc(n) for n in x] * w1 short_coefs = convert_coefs(coef_1) + convert_coefs(coef_2) + convert_coefs(coef_3) + [0] * 512 +# needed for GBA ucode +gba_coefs = ( + (0x03b, 0x0065), + (0x043, 0x0076), + (0x0ca, 0x3461), + (0x0e2, 0x376f), + (0x1b8, 0x007f), + (0x1b8, 0x007f), + (0x1f8, 0x0009), + (0x1fc, 0x0003), + (0x229, 0x657c), + (0x231, 0x64fc), + (0x259, 0x6143), + (0x285, 0x5aff), + (0x456, 0x102f), + (0x468, 0xf808), + (0x491, 0x6a0f), + (0x5f1, 0x0200), + (0x5f6, 0x7f65), + (0x65b, 0x0000), + (0x66b, 0x0000), + (0x66c, 0x06f2), + (0x6fe, 0x0008), + (0x723, 0xffe0), + (0x766, 0x0273), +) +for (addr, value) in gba_coefs: + old_value = short_coefs[addr] + if old_value != value: + print("At %04x: replacing %04x with %04x (diff. of % #x)" % (addr, old_value, value, value - old_value)) + short_coefs[addr] = value + with open('dsp_coef.bin', 'wb') as f: f.write(pack_coefs(short_coefs))