1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-05-17 21:23:22 -07:00

refactor build scripts, use new lips features

This commit is contained in:
Connor Olding 2016-04-26 15:28:58 -07:00
parent 5691484000
commit 6c62cd965c
16 changed files with 546 additions and 164 deletions

View File

@ -36,6 +36,8 @@ short term:
set clock town first time as being watched set clock town first time as being watched
set deku mask being worn once set deku mask being worn once
add true RNG mode
long term: long term:
maybe skip zora/goron mask cutscenes (1C00 FFF3 -> 6890 0000, 1C00 FFF4 -> 9610 0000) maybe skip zora/goron mask cutscenes (1C00 FFF3 -> 6890 0000, 1C00 FFF4 -> 9610 0000)
skip giants cutscenes; give oath when any mask is acquired (0xCC00 fyi) skip giants cutscenes; give oath when any mask is acquired (0xCC00 fyi)

View File

@ -30,9 +30,9 @@ crc32:
lw t7, (t6) lw t7, (t6)
xor v0, t1, t7 xor v0, t1, t7
// iterate or return // iterate or return
subi a1, a1, 1 // cnt-- subi a1, 1 // cnt--
bnez a1, - bnez a1, -
addi a0, a0, 1 // ptr++ addi a0, 1 // ptr++
jr jr
nop nop

View File

@ -4,8 +4,8 @@ dpad_control:
// v0: number after modifications // v0: number after modifications
la t1, dpad_values la t1, dpad_values
srl t0, a1, 8 srl t0, a1, 8
andi t0, t0, 0xF andi t0, 0xF
add t0, t0, t1 add t0, t1
lb t0, 0(t0) lb t0, 0(t0)
jr jr
add v0, a0, t0 add v0, a0, t0

View File

@ -1,14 +1,3 @@
/*
.org 0x18F30
; add an entry to the end of dmatable to hold our extra code
; this actually just crashes the game so don't bother
; (no debug filename associated with it = bad pointer dereference? maybe?)
.word @vstart ; virtual start
.word 0x035E0000 ; virtual end (@vstart + @size)
.word @vstart ; physical start (should be same as virtual start)
.word 0 ; physical end (should be 0 for uncompressed)
*/
start: start:
push 4, 1, ra push 4, 1, ra

View File

@ -1,13 +1,17 @@
.include "common.asm" .include "common.asm"
[starting_exit]: 0x9F87C [game_main]: 0xCEDE0 ; 0x801748A0
[dma_overwrite]: 0xC4808 ; 0x8016A2C8
[tunic_color_overwrite]: 0x80710
[starting_exit_func]: 0x9F87C
[starting_exit_jr]: 0x9F9A4
[default_save]: 0x120DD8 [default_save]: 0x120DD8
; 0x8016A2C8 -> 0xC4808 ; 0x8016A2C8 -> 0xC4808
; 0x8016A2C8 - 0xC4808 = 0x800A5AC0 ; 0x8016A2C8 - 0xC4808 = 0x800A5AC0
; 0x8016AC0C - 0x8016A2C8 = 0x944 ; 0x8016AC0C - 0x8016A2C8 = 0x944
.org 0xCEDE0 ; 0x801748A0 .org @game_main
; this appears to be the main game loop function ; this appears to be the main game loop function
; we can "make room" for some injected code ; we can "make room" for some injected code
; by taking advantage of it never returning under normal circumstances. ; by taking advantage of it never returning under normal circumstances.
@ -21,22 +25,22 @@
li a1, @vstart ; 2 li a1, @vstart ; 2
li a2, @size ; 2 li a2, @size ; 2
jal @DMARomToRam ; 1 jal @DMARomToRam ; 1
li a0, @start ; 1 (just make sure @start can be a LUI!) li a0, @start ; 1 (just ensure @start can be a LUI!)
.org 0xC4808 ; 0x8016A2C8 .org @dma_overwrite
j dma_hook ; 1 j dma_hook ; 1
nop ; 1 nop ; 1
.org 0x9F9A4 ; JR of starting_exit's function .org @tunic_color_overwrite
j load_hook ; tail call
.org 0x80710
j tunic_color_hook j tunic_color_hook
lhu t1, 0x1DB0(t1); original code lhu t1, 0x1DB0(t1); original code
.org @starting_exit .org @starting_exit_func
li t8, 0xD800 ; modified code li t8, @starting_exit ; modified code
li t4, 0xD800 ; modified code li t4, @starting_exit ; modified code
.org @starting_exit_jr
j load_hook ; tail call
.org @default_save .org @default_save
.ascii "\0\0\0\0\0\0" ; ZELDA3 .ascii "\0\0\0\0\0\0" ; ZELDA3

View File

@ -22,3 +22,5 @@
;[link_object_ptr]: 0x244 ;[link_object_ptr]: 0x244
[scene_record_size]: 0x14 [scene_record_size]: 0x14
[starting_exit]: 0xD800

83
patch/common.sh Normal file
View File

@ -0,0 +1,83 @@
#!/usr/bin/env bash
fast=0
[[ "$1" == "fast" ]] && fast=1 && shift || [[ "$1" == "test" ]] && fast=2 && shift
args="$@"
inject="$(readlink -f ../Lua/inject)"
lips="$(readlink -f ../Lua/lib/lips)"
YAZ0="$(readlink -f ../z64yaz0)"
DUMP="$(readlink -f ../z64dump.py)"
#extracted="$(readlink -f "$extracted")"
rom="$(readlink -f "$rom")"
mkdir -p build
quiet=0
[ ! -s "$YAZ0" ] && cc -O3 "${YAZ0}.c" -o "$YAZ0"
dump() {
(cd "$(dirname "$DUMP")"; ./z64dump.py "$@")
}
if [ $fast -eq 0 ] || [ ! -d patchme ]; then
if [ -n "$sha1" ]; then
[ -d build/patchme ] && rm -r build/patchme
dump -c "$rom"
mv ../"$sha1" build/patchme
else
cp "$rom" "build/$out"
fi
fi
ratio() {
local len1="$(wc -c < "$1")"
local len2="$(wc -c < "$2")"
if [ $len1 -eq 0 ]; then
[ $quiet -le 0 ] && echo emptIy
else
let percent=(len2*100)/len1
[ $quiet -le 0 ] && echo "ratio: $percent%"
return "$((percent < 100))"
fi
}
unc() {
local in=patchme/"$1".Yaz0
local out=patchme/"$1"
[ -e "$in" ] || return 0
"$YAZ0" "$in" > "$out"
[ $quiet -le 0 ] && echo "uncompressed $1"
ratio "$out" "$in" || true
rm patchme/"$1".Yaz0
}
comp() {
local in=patchme/"$1"
local out=patchme/"$1".Yaz0
[ -e "$in" ] || return 0
"$YAZ0" "$in" > "$out"
[ $quiet -le 0 ] && echo "compressed $1"
ratio "$in" "$out" && {
[ $quiet -le 1 ] && echo "leaving uncompressed $1"
rm "$out"
} || {
rm "$in"
}
}
copy_rom() {
dd if=patchme.z64 of="$1" bs=$((1024*1024)) count="${2:-32}" status=none
}
cp *.lua build/
cp "$inject"/*.asm build/
cp *.asm build/
cd build
# don't copy entire dir; avoid copying dotfiles (.git)
mkdir -p lips
cp "$lips"/* lips

View File

@ -1,3 +1,5 @@
.push pc
[DMARomToRam]: 0x80000BFC [DMARomToRam]: 0x80000BFC
[vstart]: 0x035D0000 [vstart]: 0x035D0000
@ -15,6 +17,8 @@
.word 0 ; physical end (should be 0 for uncompressed) .word 0 ; physical end (should be 0 for uncompressed)
*/ */
.base 0x7F588E60 ; code file in memory
.org 0xB3D9E4 ; 0x800C6844 .org 0xB3D9E4 ; 0x800C6844
; this appears to be the main game loop function ; this appears to be the main game loop function
; we can "make room" for some injected code ; we can "make room" for some injected code
@ -39,3 +43,5 @@
nop nop
nop nop
nop nop
.pop pc

View File

@ -25,7 +25,7 @@ dma_hook:
jal setup_hook jal setup_hook
nop nop
pop 4, 1, ra pop 4, 1, ra
addiu sp, sp, 0xFF58 ; original code addiu sp, 0xFF58 ; original code
j 0x8016A2D0 ; return to scene setup function j 0x8016A2D0 ; return to scene setup function
sw s1, 0x30(sp) ; original code sw s1, 0x30(sp) ; original code
@ -41,11 +41,11 @@ set_scene_flag:
mflo t2 mflo t2
addu t3, t1, t2 addu t3, t1, t2
sll t4, a1, 2 ; t4 = a1*sizeof(word) sll t4, a1, 2 ; t4 = a1*sizeof(word)
addu t3, t3, t4 addu t3, t4
lw v0, (t3) ; load scene flag word lw v0, (t3) ; load scene flag word
li t6, 1 li t6, 1
sllv t6, t6, a2 sllv t6, a2
or v0, v0, t6 ; set flag or v0, t6 ; set flag
jr jr
sw v0, (t3) ; write it back sw v0, (t3) ; write it back
@ -59,8 +59,8 @@ get_event_flag:
addu t2, t1, a1 addu t2, t1, a1
lb v0, (t2) lb v0, (t2)
li t6, 1 li t6, 1
sllv t6, t6, a2 sllv t6, a2
and v0, v0, t6 and v0, t6
beqz v0, + beqz v0, +
cl v0 cl v0
li v0, 1 li v0, 1
@ -78,8 +78,8 @@ set_event_flag:
addu t2, t1, a1 addu t2, t1, a1
lb v0, (t2) lb v0, (t2)
li t6, 1 li t6, 1
sllv t6, t6, a2 sllv t6, a2
or v0, v0, t6 or v0, t6
jr jr
sb v0, (t2) sb v0, (t2)
@ -189,7 +189,7 @@ shuffle_all:
lhu t4, 0(t0) lhu t4, 0(t0)
sh t4, 2(t1) sh t4, 2(t1)
; iterate ; iterate
addi s0, s0, 1 addi s0, 1
bne s0, s1, - bne s0, s1, -
nop nop
+: +:
@ -343,7 +343,7 @@ setup_hook:
push 4, a0, ra push 4, a0, ra
lw a0, @link_save lw a0, @link_save
jal shuffle_exit jal shuffle_exit
andi a0, a0, 0xFFFF andi a0, 0xFFFF
sw v0, @link_save sw v0, @link_save
jpop 4, a0, ra jpop 4, a0, ra

View File

@ -1,69 +1,21 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
fast=0
[[ "$1" == "fast" ]] && fast=1 && shift
[[ "$1" == "test" ]] && fast=2 && shift
args="$@"
inject=../Lua/inject
sha1=d6133ace5afaa0882cf214cf88daba39e266c078 sha1=d6133ace5afaa0882cf214cf88daba39e266c078
extracted=../dump/mm-US10-"$sha1" #extracted=../dump/mm-US10-"$sha1"
rom=../roms/everything/"Legend of Zelda, The - Majora's Mask (U) [!].z64" rom=../../roms/everything/"Legend of Zelda, The - Majora's Mask (U) [!].z64"
lips=../Lua/lib/lips
out=mm-bq.z64 out=mm-bq.z64
. common.sh
code="0031 V00B3C000" code="0031 V00B3C000"
extra="1552 V02EE7040" extra="1552 V02EE7040"
ratio() {
len1="$(wc -c < "$1")"
len2="$(wc -c < "$2")"
let percent=(len2*100)/len1
echo "ratio: $percent%"
}
unc() {
[ -e patchme/"$1".Yaz0 ] || return 0
../../z64yaz0 patchme/"$1".Yaz0 > patchme/"$1"
echo "uncompressed $1"
ratio patchme/"$1" patchme/"$1".Yaz0
rm patchme/"$1".Yaz0
}
comp() {
[ -e patchme/"$1" ] || return 0
../../z64yaz0 patchme/"$1" > patchme/"$1".Yaz0
echo "compressed $1"
ratio patchme/"$1" patchme/"$1".Yaz0
rm patchme/"$1"
}
mkdir -p build
cp *.lua build/
cd build
[ ! -s ../../z64yaz0 ] && cc -O3 ../../z64yaz0.c -o ../../z64yaz0
if [ $fast -eq 0 ] || [ ! -d patchme ]; then
[ -d patchme ] && rm -r patchme
(cd ../../; ./z64dump.py -c "$rom")
mv ../../"$sha1" patchme
fi
unc "$code" unc "$code"
# don't copy entire dir; avoid copying dotfiles (.git)
mkdir -p lips
cp ../"$lips"/* lips
cp ../"$inject"/*.asm .
cp ../*.asm .
dd if=/dev/zero of=extra bs=370688 count=1 2>/dev/null dd if=/dev/zero of=extra bs=370688 count=1 2>/dev/null
luajit patch.lua -e labels.lua -o 0x80780000 "$@" extra.asm extra luajit patch.lua -e labels.lua -b 0x80780000 "$@" extra.asm extra
luajit patch.lua -i labels.lua "$@" code.asm patchme/"$code" luajit patch.lua -i labels.lua "$@" code.asm patchme/"$code"
# ensure the file is the proper size (Lua seems to expand it?) # ensure the file is the proper size (Lua seems to expand it?)
@ -73,6 +25,6 @@ rm extra
if [ $fast -ne 2 ]; then if [ $fast -ne 2 ]; then
comp "$code" comp "$code"
comp "$extra" comp "$extra"
(cd ../..; ./z64dump.py patch/build/patchme) dump patch/build/patchme
dd if=patchme.z64 of="$out" bs=$((1024*1024)) count=32 status=none copy_rom "$out" 32
fi fi

313
patch/oot-dbg-comp Normal file
View File

@ -0,0 +1,313 @@
#!/usr/bin/env bash
set -e
sha1=50bebedad9e0f10746a52b07239e47fa6c284d03
rom=../../roms/everything/"Legend of Zelda, The - Ocarina of Time - Master Quest (E) (Debug) [f1].z64"
out=oot-dbg-comp.z64
#sha1=bcc07421ead8a2388075f2051eb89c83164a2bfd
#rom=patch/oot-dbg-compressed.z64
#out=oot-dbg-comp.z64
. common.sh
code="0028 V00A94000 code"
title="0029 V00BCEF30 ovl_title"
#unc "$code"
#unc "$title"
#luajit patch.lua -o 0 ass.asm "$out"
for f in \
"0013 V00802000 icon_item_ger_static" \
"0014 V00811000 icon_item_fra_static" \
"0022 V008FF000 ger_message_data_static" \
"0023 V0093B000 fra_message_data_static" \
"1007 V02793000 syotes_scene" \
"1008 V02795000 syotes_room_0" \
"1009 V027A2000 syotes2_scene" \
"1010 V027A5000 syotes2_room_0" \
"1011 V027AF000 depth_test_scene" \
"1012 V027B0000 depth_test_room_0" \
"1305 V02AF6000 testroom_scene" \
"1306 V02AFB000 testroom_room_0" \
"1307 V02B00000 testroom_room_1" \
"1308 V02B03000 testroom_room_2" \
"1309 V02B07000 testroom_room_3" \
"1310 V02B0B000 testroom_room_4" \
"1316 V02B57000 sutaru_scene" \
"1317 V02B58000 sutaru_room_0" \
"1352 V02D00000 sasatest_scene" \
"1353 V02D03000 sasatest_room_0" \
"1446 V03280000 hairal_niwa2_scene" \
"1447 V03283000 hairal_niwa2_room_0" \
"1507 V03544000 besitu_scene" \
"1508 V03545000 besitu_room_0" \
"1516 V035B3000 test01_scene" \
"1517 V035B7000 test01_room_0" \
; do
rm patchme/"$f"
touch patchme/"$f"
echo "deleted $f"
done
declare -A raw
# must be uncompressed
raw[0000]=1
raw[0001]=1
raw[0002]=1
raw[0007]=1
raw[0008]=1
raw[0009]=1
raw[0010]=1
raw[0011]=1
raw[0012]=1
raw[0013]=1
raw[0014]=1
raw[0015]=1
raw[0016]=1
raw[0017]=1
raw[0018]=1
raw[0019]=1
raw[0020]=1
raw[0021]=1
raw[0022]=1
raw[0023]=1
raw[0024]=1
raw[0025]=1
raw[0026]=1
raw[0027]=1
raw[0501]=1
raw[0937]=1
raw[0938]=1
raw[0939]=1
raw[0940]=1
raw[0941]=1
raw[0942]=1
raw[0943]=1
raw[0944]=1
raw[0945]=1
raw[0946]=1
raw[0947]=1
raw[0948]=1
raw[0949]=1
raw[0950]=1
raw[0951]=1
raw[0952]=1
raw[0953]=1
raw[0954]=1
raw[0955]=1
raw[0956]=1
raw[0957]=1
raw[0958]=1
raw[0959]=1
raw[0960]=1
raw[0961]=1
raw[0962]=1
raw[0963]=1
raw[0964]=1
raw[0965]=1
raw[0966]=1
raw[0967]=1
raw[0968]=1
raw[0969]=1
raw[0970]=1
raw[0971]=1
raw[0972]=1
raw[0973]=1
raw[0974]=1
raw[0975]=1
raw[0976]=1
raw[0977]=1
raw[0978]=1
raw[0979]=1
raw[0980]=1
raw[0981]=1
raw[0982]=1
raw[0983]=1
raw[0984]=1
raw[0985]=1
raw[0986]=1
raw[0987]=1
raw[0988]=1
raw[0989]=1
raw[0990]=1
raw[0991]=1
raw[0992]=1
raw[0993]=1
raw[0994]=1
raw[0995]=1
raw[0996]=1
raw[0997]=1
raw[0998]=1
raw[0999]=1
raw[1000]=1
raw[1001]=1
raw[1002]=1
raw[1003]=1
raw[1004]=1
raw[1518]=1
raw[1519]=1
raw[1520]=1
raw[1521]=1
raw[1522]=1
raw[1523]=1
raw[1524]=1
raw[1525]=1
raw[1526]=1
raw[1527]=1
raw[1528]=1
raw[1529]=1
raw[1530]=1
raw[1531]=1
# other shit
raw[0003]=1
raw[0004]=1
raw[0006]=1
raw[1509]=1
raw[1510]=1
raw[1511]=1
raw[1512]=1
raw[1513]=1
raw[1514]=1
raw[1515]=1
raw[1516]=1
raw[1517]=1
# might not actually need to be uncompressed
raw[0010]=0
raw[0011]=0
raw[0012]=0
raw[0013]=0
raw[0014]=0
raw[0027]=0
raw[0501]=0
raw[0607]=0
raw[0624]=0
raw[0648]=0
raw[0649]=0
raw[0737]=0
raw[0841]=0
raw[0856]=0
raw[0869]=0
raw[0937]=0
raw[0938]=0
raw[0939]=0
raw[0940]=0
raw[0942]=0
raw[0944]=0
raw[0946]=0
raw[0948]=0
raw[0950]=0
raw[0952]=0
raw[0954]=0
raw[0956]=0
raw[0958]=0
raw[0960]=0
raw[0962]=0
raw[0964]=0
raw[0966]=0
raw[0968]=0
raw[0970]=0
raw[0972]=0
raw[0974]=0
raw[0976]=0
raw[0978]=0
raw[0980]=0
raw[0982]=0
raw[0984]=0
raw[0986]=0
raw[0988]=0
raw[0990]=0
raw[0992]=0
raw[0994]=0
raw[0996]=0
raw[0998]=0
raw[1000]=0
raw[1002]=0
raw[1004]=0
raw[1005]=0
raw[1006]=0
raw[1525]=0
raw[1526]=0
raw[1527]=0
raw[1528]=0
raw[1529]=0
raw[1530]=0
raw[1531]=0
# smaller when uncompressed
raw[0005]=1
raw[0501]=1
raw[0607]=1
raw[0624]=1
raw[0648]=1
raw[0649]=1
raw[0737]=1
raw[0841]=1
raw[0856]=1
raw[0869]=1
raw[0942]=1
raw[0944]=1
raw[0946]=1
raw[0948]=1
raw[0950]=1
raw[0952]=1
raw[0954]=1
raw[0960]=1
raw[0962]=1
raw[0964]=1
raw[0966]=1
raw[0968]=1
raw[0972]=1
raw[0974]=1
raw[0976]=1
raw[0980]=1
raw[0982]=1
raw[0984]=1
raw[0986]=1
raw[0988]=1
raw[0990]=1
raw[0992]=1
raw[0994]=1
raw[0996]=1
raw[0998]=1
raw[1000]=1
raw[1002]=1
raw[1004]=1
raw[1005]=1
raw[1006]=1
raw[1519]=1
raw[1520]=1
raw[1521]=1
raw[1522]=1
raw[1523]=1
raw[1524]=1
raw[1525]=1
raw[1526]=1
raw[1527]=1
raw[1528]=1
raw[1529]=1
raw[1530]=1
if [ $fast -ne 2 ]; then
# comp "$code"
# comp "$title"
# z64dump.py doesn't have compression support rn
# so we'll do this ourselves
for f in patchme/*; do
ext="${f##*.}" # warning: not robust
dirless="${f##*/}" # warning: not robust
n="${dirless:0:4}"
if [ -n "${raw[$n]}" ] && [ "${raw[$n]}" -eq 1 ]; then
echo "skipping $dirless"
else
quiet=1
[ "$ext" == 'Yaz0' ] || comp "$dirless"
quiet=0
fi
done
dump patch/build/patchme
copy_rom "$out" 32
fi

View File

@ -2,25 +2,14 @@
set -e set -e
inject=../Lua/inject inject=../Lua/inject
rom=../roms/everything/"Legend of Zelda, The - Ocarina of Time - Master Quest (E) (Debug) [f1].z64" rom=../../roms/everything/"Legend of Zelda, The - Ocarina of Time - Master Quest (E) (Debug) [f1].z64"
lips=../Lua/lib/lips lips=../Lua/lib/lips
out=oot-spawner.z64 out=oot-spawner.z64
mkdir -p build . common.sh
cp *.lua build/
cd build
cp ../../"$rom" "$out" luajit patch.lua \
-O 0x035D0000 -b $((0x80700000 - 0x035D0000)) \
# don't copy entire dir; avoid copying dotfiles (.git)
mkdir -p lips
cp ../"$lips"/* lips
cp ../"$inject/"*.asm .
cp ../*.asm .
luajit patch.lua -o 0 \
--extra-rom 0x035D0000 --extra-ram 0x80700000 \
'spawn O EUDB MQ.asm' "$out" 'spawn O EUDB MQ.asm' "$out"
(cd ../../; ./z64dump.py -f patch/build/"$out") dump -f patch/build/"$out"

View File

@ -2,25 +2,14 @@
set -e set -e
inject=../Lua/inject inject=../Lua/inject
rom=../roms/everything/"Legend of Zelda, The - Ocarina of Time - Master Quest (E) (Debug) [f1].z64" rom=../../roms/everything/"Legend of Zelda, The - Ocarina of Time - Master Quest (E) (Debug) [f1].z64"
lips=../Lua/lib/lips lips=../Lua/lib/lips
out=oot-widescreen.z64 out=oot-widescreen.z64
mkdir -p build . common.sh
cp *.lua build/
cd build
cp ../../"$rom" "$out" luajit patch.lua \
-O 0x035D0000 -b $((0x80700000 - 0x035D0000)) \
# don't copy entire dir; avoid copying dotfiles (.git)
mkdir -p lips
cp ../"$lips"/* lips
cp ../"$inject/"*.asm .
cp ../*.asm .
luajit patch.lua -o 0 \
--extra-rom 0x035D0000 --extra-ram 0x80700000 \
widescreen-inline.asm "$out" widescreen-inline.asm "$out"
(cd ../../; ./z64dump.py -f patch/build/"$out") dump -f patch/build/"$out"

View File

@ -1,5 +1,7 @@
#!/usr/bin/env luajit
package.path = package.path..";./?/init.lua" package.path = package.path..";./?/init.lua"
--require "test.strict"
local assemble = require "lips" local assemble = require "lips"
local cereal = require "serialize" local cereal = require "serialize"
local argparse = require "argparse" local argparse = require "argparse"
@ -10,6 +12,9 @@ local function lament(...)
end end
local function parsenum(s) local function parsenum(s)
if type(s) == 'number' then
return s
end
if s:sub(1, 2) == '0x' then if s:sub(1, 2) == '0x' then
return tonumber(s, 16) return tonumber(s, 16)
elseif s:sub(1, 1) == '0' then elseif s:sub(1, 1) == '0' then
@ -19,15 +24,45 @@ local function parsenum(s)
end end
end end
local function make_verbose_writer()
local buff = {}
local max = -1
return function(pos, b)
if pos then
buff[pos] = b
if pos > max then
max = pos
end
elseif max >= 0 then
for i=0, max, 4 do
local a = buff[i+0] or nil
local b = buff[i+1] or nil
local c = buff[i+2] or nil
local d = buff[i+3] or nil
if a or b or c or d then
a = a and ("%02X"):format(a) or '--'
b = b and ("%02X"):format(b) or '--'
c = c and ("%02X"):format(c) or '--'
d = d and ("%02X"):format(d) or '--'
print(('%08X %s'):format(i, a..b..c..d))
end
end
end
end
end
local function inject(args) local function inject(args)
local offset = args.offset and parsenum(args.offset) or 0 local offset = args.offset and parsenum(args.offset) or 0
local origin = args.origin and parsenum(args.origin) or 0 local origin = args.origin and parsenum(args.origin) or 0
local base = args.base and parsenum(args.base) or 0x80000000 local base = args.base and parsenum(args.base) or 0x80000000
local f = io.open(args.output, 'r+b') local f
if not f then if args.output then
lament("file not found:", args.output) f = io.open(args.output, 'r+b')
return if not f then
lament("file not found:", args.output)
return
end
end end
local state = {} local state = {}
@ -39,19 +74,23 @@ local function inject(args)
end end
local function write(pos, b) local function write(pos, b)
if args.extra_rom and args.extra_ram and pos >= args.extra_ram then --if args.extra_rom and args.extra_ram and pos >= args.extra_ram then
pos = pos - args.extra_ram + args.extra_rom -- pos = pos - args.extra_ram + args.extra_rom
elseif pos >= offset then --elseif pos >= offset then
if pos >= offset then
pos = pos - offset pos = pos - offset
end end
if pos >= 1024*1024*1024 then if pos >= 1024*1024*1024 then
lament("you probably don't want to do this:") lament(("oops: %08X %02X"):format(pos, b))
lament(("%08X %02X"):format(pos, b))
return return
end end
f:seek('set', pos)
f:write(string.char(b)) if f then
f:seek('set', pos)
f:write(string.char(b))
else
print(("%08X %02X"):format(pos, b))
end
end end
local options = { local options = {
@ -59,7 +98,8 @@ local function inject(args)
labels = state, labels = state,
debug_token = args.dump_token, debug_token = args.dump_token,
debug_pre = args.dump_pre, debug_pre = args.dump_pre,
debug_dump = args.dump_asm, debug_post = args.dump_post,
debug_asm = args.dump_asm,
} }
if args.offset then if args.offset then
if args.origin or args.base then if args.origin or args.base then
@ -68,39 +108,44 @@ local function inject(args)
options.offset = offset options.offset = offset
else else
options.origin = origin options.origin = origin
if args.origin or args.base then options.base = base
options.base = base
else
options.base = 0
end
end end
assemble(args.input, write, options) if f then
assemble(args.input, write, options)
else
local vb = make_verbose_writer()
assemble(args.input, vb, options)
vb()
end
if args.export then if args.export then
cereal.serialize(args.export, state) cereal.serialize(args.export, state)
end end
f:close() if f then
f:close()
end
end end
local ap = argparse("patch", "patch a binary file with assembly") local ap = argparse("patch", "patch a binary file with assembly")
-- TODO: option to dump hex or gs codes when no output is given -- TODO: option to dump hex or gs codes when no output is given
ap:argument("input", "input assembly file") ap:argument("input", "input assembly file")
ap:argument("output", "output binary file") ap:argument("output", "output binary file"):args('?')
ap:option("-o --offset", "(deprecated) offset to pass to lips", nil) ap:option("-o --offset", "(deprecated) offset to pass to lips", nil)
ap:option("-O --origin", "origin to pass to lips", nil):convert(parsenum) ap:option("-O --origin", "origin to pass to lips", nil)
ap:option("-b --base", "base to pass to lips", nil):convert(parsenum) ap:option("-b --base", "base to pass to lips", nil)
ap:option("-i --import", "import state file(s) containing labels"):count("*") ap:option("-i --import", "import state file(s) containing labels"):count("*")
ap:option("-e --export", "export state file containing labels") ap:option("-e --export", "export state file containing labels")
ap:flag("--dump-token", "(debug) dump statements to stdout after lexing") ap:flag("--dump-token", "(debug) dump statements to stdout after lexing")
ap:flag("--dump-pre", "(debug) dump statements to stdout after preprocessing") ap:flag("--dump-pre", "(debug) dump statements to stdout after preprocessing")
ap:flag("--dump-post", "(debug) dump statements to stdout after expanding")
ap:flag("--dump-asm", "(debug) dump statements to stdout after assembling") ap:flag("--dump-asm", "(debug) dump statements to stdout after assembling")
--ap:option("-s --state", "--import and --export to this file") --ap:option("-s --state", "--import and --export to this file")
-- TODO: replace this with a lua table import of associated addresses -- use -D defines instead
ap:option("--extra-rom", "dumb stuff"):convert(parsenum) --ap:option("--extra-rom", "dumb stuff"):convert(parsenum)
ap:option("--extra-ram", "dumb stuff"):convert(parsenum) --ap:option("--extra-ram", "dumb stuff"):convert(parsenum)
local inject_args = ap:parse() local inject_args = ap:parse()

View File

@ -4,10 +4,14 @@
[inject_from]: 0xB3D458 ; 0x800C62B8 [inject_from]: 0xB3D458 ; 0x800C62B8
[inject_to]: 0x80700000 [inject_to]: 0x80700000
.push pc
.base 0x7F588E60 ; code file in memory
.org @inject_from .org @inject_from
jal @inject_to jal @inject_to
.org @inject_to .pop pc
sw ra, -4(sp) sw ra, -4(sp)
sw a0, 0(sp) sw a0, 0(sp)
sw a1, 4(sp) sw a1, 4(sp)

View File

@ -6,16 +6,32 @@
[ctxt]: 0x80212020 [ctxt]: 0x80212020
[dlists]: 0x80168930 [dlists]: 0x80168930
.include "dma O EUDB MQ.asm"
[original]: 0x800C6AC4 [original]: 0x800C6AC4
[inject_from]: 0xB3D458 ; 0x800C62B8 [inject_from]: 0xB3D458 ; 0x800C62B8
[inject_to]: 0x80700000 [inject_to]: 0x80700000
; set up screen dimensions to render widescreen.
[res2_L]: 0
[res2_T]: 30
[res2_R]: 320
[res2_B]: 210
.include "dma O EUDB MQ.asm"
.push pc
.base 0x7F588E60 ; code file in memory
.org @inject_from .org @inject_from
jal @inject_to jal @inject_to
.org @inject_to .org 0xB21D30 ; 0x800AAB90
li t3, @res2_B ; 240B00D2
li t4, @res2_T ; 240C001E
.org 0xB21D48 ; 0x800AABA8
li t1, @res2_R ; 24090140
li t2, @res2_L ; 240A0000
.pop pc
sw ra, -4(sp) sw ra, -4(sp)
sw a0, 0(sp) sw a0, 0(sp)
sw a1, 4(sp) sw a1, 4(sp)
@ -32,15 +48,3 @@
addi sp, sp, 24 addi sp, sp, 24
.include "widescreen-either.asm" .include "widescreen-either.asm"
; set up screen dimensions to render widescreen.
[res2_L]: 0
[res2_T]: 30
[res2_R]: 320
[res2_B]: 210
.org 0xB21D30 ; 0x800AAB90
li t3, @res2_B ; 240B00D2
li t4, @res2_T ; 240C001E
.org 0xB21D48 ; 0x800AABA8
li t1, @res2_R ; 24090140
li t2, @res2_L ; 240A0000