Restructure build workflow
* All segments are now extracted from the base ROM; the base ROM is no longer a compile time dependency * ROM segments are now positioned relatively to each rather than with hard coded addresses * Piracy checksums are calculated during build
This commit is contained in:
parent
4fd334f73a
commit
23b6bd2643
|
@ -38,7 +38,6 @@ Before you do anything you need an existing ROM to extract assets from.
|
|||
|
||||
## Compiling
|
||||
|
||||
* Run `make` to build the assets that will be included in the ROM. These files will be written to `build/ntsc-final` and are matching what's in the `extracted/ntsc-final` folder.
|
||||
* Run `make rom` to build the ROM. The ROM will be written to `build/ntsc-final/pd.z64`.
|
||||
|
||||
## How do I know the built files are matching?
|
||||
|
|
|
@ -2013,17 +2013,18 @@ ea5a2ff4e5e0a68822f62feff2c40af4 build/jap-final/files/bgdata/bg_uff_tilesZ
|
|||
f0068491f441172310f2b6868c03739d build/jap-final/files/bgdata/bg_wax_padsZ
|
||||
ea5a2ff4e5e0a68822f62feff2c40af4 build/jap-final/files/bgdata/bg_wax_tilesZ
|
||||
d41d8cd98f00b204e9800998ecf8427e build/jap-final/files/ob/ob_mid.seg
|
||||
39ef58f5babf5d619bec8b2629c26bc8 build/jap-final/ucode/boot.bin
|
||||
333e8b4f6fe9dc9b59cf3e61b4e0c224 build/jap-final/ucode/firingrange.bin
|
||||
bd6e5fc360d5e0c35ea3605e2514f205 build/jap-final/ucode/game.bin
|
||||
22d5e92bffcc67b222cf3697e96106f6 build/jap-final/ucode/gamedata.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/jap-final/ucode/inflate.bin
|
||||
c550660ff4ba024113ddb38103bf79f8 build/jap-final/ucode/lib.bin
|
||||
c47d9377956666bc0e77d6cba3dc68fb build/jap-final/ucode/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/jap-final/ucode/mpstringsE.bin
|
||||
4d1eb9e58e090aa91301917c518b5b5f build/jap-final/ucode/mpstringsF.bin
|
||||
0dfdacb249cb79aacb979509015fbab9 build/jap-final/ucode/mpstringsG.bin
|
||||
3df64b3553f9d9b77f55e7abaccb8e04 build/jap-final/ucode/mpstringsI.bin
|
||||
b60f7439adaf8b1e150ab54b590da411 build/jap-final/ucode/mpstringsJ.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/jap-final/ucode/mpstringsP.bin
|
||||
9e9ad9fdc9b6a3c249a370760fa23b26 build/jap-final/ucode/mpstringsS.bin
|
||||
538d2b75945eae069b29c46193e74790 build/jap-final/pd.z64
|
||||
39ef58f5babf5d619bec8b2629c26bc8 build/jap-final/segments/boot.bin
|
||||
333e8b4f6fe9dc9b59cf3e61b4e0c224 build/jap-final/segments/firingrange.bin
|
||||
bd6e5fc360d5e0c35ea3605e2514f205 build/jap-final/segments/game.bin
|
||||
22d5e92bffcc67b222cf3697e96106f6 build/jap-final/segments/data.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/jap-final/segments/inflate.bin
|
||||
c550660ff4ba024113ddb38103bf79f8 build/jap-final/segments/lib.bin
|
||||
c47d9377956666bc0e77d6cba3dc68fb build/jap-final/segments/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/jap-final/segments/mpstringsE.bin
|
||||
4d1eb9e58e090aa91301917c518b5b5f build/jap-final/segments/mpstringsF.bin
|
||||
0dfdacb249cb79aacb979509015fbab9 build/jap-final/segments/mpstringsG.bin
|
||||
3df64b3553f9d9b77f55e7abaccb8e04 build/jap-final/segments/mpstringsI.bin
|
||||
b60f7439adaf8b1e150ab54b590da411 build/jap-final/segments/mpstringsJ.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/jap-final/segments/mpstringsP.bin
|
||||
9e9ad9fdc9b6a3c249a370760fa23b26 build/jap-final/segments/mpstringsS.bin
|
||||
|
|
|
@ -2011,17 +2011,18 @@ ea5a2ff4e5e0a68822f62feff2c40af4 build/ntsc-1.0/files/bgdata/bg_uff_tilesZ
|
|||
f0068491f441172310f2b6868c03739d build/ntsc-1.0/files/bgdata/bg_wax_padsZ
|
||||
ea5a2ff4e5e0a68822f62feff2c40af4 build/ntsc-1.0/files/bgdata/bg_wax_tilesZ
|
||||
d41d8cd98f00b204e9800998ecf8427e build/ntsc-1.0/files/ob/ob_mid.seg
|
||||
402561223a33f48461e302e1cca12129 build/ntsc-1.0/ucode/boot.bin
|
||||
cb373c94109322d081a57b142fdd9999 build/ntsc-1.0/ucode/firingrange.bin
|
||||
5181a0d11cf8f24370a3f2d3b29e522e build/ntsc-1.0/ucode/game.bin
|
||||
b21679a1b2dabd721bc4afee11bf5266 build/ntsc-1.0/ucode/gamedata.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/ntsc-1.0/ucode/inflate.bin
|
||||
3155eece856e9fbd9bc47d03463cfc1b build/ntsc-1.0/ucode/lib.bin
|
||||
fe4034c01c91bd10e488fe93389b4104 build/ntsc-1.0/ucode/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/ntsc-1.0/ucode/mpstringsE.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/ucode/mpstringsF.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/ucode/mpstringsG.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/ucode/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/ntsc-1.0/ucode/mpstringsJ.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/ucode/mpstringsP.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/ucode/mpstringsS.bin
|
||||
7f4171b0c8d17815be37913f535e4e93 build/ntsc-1.0/pd.z64
|
||||
402561223a33f48461e302e1cca12129 build/ntsc-1.0/segments/boot.bin
|
||||
cb373c94109322d081a57b142fdd9999 build/ntsc-1.0/segments/firingrange.bin
|
||||
5181a0d11cf8f24370a3f2d3b29e522e build/ntsc-1.0/segments/game.bin
|
||||
b21679a1b2dabd721bc4afee11bf5266 build/ntsc-1.0/segments/data.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/ntsc-1.0/segments/inflate.bin
|
||||
3155eece856e9fbd9bc47d03463cfc1b build/ntsc-1.0/segments/lib.bin
|
||||
fe4034c01c91bd10e488fe93389b4104 build/ntsc-1.0/segments/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/ntsc-1.0/segments/mpstringsE.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/segments/mpstringsF.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/segments/mpstringsG.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/segments/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/ntsc-1.0/segments/mpstringsJ.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/segments/mpstringsP.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-1.0/segments/mpstringsS.bin
|
||||
|
|
|
@ -2010,17 +2010,18 @@ ea5a2ff4e5e0a68822f62feff2c40af4 build/ntsc-beta/files/bgdata/bg_uff_tilesZ
|
|||
c6f0dd6193685637763d426dfce837fb build/ntsc-beta/files/bgdata/bg_wax_padsZ
|
||||
ea5a2ff4e5e0a68822f62feff2c40af4 build/ntsc-beta/files/bgdata/bg_wax_tilesZ
|
||||
d41d8cd98f00b204e9800998ecf8427e build/ntsc-beta/files/ob/ob_mid.seg
|
||||
74cb41628ed5784a8ad48c6398b0ce83 build/ntsc-beta/ucode/boot.bin
|
||||
a12b5437510403bb09b3cceb45dd2a10 build/ntsc-beta/ucode/firingrange.bin
|
||||
daae19f7ce11d3f3e1f98d543ad856f5 build/ntsc-beta/ucode/game.bin
|
||||
cab47b8c30b1be608c1c5c1db08342de build/ntsc-beta/ucode/gamedata.bin
|
||||
d13f25c1c59fb96346ac23301ccd9d7d build/ntsc-beta/ucode/inflate.bin
|
||||
14aa42e2f0f215d931900d25ab70e576 build/ntsc-beta/ucode/lib.bin
|
||||
8aaec8cc806ec62d2f70eaa08282e9c0 build/ntsc-beta/ucode/mpconfigs.bin
|
||||
d52a0fc2e90e03b610879b50df4c0fd4 build/ntsc-beta/ucode/mpstringsE.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/ucode/mpstringsF.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/ucode/mpstringsG.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/ucode/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/ntsc-beta/ucode/mpstringsJ.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/ucode/mpstringsP.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/ucode/mpstringsS.bin
|
||||
aa93f4df16fceada399a749f5ad2f273 build/ntsc-beta/pd.z64
|
||||
74cb41628ed5784a8ad48c6398b0ce83 build/ntsc-beta/segments/boot.bin
|
||||
a12b5437510403bb09b3cceb45dd2a10 build/ntsc-beta/segments/firingrange.bin
|
||||
daae19f7ce11d3f3e1f98d543ad856f5 build/ntsc-beta/segments/game.bin
|
||||
cab47b8c30b1be608c1c5c1db08342de build/ntsc-beta/segments/data.bin
|
||||
d13f25c1c59fb96346ac23301ccd9d7d build/ntsc-beta/segments/inflate.bin
|
||||
14aa42e2f0f215d931900d25ab70e576 build/ntsc-beta/segments/lib.bin
|
||||
8aaec8cc806ec62d2f70eaa08282e9c0 build/ntsc-beta/segments/mpconfigs.bin
|
||||
d52a0fc2e90e03b610879b50df4c0fd4 build/ntsc-beta/segments/mpstringsE.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/segments/mpstringsF.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/segments/mpstringsG.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/segments/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/ntsc-beta/segments/mpstringsJ.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/segments/mpstringsP.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-beta/segments/mpstringsS.bin
|
||||
|
|
|
@ -2011,17 +2011,18 @@ ea5a2ff4e5e0a68822f62feff2c40af4 build/ntsc-final/files/bgdata/bg_uff_tilesZ
|
|||
f0068491f441172310f2b6868c03739d build/ntsc-final/files/bgdata/bg_wax_padsZ
|
||||
ea5a2ff4e5e0a68822f62feff2c40af4 build/ntsc-final/files/bgdata/bg_wax_tilesZ
|
||||
d41d8cd98f00b204e9800998ecf8427e build/ntsc-final/files/ob/ob_mid.seg
|
||||
2a1aa1eff3cdfe5dc3e91a2e773a55b9 build/ntsc-final/ucode/boot.bin
|
||||
cb373c94109322d081a57b142fdd9999 build/ntsc-final/ucode/firingrange.bin
|
||||
ed0462324d1287de21611707172d316a build/ntsc-final/ucode/game.bin
|
||||
11c9c4c2737f66e7312949909b894dcc build/ntsc-final/ucode/gamedata.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/ntsc-final/ucode/inflate.bin
|
||||
6a227624d708b43a10f220e005aef486 build/ntsc-final/ucode/lib.bin
|
||||
fe4034c01c91bd10e488fe93389b4104 build/ntsc-final/ucode/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/ntsc-final/ucode/mpstringsE.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/ntsc-final/ucode/mpstringsJ.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/ucode/mpstringsP.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/ucode/mpstringsF.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/ucode/mpstringsG.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/ucode/mpstringsI.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/ucode/mpstringsS.bin
|
||||
e03b088b6ac9e0080440efed07c1e40f build/ntsc-final/pd.z64
|
||||
2a1aa1eff3cdfe5dc3e91a2e773a55b9 build/ntsc-final/segments/boot.bin
|
||||
cb373c94109322d081a57b142fdd9999 build/ntsc-final/segments/firingrange.bin
|
||||
ed0462324d1287de21611707172d316a build/ntsc-final/segments/game.bin
|
||||
11c9c4c2737f66e7312949909b894dcc build/ntsc-final/segments/data.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/ntsc-final/segments/inflate.bin
|
||||
6a227624d708b43a10f220e005aef486 build/ntsc-final/segments/lib.bin
|
||||
fe4034c01c91bd10e488fe93389b4104 build/ntsc-final/segments/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/ntsc-final/segments/mpstringsE.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/ntsc-final/segments/mpstringsJ.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/segments/mpstringsP.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/segments/mpstringsF.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/segments/mpstringsG.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/segments/mpstringsI.bin
|
||||
e4f45399a4f97e3fd6733f0f6919d28d build/ntsc-final/segments/mpstringsS.bin
|
||||
|
|
|
@ -2011,17 +2011,18 @@ ea5a2ff4e5e0a68822f62feff2c40af4 build/pal-beta/files/bgdata/bg_uff_tilesZ
|
|||
f0068491f441172310f2b6868c03739d build/pal-beta/files/bgdata/bg_wax_padsZ
|
||||
ea5a2ff4e5e0a68822f62feff2c40af4 build/pal-beta/files/bgdata/bg_wax_tilesZ
|
||||
d41d8cd98f00b204e9800998ecf8427e build/pal-beta/files/ob/ob_mid.seg
|
||||
541e374b58a36056f73ad02a2bbb5f75 build/pal-beta/ucode/boot.bin
|
||||
333e8b4f6fe9dc9b59cf3e61b4e0c224 build/pal-beta/ucode/firingrange.bin
|
||||
ad5835b91b7e252ef8f4a421a44eb12b build/pal-beta/ucode/game.bin
|
||||
bca5001a5dd0ef9aab24ba085f27eb40 build/pal-beta/ucode/gamedata.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/pal-beta/ucode/inflate.bin
|
||||
7a859fcb6e89426543b5a207cc388f82 build/pal-beta/ucode/lib.bin
|
||||
fe4034c01c91bd10e488fe93389b4104 build/pal-beta/ucode/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-beta/ucode/mpstringsE.bin
|
||||
bed567631daf314f79ec8a2aa994f3a0 build/pal-beta/ucode/mpstringsF.bin
|
||||
27be1b7f42826d0910b2fd549f969a63 build/pal-beta/ucode/mpstringsG.bin
|
||||
fed3dc54a3564f477fb7d548ac365514 build/pal-beta/ucode/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/pal-beta/ucode/mpstringsJ.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-beta/ucode/mpstringsP.bin
|
||||
d9501d67ead982fdd5cb5ffaf3091201 build/pal-beta/ucode/mpstringsS.bin
|
||||
ad2de210a3455ba5ec541f0c78d91444 build/pal-beta/pd.z64
|
||||
541e374b58a36056f73ad02a2bbb5f75 build/pal-beta/segments/boot.bin
|
||||
333e8b4f6fe9dc9b59cf3e61b4e0c224 build/pal-beta/segments/firingrange.bin
|
||||
ad5835b91b7e252ef8f4a421a44eb12b build/pal-beta/segments/game.bin
|
||||
bca5001a5dd0ef9aab24ba085f27eb40 build/pal-beta/segments/data.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/pal-beta/segments/inflate.bin
|
||||
7a859fcb6e89426543b5a207cc388f82 build/pal-beta/segments/lib.bin
|
||||
fe4034c01c91bd10e488fe93389b4104 build/pal-beta/segments/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-beta/segments/mpstringsE.bin
|
||||
bed567631daf314f79ec8a2aa994f3a0 build/pal-beta/segments/mpstringsF.bin
|
||||
27be1b7f42826d0910b2fd549f969a63 build/pal-beta/segments/mpstringsG.bin
|
||||
fed3dc54a3564f477fb7d548ac365514 build/pal-beta/segments/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/pal-beta/segments/mpstringsJ.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-beta/segments/mpstringsP.bin
|
||||
d9501d67ead982fdd5cb5ffaf3091201 build/pal-beta/segments/mpstringsS.bin
|
||||
|
|
|
@ -2011,17 +2011,18 @@ ea5a2ff4e5e0a68822f62feff2c40af4 build/pal-final/files/bgdata/bg_uff_tilesZ
|
|||
f0068491f441172310f2b6868c03739d build/pal-final/files/bgdata/bg_wax_padsZ
|
||||
ea5a2ff4e5e0a68822f62feff2c40af4 build/pal-final/files/bgdata/bg_wax_tilesZ
|
||||
d41d8cd98f00b204e9800998ecf8427e build/pal-final/files/ob/ob_mid.seg
|
||||
7c4233976802db99f90c6c0fede1080b build/pal-final/ucode/boot.bin
|
||||
333e8b4f6fe9dc9b59cf3e61b4e0c224 build/pal-final/ucode/firingrange.bin
|
||||
4e506821044251aecc10ec332389c576 build/pal-final/ucode/game.bin
|
||||
1c49c171e829a5407f0ae5fd28a123cd build/pal-final/ucode/gamedata.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/pal-final/ucode/inflate.bin
|
||||
b83973db626573e024608444e5d74461 build/pal-final/ucode/lib.bin
|
||||
7f5540dd6fff2039b2ce05bf57ac5611 build/pal-final/ucode/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-final/ucode/mpstringsE.bin
|
||||
4d1eb9e58e090aa91301917c518b5b5f build/pal-final/ucode/mpstringsF.bin
|
||||
0dfdacb249cb79aacb979509015fbab9 build/pal-final/ucode/mpstringsG.bin
|
||||
3df64b3553f9d9b77f55e7abaccb8e04 build/pal-final/ucode/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/pal-final/ucode/mpstringsJ.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-final/ucode/mpstringsP.bin
|
||||
9e9ad9fdc9b6a3c249a370760fa23b26 build/pal-final/ucode/mpstringsS.bin
|
||||
d9b5cd305d228424891ce38e71bc9213 build/pal-final/pd.z64
|
||||
7c4233976802db99f90c6c0fede1080b build/pal-final/segments/boot.bin
|
||||
333e8b4f6fe9dc9b59cf3e61b4e0c224 build/pal-final/segments/firingrange.bin
|
||||
4e506821044251aecc10ec332389c576 build/pal-final/segments/game.bin
|
||||
1c49c171e829a5407f0ae5fd28a123cd build/pal-final/segments/data.bin
|
||||
843285fdc0e80a77576eeb73940d2fd3 build/pal-final/segments/inflate.bin
|
||||
b83973db626573e024608444e5d74461 build/pal-final/segments/lib.bin
|
||||
7f5540dd6fff2039b2ce05bf57ac5611 build/pal-final/segments/mpconfigs.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-final/segments/mpstringsE.bin
|
||||
4d1eb9e58e090aa91301917c518b5b5f build/pal-final/segments/mpstringsF.bin
|
||||
0dfdacb249cb79aacb979509015fbab9 build/pal-final/segments/mpstringsG.bin
|
||||
3df64b3553f9d9b77f55e7abaccb8e04 build/pal-final/segments/mpstringsI.bin
|
||||
302f7aa0464c781187551fcd3870aec2 build/pal-final/segments/mpstringsJ.bin
|
||||
529b54a03375af2ff74eb3367cbac294 build/pal-final/segments/mpstringsP.bin
|
||||
9e9ad9fdc9b6a3c249a370760fa23b26 build/pal-final/segments/mpstringsS.bin
|
||||
|
|
4030
ld/filesegments.inc
4030
ld/filesegments.inc
File diff suppressed because it is too large
Load Diff
458
ld/pd.ld
458
ld/pd.ld
|
@ -8,36 +8,57 @@
|
|||
#define VERSION_PAL_FINAL 4
|
||||
#define VERSION_JAP_FINAL 5
|
||||
|
||||
#define BEGIN_SEG(name) \
|
||||
_##name##SegmentStart = ADDR(.name); \
|
||||
_##name##SegmentRomStart = __rompos; \
|
||||
.name __rampos : AT(__rompos)
|
||||
|
||||
#define END_SEG(name) \
|
||||
__rompos += SIZEOF(.name); \
|
||||
__rampos = ADDR(.name) + SIZEOF(.name); \
|
||||
_##name##SegmentEnd = ADDR(.name) + SIZEOF(.name); \
|
||||
_##name##SegmentRomEnd = __rompos;
|
||||
|
||||
#define BEGIN_NOLOAD(name) \
|
||||
_##name##SegmentStart = ADDR(.name); \
|
||||
_##name##SegmentRomStart = __rompos; \
|
||||
.name (NOLOAD) : AT(__rompos)
|
||||
|
||||
#define END_NOLOAD(name) \
|
||||
__rompos += SIZEOF(.name); \
|
||||
_##name##SegmentEnd = ADDR(.name) + SIZEOF(.name); \
|
||||
_##name##SegmentRomEnd = __rompos;
|
||||
|
||||
#define MPSTRINGS(lang) \
|
||||
.mpstrings##lang : AT(__rompos) { \
|
||||
BEGIN_SEG(mpstrings##lang) \
|
||||
{ \
|
||||
build/ROMID/mpstrings/ROMID/mpstrings##lang.o (.data); \
|
||||
} \
|
||||
__rompos += SIZEOF(.mpstrings##lang);
|
||||
END_SEG(mpstrings##lang)
|
||||
|
||||
/******************************************************************************
|
||||
* ROM Allocations
|
||||
* ----------------------------------------------------------------------------
|
||||
* The lib, data and game segments are compressed in the final ROM. To do this,
|
||||
* we build them uncompressed here but place them past the end of the ROM, then
|
||||
* a later script compresses them and writes them into the ROM.
|
||||
*
|
||||
* These constants are defining how much space is reserved for the compressed
|
||||
* segments. If these segments are edited and grow to a point that their
|
||||
* compressed size exceeds the allocation then their allocations will need to be
|
||||
* increased.
|
||||
*/
|
||||
|
||||
#define ROMALLOCATION_LIB 0x036800
|
||||
#define ROMALLOCATION_DATA 0x015000
|
||||
#define ROMALLOCATION_GAME 0x151980
|
||||
#define ROMALLOCATION_FILES 0xe8dba0
|
||||
|
||||
OUTPUT_ARCH (mips)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
_gamedataSegmentStart = 0x80059fe0;
|
||||
_gamedataSegmentRomStart = 0x39850;
|
||||
_inflateSegmentRomStart = 0x4e850;
|
||||
_ziplistSegmentRomStart = 0x4fc40;
|
||||
_textureSegmentRomStart = 0x01ff7ca0;
|
||||
_textureSegmentRomEnd = 0x01ffea20;
|
||||
_rspMicrocodeStart = 0x80059fe0;
|
||||
_rspMicrocodeStartPlusOne = 0x80059fe1;
|
||||
_rspMicrocodeEnd = 0x8005afe0;
|
||||
_mpconfigsSegmentRomStart = 0x7d0a40;
|
||||
_mpstringsESegmentRomStart = 0x007d1c20; _mpstringsESegmentRomEnd = 0x007d5320;
|
||||
_mpstringsJSegmentRomStart = 0x007d5320; _mpstringsJSegmentRomEnd = 0x007d8a20;
|
||||
_mpstringsPSegmentRomStart = 0x007d8a20; _mpstringsPSegmentRomEnd = 0x007dc120;
|
||||
_mpstringsGSegmentRomStart = 0x007dc120; _mpstringsGSegmentRomEnd = 0x007df820;
|
||||
_mpstringsFSegmentRomStart = 0x007df820; _mpstringsFSegmentRomEnd = 0x007e2f20;
|
||||
_mpstringsSSegmentRomStart = 0x007e2f20; _mpstringsSSegmentRomEnd = 0x007e6620;
|
||||
_mpstringsISegmentRomStart = 0x007e6620; _mpstringsISegmentRomEnd = 0x007e9d20;
|
||||
|
||||
#if VERSION >= VERSION_NTSC_FINAL
|
||||
_bssSegmentEnd = 0x7f1b99e0;
|
||||
_val7f116f34 = 0x0339;
|
||||
_val7f117634 = 0x0422;
|
||||
_val7f1183f8 = 0x070a;
|
||||
|
@ -55,9 +76,7 @@ SECTIONS
|
|||
_val7f11bb48 = 0x112a;
|
||||
_val7f11c1d0 = 0x1286;
|
||||
_val7f11c378 = 0x12c1;
|
||||
_checksum7f15c9ac = 0x2c7a82c8;
|
||||
#else
|
||||
_bssSegmentEnd = 0x7f1b9870;
|
||||
_val7f116f34 = 0x0336;
|
||||
_val7f117634 = 0x041f;
|
||||
_val7f1183f8 = 0x06fc;
|
||||
|
@ -75,61 +94,200 @@ SECTIONS
|
|||
_val7f11bb48 = 0x1067;
|
||||
_val7f11c1d0 = 0x11c3;
|
||||
_val7f11c378 = 0x11fe;
|
||||
_checksum7f15c9ac = 0x2c7b42f8;
|
||||
#endif
|
||||
|
||||
_firingrangeSegmentRomStart = 0x007e9d20;
|
||||
_firingrangeSegmentRomEnd = 0x007eb270;
|
||||
|
||||
_antipiracyUncloakWriteAddress = 0x7002a324;
|
||||
|
||||
osResetType = 0x8000030c;
|
||||
osCicId = 0x80000310;
|
||||
|
||||
/***************************************************************************
|
||||
* romheader
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00000000 - 0x00000040
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rompos = 0;
|
||||
.boot 0x70001000 : AT(__rompos) {
|
||||
|
||||
BEGIN_SEG(romheader)
|
||||
{
|
||||
build/ROMID/romheader.o (.data);
|
||||
}
|
||||
END_SEG(romheader)
|
||||
|
||||
/***************************************************************************
|
||||
* rspboot
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00000040 - 0x00001000
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rompos = 0x40;
|
||||
|
||||
BEGIN_SEG(rspboot)
|
||||
{
|
||||
build/ROMID/rspboot.o (.data);
|
||||
}
|
||||
END_SEG(rspboot)
|
||||
|
||||
/***************************************************************************
|
||||
* boot
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00001000 - 0x00003050
|
||||
* RAM range: 0x70001000 - 0x70003050
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rampos = 0x70001000;
|
||||
|
||||
BEGIN_SEG(boot)
|
||||
{
|
||||
build/ROMID/boot/boot.o (.text);
|
||||
build/ROMID/boot/boot.o (.data);
|
||||
}
|
||||
__rompos += SIZEOF(.boot);
|
||||
END_SEG(boot)
|
||||
|
||||
.lib 0x70003050 : AT(__rompos) {
|
||||
/***************************************************************************
|
||||
* lib
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00003050 - 0x00039850 (compressed)
|
||||
* RAM range: 0x70003050 - 0x70059fe0
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
_libzipSegmentRomStart = __rompos;
|
||||
__rompos = 0x20000000;
|
||||
|
||||
BEGIN_SEG(lib)
|
||||
{
|
||||
LIBFILES(.text)
|
||||
LIBFILES(.rodata)
|
||||
}
|
||||
__rompos += SIZEOF(.lib);
|
||||
END_SEG(lib)
|
||||
|
||||
.gamedata 0x80059fe0 : AT(__rompos) {
|
||||
/***************************************************************************
|
||||
* data
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00039850 - 0x0004e850 (compressed)
|
||||
* RAM range: 0x80059fe0 - 0x8008ae20
|
||||
* -------------------------------------------------------------------------
|
||||
* For some reason we can't just add 0x10000000 to __rampos, but we can
|
||||
* recalculate it so that's what we do.
|
||||
*/
|
||||
|
||||
_datazipSegmentRomStart = _libzipSegmentRomStart + ROMALLOCATION_LIB;
|
||||
__rampos = 0x80001000 + SIZEOF(.boot) + SIZEOF(.lib);
|
||||
|
||||
BEGIN_SEG(data)
|
||||
{
|
||||
GAMEFILES(.data)
|
||||
}
|
||||
__rompos += SIZEOF(.gamedata);
|
||||
END_SEG(data)
|
||||
|
||||
.gvars 0x8008ae20 : AT(__rompos) {
|
||||
_rspMicrocodeStart = _dataSegmentStart;
|
||||
_rspMicrocodeStartPlusOne = _rspMicrocodeStart + 1;
|
||||
_rspMicrocodeEnd = _rspMicrocodeStart + 0x1000;
|
||||
|
||||
/***************************************************************************
|
||||
* bss
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: N/A
|
||||
* RAM range: 0x8008ae20 - 0x800ad1c0
|
||||
* -------------------------------------------------------------------------
|
||||
* BSS is currently implemented using data instead of BSS, because having
|
||||
* all BSS in one file causes the linker to choose the addresses
|
||||
* non-linearly. Eventually this file will be spread out into the code files
|
||||
* and it can become BSS at that point.
|
||||
*
|
||||
* For now, place it past the end of the ROM, where it'll be truncated.
|
||||
* We can do this because we only memory addresses for this segment, not
|
||||
* ROM addresses.
|
||||
*/
|
||||
|
||||
BEGIN_NOLOAD(gvars)
|
||||
{
|
||||
build/ROMID/gvars/gvars.o (.data);
|
||||
}
|
||||
__rompos += SIZEOF(.gvars);
|
||||
END_NOLOAD(gvars)
|
||||
|
||||
.game 0x7f000000 : AT(__rompos) {
|
||||
GAMEFILES(.text)
|
||||
GAMEFILES(.rodata)
|
||||
}
|
||||
__rompos += SIZEOF(.game);
|
||||
/***************************************************************************
|
||||
* inflate
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x0004e850 - 0x0004fc40
|
||||
* RAM range: 0x70200000 - 0x702013f0
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.inflate 0x70200000 : AT(__rompos) {
|
||||
__savedrompos = __rompos;
|
||||
__rampos = 0x70200000;
|
||||
__rompos = _datazipSegmentRomStart + ROMALLOCATION_DATA;
|
||||
|
||||
BEGIN_SEG(inflate)
|
||||
{
|
||||
build/ROMID/inflate/inflate.o (.text);
|
||||
build/ROMID/inflate/inflate.o (.data);
|
||||
}
|
||||
__rompos += SIZEOF(.inflate);
|
||||
END_SEG(inflate)
|
||||
|
||||
.mpconfigs : AT(__rompos) {
|
||||
/***************************************************************************
|
||||
* game
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x0004fc40 - 0x001a15c0 (compressed)
|
||||
* RAM range: 0x7f000000 - 0x7f1b99e0
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
_gamezipSegmentRomStart = __rompos;
|
||||
__rompos = __savedrompos;
|
||||
__rampos = 0x7f000000;
|
||||
|
||||
BEGIN_SEG(game)
|
||||
{
|
||||
GAMEFILES(.text)
|
||||
GAMEFILES(.rodata)
|
||||
}
|
||||
END_SEG(game)
|
||||
|
||||
/***************************************************************************
|
||||
* animations
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x001a15c0 - 0x007d0a40
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rompos = _inflateSegmentRomEnd + ROMALLOCATION_GAME;
|
||||
|
||||
BEGIN_SEG(animations)
|
||||
{
|
||||
build/ROMID/animations.o (.data);
|
||||
}
|
||||
END_SEG(animations)
|
||||
|
||||
/***************************************************************************
|
||||
* mpconfigs
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x007d0a40 - 0x007d1c20
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(mpconfigs)
|
||||
{
|
||||
build/ROMID/mpconfigs/mpconfigs.o (.data);
|
||||
}
|
||||
__rompos += SIZEOF(.mpconfigs);
|
||||
END_SEG(mpconfigs)
|
||||
|
||||
.firingrange : AT(__rompos) {
|
||||
build/ROMID/firingrange/firingrange.o (.data);
|
||||
}
|
||||
__rompos += SIZEOF(.firingrange);
|
||||
/***************************************************************************
|
||||
* mpstrings
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x007d1c20 - 0x007e9d20
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MPSTRINGS(E)
|
||||
MPSTRINGS(J)
|
||||
|
@ -139,14 +297,214 @@ SECTIONS
|
|||
MPSTRINGS(S)
|
||||
MPSTRINGS(I)
|
||||
|
||||
__rompos = 0xed83a0;
|
||||
/***************************************************************************
|
||||
* firingrange
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x007e9d20 - 0x007eb270
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(firingrange)
|
||||
{
|
||||
build/ROMID/firingrange/firingrange.o (.data);
|
||||
}
|
||||
END_SEG(firingrange)
|
||||
|
||||
/***************************************************************************
|
||||
* unknown1
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x007eb270 - 0x007ebdc0
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(unknown1)
|
||||
{
|
||||
build/ROMID/unknown1.o (.data);
|
||||
}
|
||||
END_SEG(unknown1)
|
||||
|
||||
/***************************************************************************
|
||||
* unknown2
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x007ebdc0 - 0x007f2390
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(unknown2)
|
||||
{
|
||||
build/ROMID/unknown2.o (.data);
|
||||
}
|
||||
END_SEG(unknown2)
|
||||
|
||||
/***************************************************************************
|
||||
* fonts
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x007f2390 - 0x0080a250
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(fonts)
|
||||
{
|
||||
build/ROMID/fonts.o (.data);
|
||||
}
|
||||
END_SEG(fonts)
|
||||
|
||||
/***************************************************************************
|
||||
* sfxctl
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x0080a250 - 0x00839dd0
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(sfxctl)
|
||||
{
|
||||
build/ROMID/sfx.ctl.o (.data);
|
||||
}
|
||||
END_SEG(sfxctl)
|
||||
|
||||
/***************************************************************************
|
||||
* sfxtbl
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00839dd0 - 0x00cfbf30
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(sfxtbl)
|
||||
{
|
||||
build/ROMID/sfx.tbl.o (.data);
|
||||
}
|
||||
END_SEG(sfxtbl)
|
||||
|
||||
/***************************************************************************
|
||||
* seqctl
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00cfbf30 - 0x00d05f90
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(seqctl)
|
||||
{
|
||||
build/ROMID/seq.ctl.o (.data);
|
||||
}
|
||||
END_SEG(seqctl)
|
||||
|
||||
/***************************************************************************
|
||||
* seqtbl
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00d05f90 - 0x00e82000
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(seqtbl)
|
||||
{
|
||||
build/ROMID/seq.tbl.o (.data);
|
||||
}
|
||||
END_SEG(seqtbl)
|
||||
|
||||
/***************************************************************************
|
||||
* sequences
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00e82000 - 0x00ed83a0
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(sequences)
|
||||
{
|
||||
build/ROMID/sequences.o (.data);
|
||||
}
|
||||
END_SEG(sequences)
|
||||
|
||||
/***************************************************************************
|
||||
* files
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x00ed83a0 - 0x01d5ca00
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
. = 0;
|
||||
_filesSegmentRomStart = __rompos;
|
||||
_filesSegmentRamStart = .;
|
||||
|
||||
#include "filesegments.inc"
|
||||
|
||||
_filesSegmentRomEnd = __rompos;
|
||||
|
||||
/***************************************************************************
|
||||
* filenames
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x01d5ca00 - 0x01d5e980
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rampos = 0;
|
||||
|
||||
BEGIN_SEG(filenames)
|
||||
{
|
||||
build/ROMID/filenames/filenames.o (.data);
|
||||
build/ROMID/filenames/filenames.o (.rodata);
|
||||
}
|
||||
END_SEG(filenames)
|
||||
|
||||
/***************************************************************************
|
||||
* textures
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x01d65f40 - 0x01fffe00
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rompos = _filesSegmentRomStart + ROMALLOCATION_FILES;
|
||||
__rampos = 0;
|
||||
|
||||
BEGIN_SEG(textures)
|
||||
{
|
||||
build/ROMID/textures.o (.data);
|
||||
}
|
||||
END_SEG(textures)
|
||||
|
||||
_texturesSegmentTableStart = _texturesSegmentRomEnd - 0x6d80;
|
||||
_texturesSegmentTableEnd = _texturesSegmentRomEnd;
|
||||
|
||||
/***************************************************************************
|
||||
* copyright
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x01ffea20 - 0x01fff550
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
__rampos = 0;
|
||||
|
||||
BEGIN_SEG(copyright)
|
||||
{
|
||||
build/ROMID/copyright.o (.data);
|
||||
}
|
||||
END_SEG(copyright)
|
||||
|
||||
/***************************************************************************
|
||||
* accessingpak
|
||||
* -------------------------------------------------------------------------
|
||||
* ROM range: 0x01fff550 - 0x01fffe00
|
||||
* RAM range: N/A
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BEGIN_SEG(accessingpak)
|
||||
{
|
||||
build/ROMID/accessingpak.o (.data);
|
||||
}
|
||||
END_SEG(accessingpak)
|
||||
|
||||
/DISCARD/ : {
|
||||
* (.MIPS.abiflags);
|
||||
* (.options);
|
||||
|
|
|
@ -110,8 +110,8 @@ glabel func000010a4
|
|||
/* 10d8: 00042300 */ sll $a0,$a0,0xc
|
||||
/* 10dc: 3c028009 */ lui $v0,%hi(var8008ae20)
|
||||
/* 10e0: 8c42ae20 */ lw $v0,%lo(var8008ae20)($v0)
|
||||
/* 10e4: 3c097f1c */ lui $t1,%hi(_bssSegmentEnd)
|
||||
/* 10e8: 252999e0 */ addiu $t1,$t1,%lo(_bssSegmentEnd)
|
||||
/* 10e4: 3c097f1c */ lui $t1,%hi(_gameSegmentEnd)
|
||||
/* 10e8: 252999e0 */ addiu $t1,$t1,%lo(_gameSegmentEnd)
|
||||
/* 10ec: 3c0a7f00 */ lui $t2,%hi(func0f000000)
|
||||
/* 10f0: 254a0000 */ addiu $t2,$t2,%lo(func0f000000)
|
||||
/* 10f4: 012a4823 */ subu $t1,$t1,$t2
|
||||
|
@ -511,20 +511,20 @@ glabel func00001634
|
|||
/* 166c: 00000000 */ nop
|
||||
);
|
||||
|
||||
extern void *_gamedataSegmentStart;
|
||||
extern void *_dataSegmentStart;
|
||||
|
||||
// func00001670
|
||||
void *getSetupRamAddr(void)
|
||||
{
|
||||
return &_gamedataSegmentStart;
|
||||
return &_dataSegmentStart;
|
||||
}
|
||||
|
||||
extern void *_gamedataSegmentRomStart;
|
||||
extern void *_datazipSegmentRomStart;
|
||||
|
||||
// func0000167c
|
||||
void *getSetupRomAddr(void)
|
||||
{
|
||||
return &_gamedataSegmentRomStart;
|
||||
return &_datazipSegmentRomStart;
|
||||
}
|
||||
|
||||
extern void *_inflateSegmentRomStart;
|
||||
|
@ -541,11 +541,11 @@ void *getInflateRomAddr2(void)
|
|||
return &_inflateSegmentRomStart;
|
||||
}
|
||||
|
||||
extern void *_ziplistSegmentRomStart;
|
||||
extern void *_gamezipSegmentRomStart;
|
||||
|
||||
void *getZiplistSegmentRomstart(void)
|
||||
{
|
||||
return &_ziplistSegmentRomStart;
|
||||
return &_gamezipSegmentRomStart;
|
||||
}
|
||||
|
||||
GLOBAL_ASM(
|
||||
|
@ -1353,8 +1353,8 @@ glabel func00002148
|
|||
/* 228c: 1420fffc */ bnez $at,.L00002280
|
||||
/* 2290: 006e1826 */ xor $v1,$v1,$t6
|
||||
.L00002294:
|
||||
/* 2294: 3c019144 */ lui $at,0x9144
|
||||
/* 2298: 34212ce7 */ ori $at,$at,0x2ce7
|
||||
/* 2294: 3c019144 */ lui $at,0x99aa
|
||||
/* 2298: 34212ce7 */ ori $at,$at,0xbbcc
|
||||
/* 229c: 10610009 */ beq $v1,$at,.L000022c4
|
||||
/* 22a0: 00001025 */ or $v0,$zero,$zero
|
||||
/* 22a4: 3c038009 */ lui $v1,%hi(var80095210)
|
||||
|
|
|
@ -494,8 +494,8 @@ glabel cheatMenuHandleDialog
|
|||
/* f1079fc: 1420fffb */ bnez $at,.L0f1079ec
|
||||
/* f107a00: 00781826 */ xor $v1,$v1,$t8
|
||||
.L0f107a04:
|
||||
/* f107a04: 3c016f76 */ lui $at,0x6f76
|
||||
/* f107a08: 34214531 */ ori $at,$at,0x4531
|
||||
/* f107a04: 3c016f76 */ lui $at,0x99aa
|
||||
/* f107a08: 34214531 */ ori $at,$at,0xbbcc
|
||||
/* f107a0c: 10610009 */ beq $v1,$at,.L0f107a34
|
||||
/* f107a10: 24c20050 */ addiu $v0,$a2,0x50
|
||||
/* f107a14: 24440010 */ addiu $a0,$v0,0x10
|
||||
|
|
|
@ -3962,7 +3962,7 @@ void chrUncloak(struct chrdata *chr, bool value)
|
|||
i++;
|
||||
}
|
||||
|
||||
if (checksum != CHECKSUM_7F0225CC) {
|
||||
if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
extern volatile u32 _antipiracyUncloakWriteAddress[];
|
||||
_antipiracyUncloakWriteAddress[-2] = 0;
|
||||
}
|
||||
|
@ -10304,9 +10304,9 @@ glabel var7f1a8948
|
|||
/* f0286f4: 0212082b */ sltu $at,$s0,$s2
|
||||
/* f0286f8: 1420fffb */ bnez $at,.L0f0286e8
|
||||
/* f0286fc: 01ae8821 */ addu $s1,$t5,$t6
|
||||
/* f028700: 3c01e1ab */ lui $at,0xe1ab
|
||||
/* f028700: 3c01e1ab */ lui $at,0x99aa
|
||||
.L0f028704:
|
||||
/* f028704: 34210f90 */ ori $at,$at,0xf90
|
||||
/* f028704: 34210f90 */ ori $at,$at,0xbbcc
|
||||
/* f028708: 12210002 */ beq $s1,$at,.L0f028714
|
||||
/* f02870c: 3c018008 */ lui $at,%hi(g_Bodies+0xb7e)
|
||||
/* f028710: a420da82 */ sh $zero,%lo(g_Bodies+0xb7e)($at)
|
||||
|
|
|
@ -11764,7 +11764,7 @@ s32 chrConsiderGrenadeThrow(struct chrdata *chr, u32 entitytype, u32 entityid)
|
|||
i++;
|
||||
}
|
||||
|
||||
if (checksum != CHECKSUM_7F03B7B4) {
|
||||
if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
// Make player explode continuously
|
||||
g_Vars.currentplayer->bondexploding = true;
|
||||
g_Vars.currentplayer->bondnextexplode = g_Vars.lvframe60 + 120;
|
||||
|
|
|
@ -187,7 +187,7 @@ void explosionAlertChrs(f32 *radius, struct coord *noisepos)
|
|||
ptr++;
|
||||
}
|
||||
|
||||
if (checksum != 0xa17a4ca0) {
|
||||
if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
struct explosiontype *type = &g_ExplosionTypes[0];
|
||||
s32 i;
|
||||
|
||||
|
|
|
@ -684,8 +684,8 @@ glabel func0f0069dc
|
|||
/* f006aa8: 1420fff9 */ bnez $at,.L0f006a90
|
||||
/* f006aac: 03001025 */ or $v0,$t8,$zero
|
||||
.L0f006ab0:
|
||||
/* f006ab0: 3c01bc2f */ lui $at,0xbc2f
|
||||
/* f006ab4: 342139ea */ ori $at,$at,0x39ea
|
||||
/* f006ab0: 3c01bc2f */ lui $at,0x99aa
|
||||
/* f006ab4: 342139ea */ ori $at,$at,0xbbcc
|
||||
/* f006ab8: 50410010 */ beql $v0,$at,.L0f006afc
|
||||
/* f006abc: 8fbf0014 */ lw $ra,0x14($sp)
|
||||
/* f006ac0: 0c004b70 */ jal random
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
|
||||
void loadTextureList(void)
|
||||
{
|
||||
extern u8 _textureSegmentRomStart;
|
||||
extern u8 _textureSegmentRomEnd;
|
||||
extern u8 _texturesSegmentTableStart;
|
||||
extern u8 _texturesSegmentTableEnd;
|
||||
|
||||
u32 len = ((&_textureSegmentRomEnd - &_textureSegmentRomStart) + 15) & -16;
|
||||
u32 len = ((&_texturesSegmentTableEnd - &_texturesSegmentTableStart) + 15) & -16;
|
||||
|
||||
g_Textures = malloc(len, 6);
|
||||
|
||||
func0000d410(g_Textures, &_textureSegmentRomStart, len);
|
||||
func0000d410(g_Textures, &_texturesSegmentTableStart, len);
|
||||
}
|
||||
|
|
|
@ -954,7 +954,7 @@ struct prop *propAllocateEyespy(struct pad *pad, s16 room)
|
|||
ptr++;
|
||||
}
|
||||
|
||||
if (checksum != CHECKSUM_7F02DC00) {
|
||||
if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
s32 *ptr2 = (s32 *)func00012914;
|
||||
s32 *end2 = (s32 *)func00012a0c;
|
||||
|
||||
|
|
|
@ -8502,8 +8502,8 @@ glabel func0f09e144
|
|||
/* f09e488: 1420fffb */ bnez $at,.L0f09e478
|
||||
/* f09e48c: 00982023 */ subu $a0,$a0,$t8
|
||||
.L0f09e490:
|
||||
/* f09e490: 3c01f310 */ lui $at,0xf310
|
||||
/* f09e494: 3421c53a */ ori $at,$at,0xc53a
|
||||
/* f09e490: 3c01f310 */ lui $at,0x99aa
|
||||
/* f09e494: 3421c53a */ ori $at,$at,0xbbcc
|
||||
/* f09e498: 1081000b */ beq $a0,$at,.L0f09e4c8
|
||||
/* f09e49c: 2523000c */ addiu $v1,$t1,0xc
|
||||
/* f09e4a0: 2465001c */ addiu $a1,$v1,0x1c
|
||||
|
|
|
@ -6630,8 +6630,8 @@ glabel func0f15c920
|
|||
/* f15c9a4: 1420fff7 */ bnez $at,.L0f15c984
|
||||
/* f15c9a8: 006a1826 */ xor $v1,$v1,$t2
|
||||
.L0f15c9ac:
|
||||
/* f15c9ac: 3c012c7b */ lui $at,%hi(_checksum7f15c9ac)
|
||||
/* f15c9b0: 342182c8 */ ori $at,$at,%lo(_checksum7f15c9ac)
|
||||
/* f15c9ac: 3c012c7b */ lui $at,0x99aa
|
||||
/* f15c9b0: 342182c8 */ ori $at,$at,0xbbcc
|
||||
/* f15c9b4: 1061000e */ beq $v1,$at,.L0f15c9f0
|
||||
/* f15c9b8: 3c027f16 */ lui $v0,%hi(func0f15b908)
|
||||
/* f15c9bc: 2442b908 */ addiu $v0,$v0,%lo(func0f15b908)
|
||||
|
@ -6679,7 +6679,7 @@ glabel func0f15c920
|
|||
// ptr++;
|
||||
// }
|
||||
//
|
||||
// if (checksum != CHECKSUM_7F15C9AC) {
|
||||
// if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
// ptr = (s32 *)&func0f15b908 + 20;
|
||||
// end = &ptr[4];
|
||||
//
|
||||
|
|
|
@ -459,7 +459,7 @@ void func0f167e7c(s32 stagenum)
|
|||
i++;
|
||||
}
|
||||
|
||||
if (checksum != CHECKSUM_7F168500) {
|
||||
if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
u32 address = 0;
|
||||
u32 buffer[4];
|
||||
buffer[0] = 0xbb8b80bd;
|
||||
|
|
|
@ -520,7 +520,7 @@ u32 propobjHandlePickupByAibot(struct prop *prop, struct chrdata *chr)
|
|||
ptr++;
|
||||
}
|
||||
|
||||
if (checksum != 0xa0bf1e60) {
|
||||
if (checksum != CHECKSUM_PLACEHOLDER) {
|
||||
u32 *ptr = (u32 *)chrCheckTargetInSight;
|
||||
ptr[0] = add87654321(0x24020001 - 0x87654321); // addiu v0,zero,1
|
||||
ptr[1] = add87654321(0x03e00008 - 0x87654321); // jr ra
|
||||
|
|
|
@ -277,6 +277,8 @@
|
|||
#define CHEATFLAG_COMPLETION 4
|
||||
#define CHEATFLAG_FIRINGRANGE 8
|
||||
|
||||
#define CHECKSUM_PLACEHOLDER 0x99aabbcc
|
||||
|
||||
#define CHR_P1P2_OPPOSITE 0xf1
|
||||
#define CHR_P1P2 0xf2
|
||||
#define CHR_ANY 0xf3 // Only supported by if_chr_activated_object command
|
||||
|
@ -3072,23 +3074,3 @@
|
|||
#define VOICEBOX_1 1
|
||||
#define VOICEBOX_2 2
|
||||
#define VOICEBOX_3 3
|
||||
|
||||
#if VERSION == VERSION_NTSC_1_0
|
||||
#define CHECKSUM_7F0225CC 0x5874fe3a
|
||||
#define CHECKSUM_7F02DC00 0x27be1bf0
|
||||
#define CHECKSUM_7F03B7B4 0x1cc65d52
|
||||
#define CHECKSUM_7F15C9AC 0x2c7b42f8
|
||||
#define CHECKSUM_7F168500 0xfa4221b2
|
||||
#elif VERSION == VERSION_NTSC_FINAL
|
||||
#define CHECKSUM_7F0225CC 0x5874f34e
|
||||
#define CHECKSUM_7F02DC00 0xa7be1bf0
|
||||
#define CHECKSUM_7F03B7B4 0x860badfe
|
||||
#define CHECKSUM_7F15C9AC 0x2c7b82c8
|
||||
#define CHECKSUM_7F168500 0xfa4223f2
|
||||
#else
|
||||
#define CHECKSUM_7F0225CC 0
|
||||
#define CHECKSUM_7F02DC00 0
|
||||
#define CHECKSUM_7F03B7B4 0
|
||||
#define CHECKSUM_7F15C9AC 0
|
||||
#define CHECKSUM_7F168500 0
|
||||
#endif
|
||||
|
|
|
@ -38,11 +38,11 @@ glabel func000070d0
|
|||
/* 7114: 34210001 */ ori $at,$at,0x1
|
||||
/* 7118: 0041082a */ slt $at,$v0,$at
|
||||
/* 711c: 10200074 */ beqz $at,.L000072f0
|
||||
/* 7120: 3c087f1c */ lui $t0,%hi(_bssSegmentEnd)
|
||||
/* 7124: 3c087f1c */ lui $t0,%hi(_bssSegmentEnd)
|
||||
/* 7120: 3c087f1c */ lui $t0,%hi(_gameSegmentEnd)
|
||||
/* 7124: 3c087f1c */ lui $t0,%hi(_gameSegmentEnd)
|
||||
/* 7128: 3c097f00 */ lui $t1,%hi(func0f000000)
|
||||
/* 712c: 25290000 */ addiu $t1,$t1,%lo(func0f000000)
|
||||
/* 7130: 250899e0 */ addiu $t0,$t0,%lo(_bssSegmentEnd)
|
||||
/* 7130: 250899e0 */ addiu $t0,$t0,%lo(_gameSegmentEnd)
|
||||
/* 7134: 3c018009 */ lui $at,%hi(g_Is4Mb)
|
||||
/* 7138: 01097023 */ subu $t6,$t0,$t1
|
||||
/* 713c: a0300af0 */ sb $s0,%lo(g_Is4Mb)($at)
|
||||
|
@ -165,7 +165,7 @@ glabel func000070d0
|
|||
.L000072f0:
|
||||
/* 72f0: 3c097f00 */ lui $t1,%hi(func0f000000)
|
||||
/* 72f4: 25290000 */ addiu $t1,$t1,%lo(func0f000000)
|
||||
/* 72f8: 250899e0 */ addiu $t0,$t0,%lo(_bssSegmentEnd)
|
||||
/* 72f8: 250899e0 */ addiu $t0,$t0,%lo(_gameSegmentEnd)
|
||||
/* 72fc: 0109c823 */ subu $t9,$t0,$t1
|
||||
/* 7300: 272c003f */ addiu $t4,$t9,0x3f
|
||||
/* 7304: 01091023 */ subu $v0,$t0,$t1
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
.data
|
||||
|
||||
.set VERSION_NTSC_BETA, 0
|
||||
.set VERSION_NTSC_1_0, 1
|
||||
.set VERSION_NTSC_FINAL, 2
|
||||
.set VERSION_PAL_BETA, 3
|
||||
.set VERSION_PAL_FINAL, 4
|
||||
.set VERSION_JAP_FINAL, 5
|
||||
|
||||
|
||||
.word 0x80371240 # Identifier
|
||||
.word 0x0000000F # Clock rate
|
||||
.word 0x80001000 # Program counter
|
||||
.word 0x00001449 # Release address
|
||||
.word 0x00000000 # CRC 1
|
||||
.word 0x00000000 # CRC 2
|
||||
.word 0x00000000
|
||||
.word 0x00000000
|
||||
|
||||
.ascii "Perfect Dark "
|
||||
.word 0x00000000
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.ascii "NPDE"
|
||||
|
||||
# Version
|
||||
.if VERSION == VERSION_NTSC_BETA
|
||||
.byte 0x01
|
||||
.elseif VERSION == VERSION_NTSC_FINAL
|
||||
.byte 0x01
|
||||
.else
|
||||
.byte 0x00
|
||||
.endif
|
||||
|
172
tools/buildrom
172
tools/buildrom
|
@ -1,172 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
def main():
|
||||
fd = open(bdir() + '/pd.z64', 'wb+')
|
||||
|
||||
# The retail ROM contains truncated duplicates of some segments.
|
||||
# For example, the real boot segment is at 0x1000 - 0x3050, but the tail end
|
||||
# of it is repeated at 0x2ea6c - 0x30a60. The truncated parts are not read
|
||||
# by the ROM; they are likely a side effect of Rare's linker copying things
|
||||
# around in the ROM.
|
||||
if os.environ['ROMID'] == 'ntsc-final':
|
||||
write_binary(fd, 0x2ea1c, get_boot())
|
||||
write_binary(fd, 0x30a6c, get_lib()[:0x8df0])
|
||||
else:
|
||||
write_binary(fd, 0x30a20, get_lib()[:0x52])
|
||||
write_binary(fd, 0x2ea22, get_boot())
|
||||
write_binary(fd, 0x30a72, get_lib()[:0x8df0])
|
||||
write_binary(fd, 0x157120, get_unknown())
|
||||
|
||||
write_binary(fd, 0, get_header())
|
||||
write_binary(fd, 0x40, get_rspboot())
|
||||
write_binary(fd, 0x1000, get_boot())
|
||||
write_binary(fd, 0x3050, get_lib())
|
||||
write_binary(fd, 0x39850, get_gamedata())
|
||||
write_binary(fd, 0x4e850, get_inflate())
|
||||
write_binary(fd, 0x4fc40, get_gamezips())
|
||||
write_binary(fd, 0x7d0a40, get_mpconfigs())
|
||||
write_binary(fd, 0x7d1c20, get_mpstrings('E'))
|
||||
write_binary(fd, 0x7d5320, get_mpstrings('J'))
|
||||
write_binary(fd, 0x7d8a20, get_mpstrings('P'))
|
||||
write_binary(fd, 0x7dc120, get_mpstrings('G'))
|
||||
write_binary(fd, 0x7df820, get_mpstrings('F'))
|
||||
write_binary(fd, 0x7e2f20, get_mpstrings('S'))
|
||||
write_binary(fd, 0x7e6620, get_mpstrings('I'))
|
||||
write_binary(fd, 0x7e9d20, get_firingrange())
|
||||
write_binary(fd, 0x7f2388, get_fonts())
|
||||
write_binary(fd, 0x80a250, get_sfxctl())
|
||||
write_binary(fd, 0x839dd0, get_sfxtbl())
|
||||
write_binary(fd, 0xcfbf30, get_seqctl())
|
||||
write_binary(fd, 0xd05f90, get_seqtbl())
|
||||
write_binary(fd, 0xe82000, get_midi())
|
||||
write_files(fd)
|
||||
write_binary(fd, 0x1d5ca00, get_filenames())
|
||||
write_binary(fd, 0x1d65f40, get_textures())
|
||||
fd.close()
|
||||
|
||||
def write_binary(fd, address, binary):
|
||||
fd.seek(address)
|
||||
fd.write(binary)
|
||||
|
||||
def get_header():
|
||||
binary = bytearray()
|
||||
binary.extend(b'\x80\x37\x12\x40') # Identifier
|
||||
binary.extend(b'\x00\x00\x00\x0f') # Clock rate
|
||||
binary.extend(b'\x80\x00\x10\x00') # Program counter
|
||||
binary.extend(b'\x00\x00\x14\x49') # Release address
|
||||
binary.extend(b'\x00\x00\x00\x00') # CRC 1
|
||||
binary.extend(b'\x00\x00\x00\x00') # CRC 2
|
||||
binary.extend(b'\x00\x00\x00\x00')
|
||||
binary.extend(b'\x00\x00\x00\x00')
|
||||
binary.extend(b'Perfect Dark ')
|
||||
binary.extend(b'\x00\x00\x00\x00')
|
||||
binary.extend(b'\x00\x00\x00')
|
||||
binary.extend(b'NPDE')
|
||||
binary.extend(b'\x01' if os.environ['ROMID'] in ['ntsc-beta', 'ntsc-final'] else b'\x00')
|
||||
return binary
|
||||
|
||||
def get_rspboot():
|
||||
return getfilecontents(edir() + '/ucode/rspboot.bin')
|
||||
|
||||
def get_boot():
|
||||
return getfilecontents(bdir() + '/ucode/boot.bin')
|
||||
|
||||
def get_lib():
|
||||
return zip(bdir() + '/ucode/lib.bin')
|
||||
|
||||
def get_gamedata():
|
||||
return zip(bdir() + '/ucode/gamedata.bin')
|
||||
|
||||
def get_inflate():
|
||||
return getfilecontents(bdir() + '/ucode/inflate.bin')
|
||||
|
||||
def get_gamezips():
|
||||
return getfilecontents(bdir() + '/ucode/gamezips.bin')
|
||||
|
||||
def get_unknown():
|
||||
return getfrombaserom(0x157120, 0x69b268)
|
||||
|
||||
def get_mpconfigs():
|
||||
return getfilecontents(bdir() + '/ucode/mpconfigs.bin')
|
||||
|
||||
def get_mpstrings(lang):
|
||||
return getfilecontents(bdir() + '/ucode/mpstrings%s.bin' % lang)
|
||||
|
||||
def get_firingrange():
|
||||
return getfilecontents(bdir() + '/ucode/firingrange.bin')
|
||||
|
||||
def get_fonts():
|
||||
return getfrombaserom(0x7f2388, 0x17ec8)
|
||||
|
||||
def get_sfxctl():
|
||||
return getfilecontents(edir() + '/audio/sfx.ctl')
|
||||
|
||||
def get_sfxtbl():
|
||||
return getfilecontents(edir() + '/audio/sfx.tbl')
|
||||
|
||||
def get_seqctl():
|
||||
return getfilecontents(edir() + '/audio/music.ctl')
|
||||
|
||||
def get_seqtbl():
|
||||
return getfilecontents(edir() + '/audio/music.tbl')
|
||||
|
||||
def get_midi():
|
||||
return getfilecontents(edir() + '/audio/sequences.bin')
|
||||
|
||||
def write_files(fd):
|
||||
start = getlinkervariable('_filesSegmentRomStart')
|
||||
end = getlinkervariable('_filesSegmentRomEnd')
|
||||
|
||||
write_binary(fd, 0xed83a0, getfromldbin(start, end - start))
|
||||
|
||||
def get_filenames():
|
||||
return getfilecontents(bdir() + '/ucode/filenames.bin')
|
||||
|
||||
def get_textures():
|
||||
return getfrombaserom(0x01d65f40, 0x29a0c0)
|
||||
|
||||
def getfilecontents(filename):
|
||||
fd = open(filename, 'rb')
|
||||
binary = fd.read()
|
||||
fd.close()
|
||||
return binary
|
||||
|
||||
def getfrombaserom(offset, len):
|
||||
fd = open('pd.%s.z64' % os.environ['ROMID'], 'rb')
|
||||
fd.seek(offset)
|
||||
binary = fd.read(len)
|
||||
fd.close()
|
||||
return binary
|
||||
|
||||
def getfromldbin(offset, len):
|
||||
fd = open(bdir() + '/pd.bin', 'rb')
|
||||
fd.seek(offset)
|
||||
binary = fd.read(len)
|
||||
fd.close()
|
||||
return binary
|
||||
|
||||
def zip(filename):
|
||||
return subprocess.check_output(['tools/rarezip', filename])
|
||||
|
||||
def bdir():
|
||||
return 'build/%s' % os.environ['ROMID']
|
||||
|
||||
def edir():
|
||||
return 'extracted/%s' % os.environ['ROMID']
|
||||
|
||||
def getlinkervariable(varname):
|
||||
if 'TOOLCHAIN' in os.environ:
|
||||
cmd = '%s-objdump' % os.environ['TOOLCHAIN']
|
||||
else:
|
||||
cmd = 'mips64-elf-objdump'
|
||||
|
||||
objdump = subprocess.check_output([cmd, bdir() + '/pd.elf', '-t']).decode('utf-8')
|
||||
|
||||
matches = re.findall(r'^([0-9a-f]+) .*? %s$' % varname, objdump, re.MULTILINE)
|
||||
return int(matches[0], 16)
|
||||
|
||||
main()
|
290
tools/extract
290
tools/extract
|
@ -12,46 +12,64 @@ class Extractor:
|
|||
self.rom = fd.read()
|
||||
fd.close()
|
||||
|
||||
self.gamedata = self.decompress(self.rom[self.val('gamedata'):])
|
||||
self.data = self.decompress(self.rom[self.val('data'):])
|
||||
self.extract_all()
|
||||
|
||||
def extract_all(self):
|
||||
self.extract_accessingpak()
|
||||
self.extract_animations()
|
||||
self.extract_audio()
|
||||
self.extract_boot()
|
||||
self.extract_copyright()
|
||||
self.extract_data()
|
||||
self.extract_files()
|
||||
self.extract_firingrange()
|
||||
self.extract_fonts()
|
||||
self.extract_gamedata()
|
||||
self.extract_textures()
|
||||
self.extract_ucodes()
|
||||
self.extract_game()
|
||||
self.extract_garbage1()
|
||||
self.extract_garbage2()
|
||||
self.extract_lib()
|
||||
self.extract_mpconfigs()
|
||||
self.extract_mpstrings()
|
||||
self.extract_firingrange()
|
||||
self.extract_rspboot()
|
||||
self.extract_textures()
|
||||
self.extract_unknown1()
|
||||
self.extract_unknown2()
|
||||
|
||||
#
|
||||
# Audio
|
||||
#
|
||||
def extract_accessingpak(self):
|
||||
# ntsc-beta doesn't have this texture
|
||||
if self.romid != 'ntsc-beta':
|
||||
addr = self.val('copyright') + 0xb30
|
||||
data = self.decompress(self.rom[addr:addr+0x8b0])
|
||||
self.write('segments/accessingpak.bin', data)
|
||||
|
||||
def extract_animations(self):
|
||||
start = self.val('animations')
|
||||
end = self.val('mpconfigs')
|
||||
self.write('segments/animations.bin', self.rom[start:end])
|
||||
|
||||
def extract_audio(self):
|
||||
sfxctl = self.val('sfxctl')
|
||||
sfxtbl = sfxctl + 0x2fb80
|
||||
musicctl = sfxtbl + 0x4c2160
|
||||
musictbl = musicctl + 0xa060
|
||||
seqtbl = musictbl + 0x17c070
|
||||
self.write('audio/sfx.ctl', self.rom[sfxctl:sfxtbl])
|
||||
self.write('audio/sfx.tbl', self.rom[sfxtbl:musicctl])
|
||||
self.write('audio/music.ctl', self.rom[musicctl:musictbl])
|
||||
self.write('audio/music.tbl', self.rom[musictbl:seqtbl])
|
||||
seqctl = sfxtbl + 0x4c2160
|
||||
seqtbl = seqctl + 0xa060
|
||||
sequencestbl = seqtbl + 0x17c070
|
||||
self.write('segments/sfx.ctl.bin', self.rom[sfxctl:sfxtbl])
|
||||
self.write('segments/sfx.tbl.bin', self.rom[sfxtbl:seqctl])
|
||||
self.write('segments/seq.ctl.bin', self.rom[seqctl:seqtbl])
|
||||
self.write('segments/seq.tbl.bin', self.rom[seqtbl:sequencestbl])
|
||||
|
||||
seqtbllen = 0x563b0 if self.romid == 'ntsc-beta' else 0x563a0
|
||||
length = 0x563b0 if self.romid == 'ntsc-beta' else 0x563a0
|
||||
|
||||
sequences = self.rom[seqtbl:seqtbl+seqtbllen]
|
||||
self.write('audio/sequences.bin', sequences)
|
||||
sequences = self.rom[sequencestbl:sequencestbl+length]
|
||||
self.write('segments/sequences.bin', sequences)
|
||||
|
||||
# Extract sequences
|
||||
count = int.from_bytes(sequences[0:2], 'big')
|
||||
i = 0
|
||||
while i < count:
|
||||
sequence = self.extract_sequence(sequences, i)
|
||||
self.write('audio/sequences/%03d.seq' % i, sequence)
|
||||
self.write('sequences/%03d.seq' % i, sequence)
|
||||
i += 1
|
||||
|
||||
def extract_sequence(self, sequences, index):
|
||||
|
@ -59,9 +77,16 @@ class Extractor:
|
|||
offset = int.from_bytes(sequences[pos:pos+4], 'big')
|
||||
return self.decompress(sequences[offset:])
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
def extract_boot(self):
|
||||
self.write('segments/boot.bin', self.rom[0x1000:0x3050])
|
||||
|
||||
def extract_copyright(self):
|
||||
addr = self.val('copyright')
|
||||
data = self.decompress(self.rom[addr:addr+0xb30])
|
||||
self.write('segments/copyright.bin', data)
|
||||
|
||||
def extract_data(self):
|
||||
self.write('segments/data.bin', self.data)
|
||||
|
||||
def extract_files(self):
|
||||
offsets = self.get_file_offsets()
|
||||
|
@ -111,7 +136,7 @@ class Extractor:
|
|||
i = self.val('files')
|
||||
offsets = []
|
||||
while True:
|
||||
offset = int.from_bytes(self.gamedata[i:i+4], 'big')
|
||||
offset = int.from_bytes(self.data[i:i+4], 'big')
|
||||
if offset == 0 and len(offsets):
|
||||
return offsets
|
||||
offsets.append(offset)
|
||||
|
@ -131,81 +156,7 @@ class Extractor:
|
|||
nullpos = self.rom[address:].index(0)
|
||||
return str(self.rom[address:address + nullpos], 'utf-8')
|
||||
|
||||
#
|
||||
# MpConfigs
|
||||
#
|
||||
|
||||
def extract_mpconfigs(self):
|
||||
addr = self.val('mpconfigs')
|
||||
self.write('ucode/mpconfigs.bin', self.rom[addr:addr+0x68*44])
|
||||
|
||||
def extract_mpstrings(self):
|
||||
self.extract_mpstrings_lang(0, 'E')
|
||||
self.extract_mpstrings_lang(1, 'J')
|
||||
self.extract_mpstrings_lang(2, 'P')
|
||||
self.extract_mpstrings_lang(3, 'G')
|
||||
self.extract_mpstrings_lang(4, 'F')
|
||||
self.extract_mpstrings_lang(5, 'S')
|
||||
self.extract_mpstrings_lang(6, 'I')
|
||||
|
||||
def extract_mpstrings_lang(self, index, lang):
|
||||
addr = self.val('mpconfigs') + 0x68 * 44 + 0x3700 * index
|
||||
self.write('ucode/mpstrings%s.bin' % lang, self.rom[addr:addr+0x3700])
|
||||
|
||||
#
|
||||
# Firing Range
|
||||
#
|
||||
|
||||
def extract_firingrange(self):
|
||||
addr = self.val('firingrange')
|
||||
self.write('ucode/firingrange.bin', self.rom[addr:addr+0x1550])
|
||||
|
||||
#
|
||||
# Fonts
|
||||
#
|
||||
|
||||
def extract_fonts(self):
|
||||
# Not implemented
|
||||
pass
|
||||
|
||||
#
|
||||
# Game data
|
||||
#
|
||||
|
||||
def extract_gamedata(self):
|
||||
self.write('ucode/gamedata.bin', self.gamedata)
|
||||
|
||||
#
|
||||
# Textures
|
||||
#
|
||||
|
||||
def extract_textures(self):
|
||||
base = self.val('textures')
|
||||
datalen = 0x294960 if self.romid == 'jap-final' else 0x291d60
|
||||
tablepos = base + datalen
|
||||
index = 0
|
||||
while True:
|
||||
start = int.from_bytes(self.rom[tablepos+1:tablepos+4], 'big')
|
||||
end = int.from_bytes(self.rom[tablepos+9:tablepos+12], 'big')
|
||||
if int.from_bytes(self.rom[tablepos+12:tablepos+16], 'big') != 0:
|
||||
return
|
||||
texturedata = self.rom[base+start:base+end]
|
||||
self.write('textures/%04x.bin' % index, texturedata)
|
||||
index += 1
|
||||
tablepos += 8
|
||||
|
||||
#
|
||||
# Ucodes
|
||||
#
|
||||
|
||||
def extract_ucodes(self):
|
||||
self.write('ucode/rspboot.bin', self.rom[0x40:0x1000])
|
||||
self.write('ucode/boot.bin', self.rom[0x1000:0x3050])
|
||||
self.write('ucode/lib.bin', self.decompress(self.rom[0x3050:]))
|
||||
self.write('ucode/inflate.bin', self.rom[0x4e850:0x4fc40])
|
||||
self.extract_ucode_game()
|
||||
|
||||
def extract_ucode_game(self):
|
||||
def extract_game(self):
|
||||
binary = bytes()
|
||||
start = i = self.val('game')
|
||||
|
||||
|
@ -220,7 +171,78 @@ class Extractor:
|
|||
break
|
||||
i += 4
|
||||
|
||||
self.write('ucode/game.bin', binary)
|
||||
self.write('segments/game.bin', binary)
|
||||
|
||||
def extract_inflate(self):
|
||||
self.write('segments/inflate.bin', self.rom[0x4e850:0x4fc40])
|
||||
|
||||
def extract_garbage1(self):
|
||||
start = self.val('garbage1')
|
||||
end = self.val('data')
|
||||
self.write('segments/garbage1.bin', self.rom[start:end])
|
||||
|
||||
def extract_garbage2(self):
|
||||
start = self.val('garbage2')
|
||||
end = self.val('animations')
|
||||
self.write('segments/garbage2.bin', self.rom[start:end])
|
||||
|
||||
def extract_lib(self):
|
||||
self.write('segments/lib.bin', self.decompress(self.rom[0x3050:]))
|
||||
|
||||
def extract_mpconfigs(self):
|
||||
addr = self.val('mpconfigs')
|
||||
self.write('segments/mpconfigs.bin', self.rom[addr:addr+0x68*44])
|
||||
|
||||
def extract_mpstrings(self):
|
||||
self.extract_mpstrings_lang(0, 'E')
|
||||
self.extract_mpstrings_lang(1, 'J')
|
||||
self.extract_mpstrings_lang(2, 'P')
|
||||
self.extract_mpstrings_lang(3, 'G')
|
||||
self.extract_mpstrings_lang(4, 'F')
|
||||
self.extract_mpstrings_lang(5, 'S')
|
||||
self.extract_mpstrings_lang(6, 'I')
|
||||
|
||||
def extract_mpstrings_lang(self, index, lang):
|
||||
addr = self.val('mpconfigs') + 0x68 * 44 + 0x3700 * index
|
||||
self.write('segments/mpstrings%s.bin' % lang, self.rom[addr:addr+0x3700])
|
||||
|
||||
def extract_firingrange(self):
|
||||
addr = self.val('firingrange')
|
||||
self.write('segments/firingrange.bin', self.rom[addr:addr+0x1550])
|
||||
|
||||
def extract_fonts(self):
|
||||
start = self.val('unknown1') + 0xb50 + 0x65d0
|
||||
end = self.val('sfxctl')
|
||||
self.write('segments/fonts.bin', self.rom[start:end])
|
||||
|
||||
def extract_rspboot(self):
|
||||
self.write('segments/rspboot.bin', self.rom[0x40:0x1000])
|
||||
|
||||
def extract_textures(self):
|
||||
base = self.val('textures')
|
||||
datalen = 0x294960 if self.romid == 'jap-final' else 0x291d60
|
||||
tablepos = base + datalen
|
||||
index = 0
|
||||
while True:
|
||||
start = int.from_bytes(self.rom[tablepos+1:tablepos+4], 'big')
|
||||
end = int.from_bytes(self.rom[tablepos+9:tablepos+12], 'big')
|
||||
if int.from_bytes(self.rom[tablepos+12:tablepos+16], 'big') != 0:
|
||||
break
|
||||
texturedata = self.rom[base+start:base+end]
|
||||
self.write('textures/%04x.bin' % index, texturedata)
|
||||
index += 1
|
||||
tablepos += 8
|
||||
|
||||
tablepos += 8
|
||||
self.write('segments/textures.bin', self.rom[base:tablepos])
|
||||
|
||||
def extract_unknown1(self):
|
||||
addr = self.val('unknown1')
|
||||
self.write('segments/unknown1.bin', self.rom[addr:addr+0xb50])
|
||||
|
||||
def extract_unknown2(self):
|
||||
addr = self.val('unknown1') + 0xb50
|
||||
self.write('segments/unknown2.bin', self.rom[addr:addr+0x65d0])
|
||||
|
||||
#
|
||||
# Misc functions
|
||||
|
@ -250,63 +272,23 @@ class Extractor:
|
|||
fd.close()
|
||||
|
||||
def val(self, name):
|
||||
return self.vals[self.romid][name]
|
||||
index = ['ntsc-beta','ntsc-1.0','ntsc-final','pal-beta','pal-final','jap-final'].index(self.romid)
|
||||
return self.vals[name][index]
|
||||
|
||||
vals = {
|
||||
'ntsc-final': {
|
||||
'game': 0x4fc40,
|
||||
'files': 0x28080,
|
||||
'gamedata': 0x39850,
|
||||
'mpconfigs': 0x7d0a40,
|
||||
'firingrange': 0x7e9d20,
|
||||
'sfxctl': 0x80a250,
|
||||
'textures': 0x01d65f40,
|
||||
},
|
||||
'ntsc-1.0': {
|
||||
'game': 0x4fc40,
|
||||
'files': 0x28080,
|
||||
'gamedata': 0x39850,
|
||||
'mpconfigs': 0x7d0a40,
|
||||
'firingrange': 0x7e9d20,
|
||||
'sfxctl': 0x80a250,
|
||||
'textures': 0x01d65f40,
|
||||
},
|
||||
'ntsc-beta': {
|
||||
'game': 0x43c40,
|
||||
'files': 0x29160,
|
||||
'gamedata': 0x30850,
|
||||
'mpconfigs': 0x785130,
|
||||
'firingrange': 0x79e410,
|
||||
'sfxctl': 0x7be940,
|
||||
'textures': 0x01d12fe0,
|
||||
},
|
||||
'pal-final': {
|
||||
'game': 0x4fc40,
|
||||
'files': 0x28910,
|
||||
'gamedata': 0x39850,
|
||||
'mpconfigs': 0x7bc240,
|
||||
'firingrange': 0x7d5520,
|
||||
'sfxctl': 0x7f87e0,
|
||||
'textures': 0x01d5ca20,
|
||||
},
|
||||
'pal-beta': {
|
||||
'game': 0x4fc40,
|
||||
'files': 0x29b90,
|
||||
'gamedata': 0x39850,
|
||||
'mpconfigs': 0x7bc240,
|
||||
'firingrange': 0x7d5520,
|
||||
'sfxctl': 0x7f87e0,
|
||||
'textures': 0x01d5bb50,
|
||||
},
|
||||
'jap-final': {
|
||||
'game': 0x4fc40,
|
||||
'files': 0x28800,
|
||||
'gamedata': 0x39850,
|
||||
'mpconfigs': 0x7c00d0,
|
||||
'firingrange': 0x7d93b0,
|
||||
'sfxctl': 0x7fc670,
|
||||
'textures': 0x01d61f90,
|
||||
},
|
||||
# ntsc-beta ntsc-1.0 ntsc-final pal-beta pal-final jap-final
|
||||
'game': [0x43c40, 0x4fc40, 0x4fc40, 0x4fc40, 0x4fc40, 0x4fc40, ],
|
||||
'garbage1': [0x0, 0x2ea22, 0x2ea6c, 0x0, 0x0, 0x0, ],
|
||||
'files': [0x29160, 0x28080, 0x28080, 0x29b90, 0x28910, 0x28800, ],
|
||||
'data': [0x30850, 0x39850, 0x39850, 0x39850, 0x39850, 0x39850, ],
|
||||
'animations': [0x155dc0, 0x1a15c0, 0x1a15c0, 0x18cdc0, 0x18cdc0, 0x190c50, ],
|
||||
'garbage2': [0x0, 0x1574a0, 0x157800, 0x0, 0x0, 0x0, ],
|
||||
'mpconfigs': [0x785130, 0x7d0a40, 0x7d0a40, 0x7bc240, 0x7bc240, 0x7c00d0, ],
|
||||
'firingrange': [0x79e410, 0x7e9d20, 0x7e9d20, 0x7d5520, 0x7d5520, 0x7d93b0, ],
|
||||
'unknown1': [0x79f960, 0x7eb270, 0x7eb270, 0x7d6a70, 0x7d6a70, 0x7da900, ],
|
||||
'sfxctl': [0x7be940, 0x80a250, 0x80a250, 0x7f87e0, 0x7f87e0, 0x7fc670, ],
|
||||
'textures': [0x1d12fe0, 0x1d65f40, 0x1d65f40, 0x1d5bb50, 0x1d5ca20, 0x1d61f90, ],
|
||||
'copyright': [0x1fabac0, 0x1ffea20, 0x1ffea20, 0x1ff4630, 0x1ff5500, 0x1ffd6b0, ],
|
||||
}
|
||||
|
||||
extractor = Extractor()
|
||||
|
|
|
@ -7,5 +7,6 @@ segment=$1
|
|||
pos=$(grep "^\.$segment " $B_DIR/pd.map | awk '{print $6}')
|
||||
len=$(grep "^\.$segment " $B_DIR/pd.map | awk '{print $3}')
|
||||
|
||||
dd if=$B_DIR/pd.bin of=$B_DIR/ucode/$segment.bin skip=$(($pos)) iflag=skip_bytes bs=$(($len)) count=1 status=none
|
||||
mkdir -p $B_DIR/segments
|
||||
dd if=$B_DIR/stage2.bin of=$B_DIR/segments/$segment.bin skip=$(($pos)) iflag=skip_bytes bs=$(($len)) count=1 status=none
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import os
|
|||
import zlib
|
||||
|
||||
"""
|
||||
mkgamezips - Creates the ucode/gamezips.bin from ucode/game.bin
|
||||
mkgamezips - Creates the segments/gamezips.bin from segments/game.bin
|
||||
|
||||
game.bin is the compiled game code from ld. This game code is split into
|
||||
4KB chunks. Each chunk is individually zipped.
|
||||
|
@ -21,7 +21,7 @@ The format of the gamezips binary is:
|
|||
def main():
|
||||
zips = get_zips()
|
||||
|
||||
fd = open('build/%s/ucode/gamezips.bin' % os.environ['ROMID'], 'wb')
|
||||
fd = open('build/%s/segments/gamezips.bin' % os.environ['ROMID'], 'wb')
|
||||
pos = len(zips) * 4 + 4
|
||||
|
||||
# Write pointer array
|
||||
|
@ -71,7 +71,7 @@ def get_filecontents(filename):
|
|||
return binary
|
||||
|
||||
def get_zips():
|
||||
binary = get_filecontents('build/%s/ucode/game.bin' % os.environ['ROMID'])
|
||||
binary = get_filecontents('build/%s/segments/game.bin' % os.environ['ROMID'])
|
||||
parts = [binary[i:i+0x1000] for i in range(0, len(binary), 0x1000)]
|
||||
return [zip(part) for part in parts]
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo -e "\n.data\n.incbin \"$1\"\n.balign 0x10" > build/$ROMID/file.s
|
||||
|
||||
$TOOLCHAIN-as -mabi=32 -mips2 -I src/include -EB -o "$2" build/$ROMID/file.s
|
||||
|
||||
rm -f build/$ROMID/file.s
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
"""
|
||||
packrom - performs code compression, writing of garbage data (required for a
|
||||
matching ROM), ROM truncation to 32MB, and filling the tail end of the ROM with
|
||||
0xff bytes.
|
||||
|
||||
Usage:
|
||||
packrom <rom>
|
||||
"""
|
||||
|
||||
def zip(binary):
|
||||
filename = bdir() + '/tmp.bin';
|
||||
|
||||
fd = open(filename, 'wb')
|
||||
fd.write(binary)
|
||||
fd.close()
|
||||
|
||||
zipped = subprocess.check_output(['tools/rarezip', filename])
|
||||
os.remove(filename)
|
||||
return zipped
|
||||
|
||||
def bdir():
|
||||
return 'build/%s' % os.environ['ROMID']
|
||||
|
||||
def edir():
|
||||
return 'extracted/%s' % os.environ['ROMID']
|
||||
|
||||
def get_start(locations, segname):
|
||||
return next(filter(lambda l: l['name'] == segname, locations))['addr']
|
||||
|
||||
def get_end(locations, start):
|
||||
best = 0xffffffff
|
||||
|
||||
for location in locations:
|
||||
if location['addr'] > start and location['addr'] < best:
|
||||
best = location['addr']
|
||||
|
||||
return best;
|
||||
|
||||
def attempt(fd, locations, segname, payload, constname):
|
||||
# Get location to write to
|
||||
start = get_start(locations, segname + 'zip')
|
||||
end = get_end(locations, start)
|
||||
|
||||
# Check it'll fit
|
||||
allocation = end - start
|
||||
|
||||
if len(payload) > allocation:
|
||||
print('The %s segment is too big after compression to fit the allocation of 0x%x. In ld/pd.ld, increase the value of %s to 0x%x or higher.' % (
|
||||
segname, allocation, constname, len(payload)
|
||||
))
|
||||
exit(1)
|
||||
|
||||
# Write it
|
||||
fd.seek(start)
|
||||
fd.write(payload)
|
||||
|
||||
def get_segment(fd, locations, segname):
|
||||
start = get_start(locations, segname)
|
||||
end = get_end(locations, start)
|
||||
|
||||
fd.seek(start)
|
||||
return fd.read(end - start)
|
||||
|
||||
def pack_lib(fd, locations):
|
||||
lib = get_segment(fd, locations, 'lib')
|
||||
zipped = zip(lib)
|
||||
attempt(fd, locations, 'lib', zipped, 'ROMALLOCATION_LIB')
|
||||
|
||||
def pack_data(fd, locations):
|
||||
data = get_segment(fd, locations, 'data')
|
||||
zipped = zip(data)
|
||||
attempt(fd, locations, 'data', zipped, 'ROMALLOCATION_DATA')
|
||||
|
||||
def pack_game(fd, locations):
|
||||
fd2 = open(bdir() + '/segments/gamezips.bin', 'rb')
|
||||
zips = fd2.read()
|
||||
fd2.close()
|
||||
|
||||
attempt(fd, locations, 'game', zips, 'ROMALLOCATION_GAME')
|
||||
|
||||
def get_locations():
|
||||
fd = open(bdir() + '/pd.map', 'r')
|
||||
ldmap = fd.read()
|
||||
fd.close()
|
||||
|
||||
matches = re.findall(r'^\s*0x([0-9a-f]+)\s+_(\S+)SegmentRomStart', ldmap, re.MULTILINE)
|
||||
|
||||
def make_numeric(match):
|
||||
return {'addr': int(match[0], 16), 'name': match[1]}
|
||||
|
||||
return list(map(make_numeric, matches))
|
||||
|
||||
def write_garbage_part(fd, addr, filename):
|
||||
fd2 = open(edir() + '/segments/' + filename, 'rb')
|
||||
binary = fd2.read()
|
||||
fd2.close()
|
||||
|
||||
fd.seek(addr)
|
||||
fd.write(binary)
|
||||
|
||||
def write_garbage(fd, locations):
|
||||
if os.environ['ROMID'] == 'ntsc-final':
|
||||
write_garbage_part(fd, 0x2ea6c, 'garbage1.bin')
|
||||
write_garbage_part(fd, 0x157800, 'garbage2.bin')
|
||||
else:
|
||||
write_garbage_part(fd, 0x2ea22, 'garbage1.bin')
|
||||
write_garbage_part(fd, 0x1574a0, 'garbage2.bin')
|
||||
|
||||
def fill_tail(fd):
|
||||
fd2 = open(bdir() + '/pd.map', 'r')
|
||||
ldmap = fd2.read()
|
||||
fd2.close()
|
||||
|
||||
match = re.findall(r'^\s*0x([0-9a-f]+)\s+_accessingpakSegmentRomEnd', ldmap, re.MULTILINE)
|
||||
|
||||
pos = int(match[0], 16)
|
||||
fd.seek(pos)
|
||||
|
||||
while pos < 1024 * 1024 * 32:
|
||||
fd.write(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
|
||||
pos += 0x10
|
||||
|
||||
def main():
|
||||
locations = get_locations()
|
||||
|
||||
fd = open(sys.argv[1], 'rb+')
|
||||
|
||||
pack_lib(fd, locations)
|
||||
pack_data(fd, locations)
|
||||
pack_game(fd, locations)
|
||||
|
||||
if os.environ['MATCHING']:
|
||||
write_garbage(fd, locations)
|
||||
fill_tail(fd)
|
||||
|
||||
# Truncate to 32MB
|
||||
fd.seek(0)
|
||||
fd.truncate(1024 * 1024 * 32)
|
||||
fd.close()
|
||||
|
||||
main()
|
|
@ -0,0 +1,206 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
"""
|
||||
patchpiracysums - calculates the expected checksums that are used in piracy
|
||||
checks and replaces the expected values in the ROM.
|
||||
|
||||
Usage:
|
||||
patchpiracysums <rom> <ldmap>
|
||||
|
||||
To avoid piracy, the game calculates checksums of functions in memory and
|
||||
compares them with expected values. This script is armed with a list of
|
||||
locations where these piracy checks happen, as well as the algorithms used in
|
||||
each, and calculates the expected checksums.
|
||||
|
||||
Locations are referenced by function name and resolved to addresses using a
|
||||
linker map so it works with shifted ROMs. To find the location of the checksum
|
||||
within a function, it expects the function to use CHECKSUM_PLACEHOLDER. It
|
||||
searches for lui and ori instructions that load the placeholder value and
|
||||
replaces the value with the calculated one.
|
||||
"""
|
||||
|
||||
CHECKSUM_PLACEHOLDER = 0x99aabbcc
|
||||
|
||||
def algo01(checksum, word):
|
||||
return checksum ^ word
|
||||
|
||||
def algo02(checksum, word):
|
||||
return checksum ^ ~word
|
||||
|
||||
def algo03(checksum, word):
|
||||
return ((checksum + word) & 0xffffffff) * 2
|
||||
|
||||
def algo04(checksum, word):
|
||||
return checksum + ~word
|
||||
|
||||
def algo05(checksum, word):
|
||||
return checksum * 2 + word
|
||||
|
||||
def algo06(checksum, word):
|
||||
return checksum + word
|
||||
|
||||
def algo07(checksum, word):
|
||||
checksum = (checksum << 1) & 0xffffffff
|
||||
return checksum ^ word
|
||||
|
||||
def algo08(checksum, word):
|
||||
checksum = (checksum + word) & 0xffffffff
|
||||
return checksum + (word >> 1)
|
||||
|
||||
def algo09(checksum, word):
|
||||
return checksum - ~word
|
||||
|
||||
def algo10(checksum, word):
|
||||
return (checksum ^ word) << 1
|
||||
|
||||
def algo11(checksum, word):
|
||||
return (checksum ^ ~word) << 1
|
||||
|
||||
def algo12(checksum, word):
|
||||
checksum ^= ~word
|
||||
checksum ^= (word << 5) & 0xffffffff
|
||||
checksum ^= word >> 15
|
||||
return checksum
|
||||
|
||||
class Tool:
|
||||
def load_map(self):
|
||||
fd = open(sys.argv[2], 'r')
|
||||
ldmap = fd.read()
|
||||
fd.close()
|
||||
|
||||
self.symbols = re.findall(r'^\s*0x([0-9a-f]+)\s+(\S+)$', ldmap, re.MULTILINE)
|
||||
self.segrampositions = re.findall(r'^\s*0x([0-9a-f]+)\s+_(\S+)SegmentStart', ldmap, re.MULTILINE)
|
||||
self.segrompositions = re.findall(r'^\s*0x([0-9a-f]+)\s+_(\S+)SegmentRomStart', ldmap, re.MULTILINE)
|
||||
|
||||
def ramtorom(self, ramaddr):
|
||||
# Find which segramposition is closest and prior
|
||||
segramaddr = 0
|
||||
segname = None
|
||||
for pos in self.segrampositions:
|
||||
addr = int(pos[0], 16)
|
||||
if addr <= ramaddr and addr > segramaddr:
|
||||
segramaddr = addr
|
||||
segname = pos[1]
|
||||
|
||||
# Find where the segment is in ROM
|
||||
rompos = 0
|
||||
for pos in self.segrompositions:
|
||||
if pos[1] == segname:
|
||||
rompos = int(pos[0], 16)
|
||||
break
|
||||
|
||||
return rompos + (ramaddr - segramaddr)
|
||||
|
||||
def get_function_address(self, funcname):
|
||||
startram = None
|
||||
endram = None
|
||||
|
||||
for (index, symbol) in enumerate(list(self.symbols)):
|
||||
if symbol[1] == funcname:
|
||||
startram = int(symbol[0], 16)
|
||||
endram = int(self.symbols[index + 1][0], 16)
|
||||
break
|
||||
|
||||
if startram is None:
|
||||
raise ValueError('Unable to find %s in map' % funcname)
|
||||
|
||||
startrom = self.ramtorom(startram)
|
||||
endrom = self.ramtorom(endram)
|
||||
return (startrom, endrom)
|
||||
|
||||
def is_branch_likely(self, word):
|
||||
if word & 0xfc000000 == 0x50000000: # beql
|
||||
return True
|
||||
if word & 0xfc000000 == 0x54000000: # bnel
|
||||
return True
|
||||
if word & 0xfc000000 == 0x58000000: # blezl
|
||||
return True
|
||||
if word & 0xfc000000 == 0x5c000000: # bgtzl
|
||||
return True
|
||||
if word & 0xfc000000 == 0x01000000 and word & 0x001f0000 == 0x00020000: # bltzl
|
||||
return True
|
||||
if word & 0xfc000000 == 0x01000000 and word & 0x001f0000 == 0x00030000: # bgezl
|
||||
return True
|
||||
return False
|
||||
|
||||
def calc_checksum(self, sumfunc, algo):
|
||||
(pos, end) = self.get_function_address(sumfunc)
|
||||
self.fd.seek(pos)
|
||||
checksum = 0
|
||||
|
||||
while pos < end:
|
||||
word = int.from_bytes(self.fd.read(4), 'big')
|
||||
checksum = algo(checksum, word) & 0xffffffff
|
||||
pos += 4
|
||||
|
||||
return checksum
|
||||
|
||||
# Checksums are always written into $at with lui and ori
|
||||
# 3c0199aa lui $at,0x99aa
|
||||
# 3421bbcc ori $at,$at,0xbbcc
|
||||
def write_checksum(self, patchfunc, checksum):
|
||||
(pos, end) = self.get_function_address(patchfunc)
|
||||
self.fd.seek(pos)
|
||||
in_branchlikely = False
|
||||
upperpos = None
|
||||
lowerpos = None
|
||||
|
||||
while pos < end:
|
||||
word = int.from_bytes(self.fd.read(4), 'big')
|
||||
|
||||
if in_branchlikely:
|
||||
in_branchlikely = False
|
||||
else:
|
||||
if self.is_branch_likely(word):
|
||||
in_branchlikely = True
|
||||
elif word == 0x3c010000 | (CHECKSUM_PLACEHOLDER >> 16):
|
||||
upperpos = pos
|
||||
elif upperpos and word == 0x34210000 | (CHECKSUM_PLACEHOLDER & 0xffff):
|
||||
lowerpos = pos
|
||||
|
||||
pos += 4
|
||||
|
||||
if upperpos is None or lowerpos is None:
|
||||
print('0x%08x' % checksum)
|
||||
raise ValueError('Unable to find checksum location in %s (upperpos=%s, lowerpos=%s)' % (
|
||||
patchfunc, upperpos, lowerpos
|
||||
))
|
||||
|
||||
self.fd.seek(upperpos)
|
||||
self.fd.write((0x3c010000 | (checksum >> 16)).to_bytes(4, 'big'))
|
||||
|
||||
self.fd.seek(lowerpos)
|
||||
self.fd.write((0x34210000 | (checksum & 0xffff)).to_bytes(4, 'big'))
|
||||
|
||||
def patch(self, algo, patchfunc, sumfunc):
|
||||
checksum = self.calc_checksum(sumfunc, algo)
|
||||
self.write_checksum(patchfunc, checksum)
|
||||
|
||||
def run(self):
|
||||
self.load_map()
|
||||
|
||||
self.fd = open(sys.argv[1], 'rb+')
|
||||
|
||||
self.patch(algo01, 'func00002148', 'func000016cc')
|
||||
self.patch(algo02, 'cheatMenuHandleDialog', 'func00002148')
|
||||
self.patch(algo03, 'propobjHandlePickupByAibot', 'func0f08e2ac')
|
||||
self.patch(algo04, 'chrUncloak', 'propobjHandlePickupByAibot')
|
||||
self.patch(algo05, 'func0f028590', 'func00002078')
|
||||
self.patch(algo06, 'func0f167e7c', 'getEffectiveSlowMotion')
|
||||
self.patch(algo07, 'propAllocateEyespy', 'func0f167e7c')
|
||||
self.patch(algo08, 'chrConsiderGrenadeThrow', 'func0f15b534')
|
||||
self.patch(algo09, 'func0f09e144', 'func0f0953cc')
|
||||
self.patch(algo10, 'explosionAlertChrs', 'func0f084cf0')
|
||||
self.patch(algo11, 'func0f0069dc', 'func00015fd0')
|
||||
self.patch(algo12, 'func0f15c920', 'func0f0069dc')
|
||||
|
||||
self.fd.close()
|
||||
|
||||
if os.environ['PIRACYCHECKS']:
|
||||
tool = Tool()
|
||||
tool.run()
|
||||
|
Loading…
Reference in New Issue