diff --git a/patch/.gitignore b/patch/.gitignore new file mode 100644 index 0000000..0d0b0f4 --- /dev/null +++ b/patch/.gitignore @@ -0,0 +1,5 @@ +*.z64 +patchme +lips +entrances.asm +crc32.asm diff --git a/patch/code.asm b/patch/code.asm new file mode 100644 index 0000000..3f8ca1a --- /dev/null +++ b/patch/code.asm @@ -0,0 +1,62 @@ +[link_save]: 0x801EF670 + [has_completed_intro]: 0x5 + [have_tatl]: 0x22 + [player_name]: 0x2C + [scene_flags]: 0x470 + [week_event_reg]: 0xEF8 + [voidout_type]: 0x3CB0 + [voidout_exit]: 0x3CC4 + [exit_mod_setter]: 0x3F4A + [scene_flags_ingame]: 0x3F68 + +[starting_exit]: 0x9F87C +[default_save]: 0x120DD8 + +.org @starting_exit + li t8, 0xD800 ; modified code + li t4, 0xD800 ; modified code + +.org @default_save + .ascii "\0\0\0\0\0\0" ; ZELDA3 + .half 1 ; SoT count + .ascii ">>>>>>>>" ; player name + .half 0x30 ; hearts + .half 0x30 ; max hearts + .byte 1 ; magic level + .byte 0x30 ; magic amount + .half 0 ; rupees + .word 0 ; navi timer + .byte 1 ; has normal magic + .byte 0 ; has double magic + .half 0 ; double defense + .half 0xFF00 ; unknown + .half 0x0000 ; owls hit + .word 0xFF000008 ; unknown + .word 0x4DFFFFFF ; human buttons + .word 0x4DFFFFFF ; goron buttons + .word 0x4DFFFFFF ; zora buttons + .word 0xFDFFFFFF ; deku buttons + .word 0x00FFFFFF ; equipped slots + .word 0xFFFFFFFF ; unknown + .word 0xFFFFFFFF ; unknown + .word 0xFFFFFFFF ; unknown + .half 0x0011 ; tunic & boots + .half 0 ; unknown + ; inventory items + .byte 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ; ocarina, nothing else + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + ; mask items + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x32 ; deku mask, nothing else + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + .byte 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + ; item quantities + .byte 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0 + ; + .word 0 ; upgrades + .word 0x00003000 ; quest status (set song of time and song of healing) diff --git a/patch/mm-randomizer b/patch/mm-randomizer new file mode 100755 index 0000000..1394a4d --- /dev/null +++ b/patch/mm-randomizer @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -e + +inject=../Lua/inject +sha1=d6133ace5afaa0882cf214cf88daba39e266c078 +extracted=../dump/mm-US10-"$sha1" +rom=../../roms/everything/"Legend of Zelda, The - Majora's Mask (U) [!].z64" +lips=../Lua/lib/lips +code="0031 V00B3C000" + +if ! [ -d "$extracted" ]; then + ../z64dump.py "$rom" + mv "$sha1" "$extracted" +fi +[ -d patchme ] && rm -r patchme +cp -r "$extracted" patchme + +# don't copy entire dir; avoid copying dotfiles (.git) +mkdir -p lips +cp "$lips"/* lips + +cp "$inject/"{crc32,entrances}.asm . +luajit patch.lua code.asm patchme/"$code" + +../z64dump.py patchme +mv patchme.z64 mm-randomizer.z64 diff --git a/patch/patch.lua b/patch/patch.lua new file mode 100644 index 0000000..6df5ac5 --- /dev/null +++ b/patch/patch.lua @@ -0,0 +1,22 @@ +package.path = package.path..";./?/init.lua" + +local assemble = require "lips" + +local function inject(patch, target) + local f = io.open(target, 'r+b') + + local function write(pos, line) + assert(#line == 2, "that ain't const") + -- TODO: write hex dump format of written bytes + --print(("%08X"):format(pos), line) + f:seek('set', pos) + f:write(string.char(tonumber(line, 16))) + end + + -- offset assembly labels so they work properly, and assemble! + assemble(patch, write, {unsafe=true, offset=0}) + + f:close() +end + +inject(arg[1], arg[2])