├── plugins ├── payloads_10 │ ├── overlay_table.payload │ └── spawn_params.payload ├── versions │ └── 10 │ │ ├── shadow.json │ │ ├── actor_lists.json │ │ ├── ears.json │ │ └── tokens.json ├── localization │ ├── misc_packets.txt │ ├── item_flag_packets.txt │ ├── upgrade_packets.txt │ ├── equipment_packets.txt │ ├── quest_packets.txt │ ├── dungeon_packets.txt │ ├── event_flag_packets.txt │ ├── item_packets.txt │ ├── skulltula_packets.txt │ ├── equipment_numbers.json │ ├── inf_flag_packets.txt │ ├── scene_numbers.json │ └── item_numbers.json ├── packets │ ├── link_sound.json │ ├── link_loading.json │ ├── scene_flags.json │ ├── link_packet.json │ └── save_data_old.json ├── modules │ ├── actors │ │ ├── mido.opm │ │ ├── En_Am.opm │ │ ├── En_Kz.opm │ │ ├── Bg_Haka.opm │ │ ├── Obj_Tsubo.opm │ │ ├── Bg_Ddan_Kd.opm │ │ ├── Bg_Hidan_Dalm.opm │ │ ├── Bg_Ice_Shelter.opm │ │ ├── Demo_Kankyo.opm │ │ ├── Obj_Oshihiki.opm │ │ ├── cobra_statue.opm │ │ ├── Bg_Gate_Shutter.opm │ │ ├── Bg_Spot15_Rrbox.opm │ │ ├── Bg_Haka_Zou.opm │ │ ├── Bg_Heavy_Block.opm │ │ ├── En_Sw.opm │ │ ├── Bg_Mori_Bigst.opm │ │ ├── Bg_Ice_Objects.opm │ │ ├── Bg_Ice_Turara.opm │ │ ├── En_Item00.opm │ │ ├── En_Bombf_0x01F9.opm │ │ ├── Obj_Bombiwa.opm │ │ ├── Bg_Breakwall.opm │ │ ├── Bg_Dodoago.opm │ │ ├── Bg_Ydan_Sp.opm │ │ ├── Obj_Switch.opm │ │ ├── Obj_Switch_03.opm │ │ ├── Bg_Ydan_Sp_0x3.opm │ │ ├── 2d_bombable_wall.opm │ │ ├── Bg_Ydan_Sp_0x130.opm │ │ ├── En_Bombf_0x020C.opm │ │ ├── Bg_Spot02_Objects.opm │ │ ├── En_Bubble.opm │ │ ├── gohma.opm │ │ ├── mido_coords.opm │ │ ├── Bg_Hidan_Kowarerukabe.opm │ │ ├── Bg_Mizu_Bwall.opm │ │ ├── Bg_Spot16_Bombstone.opm │ │ ├── En_Item00_0x11A.opm │ │ ├── Obj_Lift.opm │ │ ├── morpha.opm │ │ ├── volvagia.opm │ │ ├── Bg_Hidan_Sima.opm │ │ ├── Obj_Timeblock.opm │ │ ├── Bg_Ydan_Maruta.opm │ │ ├── En_Box.opm │ │ ├── En_Door.opm │ │ ├── Ganon_Trials_Magic_Barrier.opm │ │ ├── phantom_ganon.opm │ │ ├── Bg_Mori_Kaitenkabe.opm │ │ ├── Obj_Kibako2.opm │ │ ├── Bg_Mori_Kaitenkabe_2.opm │ │ ├── Bg_Mori_Kaitenkabe_3.opm │ │ ├── door_of_time_collision.opm │ │ ├── barinade.opm │ │ ├── king_d.opm │ │ ├── locked_doors_sliding.opm │ │ ├── bongo_bongo.opm │ │ ├── twinrova.opm │ │ └── adult_zelda.opm │ └── templates │ │ ├── Behavior.opm │ │ ├── Rotatable.opm │ │ ├── Pushable.opm │ │ ├── ConditionalKill.opm │ │ ├── Conditional.opm │ │ ├── Pickupable_revised.opm │ │ ├── Boss.opm │ │ └── Pickupable.opm └── MaskKeeper.js ├── README.md ├── nodemon.json ├── OotOnline_Icon.ico ├── endless_debug.ps1 ├── luasocket ├── mime │ └── core.dll ├── socket │ └── core.dll └── lua │ ├── mime.lua │ ├── socket │ └── tp.lua │ └── socket.lua ├── run_gui_test.bat ├── GUI ├── images │ └── oototransparent.png ├── jquery-ui-1.12.1.custom │ ├── images │ │ ├── ui-icons_000000_256x240.png │ │ ├── ui-icons_1f1f1f_256x240.png │ │ ├── ui-icons_9fda58_256x240.png │ │ ├── ui-icons_b8ec79_256x240.png │ │ ├── ui-icons_cd0a0a_256x240.png │ │ ├── ui-icons_ffffff_256x240.png │ │ ├── ui-bg_glass_40_0a0a0a_1x400.png │ │ ├── ui-bg_glass_55_f1fbe5_1x400.png │ │ ├── ui-bg_glass_60_000000_1x400.png │ │ ├── ui-bg_gloss-wave_55_000000_500x100.png │ │ ├── ui-bg_gloss-wave_85_9fda58_500x100.png │ │ ├── ui-bg_gloss-wave_95_f6ecd5_500x100.png │ │ └── ui-bg_diagonals-small_50_262626_40x40.png │ ├── LICENSE.txt │ └── package.json ├── package.json ├── renderer.js ├── main.js └── index.html ├── OotOnlinePayloadConverter.exe ├── generate_puppet.bat ├── src ├── asm │ └── En_Link_Puppet_N0.nonovl ├── for_emulator │ └── Lua │ │ ├── pixel_icons.png │ │ ├── test │ │ ├── Behavior.lua │ │ └── PuppetTester.lua │ │ ├── ActorDataHandler.lua │ │ └── OotUtils.lua ├── command_inject │ ├── command_hook.S │ ├── actor_ctor_hook.S │ ├── actor_dtor_hook.S │ ├── actor_main_hook.S │ ├── room_actor_hook.S │ ├── tnsn_actor_hook.S │ ├── spawn_actor_hook.S │ ├── notif.inc │ ├── bin2gsc.lua │ ├── actor_main_func.S │ ├── actor_ctor_func.S │ ├── actor_dtor_func.S │ ├── z64defs.inc │ ├── room_actor_func.S │ ├── spawn_actor_func.S │ ├── tnsn_actor_func.S │ ├── makefile │ └── command_func.S ├── OotColors.js ├── OotVersion.js ├── OotLogger.js ├── OotLocalizer.js ├── GamesharkToInjectConverter.js ├── OotEncoder.js ├── OotTimeEmulation.js ├── OotPluginLoader.js ├── OotBizHawk.js ├── OotUDP.js ├── fake_test_client.js ├── OotAPI.js └── OotConfig.js ├── dev_portal ├── images │ └── oototransparent.png ├── jquery-ui-1.12.1.custom │ ├── images │ │ ├── ui-icons_000000_256x240.png │ │ ├── ui-icons_1f1f1f_256x240.png │ │ ├── ui-icons_9fda58_256x240.png │ │ ├── ui-icons_b8ec79_256x240.png │ │ ├── ui-icons_cd0a0a_256x240.png │ │ ├── ui-icons_ffffff_256x240.png │ │ ├── ui-bg_glass_40_0a0a0a_1x400.png │ │ ├── ui-bg_glass_55_f1fbe5_1x400.png │ │ ├── ui-bg_glass_60_000000_1x400.png │ │ ├── ui-bg_gloss-wave_55_000000_500x100.png │ │ ├── ui-bg_gloss-wave_85_9fda58_500x100.png │ │ ├── ui-bg_gloss-wave_95_f6ecd5_500x100.png │ │ └── ui-bg_diagonals-small_50_262626_40x40.png │ ├── LICENSE.txt │ └── package.json ├── generate_list.js └── index.html ├── .gitignore ├── OotRandoCoop.iml ├── Oot-Rando-Coop.iml ├── package.json └── OotModLoader.sln /plugins/payloads_10/overlay_table.payload: -------------------------------------------------------------------------------- 1 | 810E8564 8060 2 | 810E8566 8840 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OotModLoader 2 | A modloader for Ocarina of Time 1.0. Includes OotOnline. 3 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true, 3 | "events": { 4 | "exit": "svn update" 5 | } 6 | } -------------------------------------------------------------------------------- /OotOnline_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/OotOnline_Icon.ico -------------------------------------------------------------------------------- /endless_debug.ps1: -------------------------------------------------------------------------------- 1 | npm install nodemon -g 2 | nodemon -e js,opm -x 'node ./src/OotModLoader.js || touch ./src/app.js' -------------------------------------------------------------------------------- /luasocket/mime/core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/luasocket/mime/core.dll -------------------------------------------------------------------------------- /luasocket/socket/core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/luasocket/socket/core.dll -------------------------------------------------------------------------------- /run_gui_test.bat: -------------------------------------------------------------------------------- 1 | rmdir /s /q bin 2 | call apache-ant-1.10.5\bin\ant GUI 3 | cd bin\OotModLoader-GUI-win32-x64 4 | OotModLoader-GUI.exe -------------------------------------------------------------------------------- /GUI/images/oototransparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/images/oototransparent.png -------------------------------------------------------------------------------- /OotOnlinePayloadConverter.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/OotOnlinePayloadConverter.exe -------------------------------------------------------------------------------- /generate_puppet.bat: -------------------------------------------------------------------------------- 1 | OotOnlinePayloadConverter.exe -noovl=src/asm/En_Link_Puppet_N0.nonovl -output=plugins/payloads_10/puppet.payload -base=0x608000 -------------------------------------------------------------------------------- /src/asm/En_Link_Puppet_N0.nonovl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/src/asm/En_Link_Puppet_N0.nonovl -------------------------------------------------------------------------------- /src/for_emulator/Lua/pixel_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/src/for_emulator/Lua/pixel_icons.png -------------------------------------------------------------------------------- /dev_portal/images/oototransparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/images/oototransparent.png -------------------------------------------------------------------------------- /plugins/versions/10/shadow.json: -------------------------------------------------------------------------------- 1 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] -------------------------------------------------------------------------------- /plugins/localization/misc_packets.txt: -------------------------------------------------------------------------------- 1 | biggoron 2 | heart_containers 3 | death_counter 4 | magic_beans 5 | double_defense 6 | big_poes 7 | magic_bool 8 | magic_size 9 | magic_limit -------------------------------------------------------------------------------- /plugins/localization/item_flag_packets.txt: -------------------------------------------------------------------------------- 1 | item_flag_0 2 | item_flag_1 3 | item_flag_2 4 | item_flag_3 5 | item_flag_4 6 | item_flag_5 7 | item_flag_6 8 | item_flag_7 9 | item_flag_8 -------------------------------------------------------------------------------- /plugins/localization/upgrade_packets.txt: -------------------------------------------------------------------------------- 1 | upgrade_deku_stick 2 | upgrade_deku_nuts 3 | upgrade_scale 4 | upgrade_deku_seeds 5 | upgrade_wallet 6 | upgrade_strength 7 | upgrade_quiver 8 | upgrade_bombs -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-icons_000000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-icons_000000_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-icons_1f1f1f_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-icons_1f1f1f_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-icons_9fda58_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-icons_9fda58_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-icons_b8ec79_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-icons_b8ec79_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_glass_40_0a0a0a_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_glass_40_0a0a0a_1x400.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_f1fbe5_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_f1fbe5_1x400.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_glass_60_000000_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_glass_60_000000_1x400.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_000000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_000000_256x240.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_1f1f1f_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_1f1f1f_256x240.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_9fda58_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_9fda58_256x240.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_b8ec79_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_b8ec79_256x240.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_55_000000_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_55_000000_500x100.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_85_9fda58_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_85_9fda58_500x100.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_95_f6ecd5_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_95_f6ecd5_500x100.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_glass_40_0a0a0a_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_glass_40_0a0a0a_1x400.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_f1fbe5_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_glass_55_f1fbe5_1x400.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_glass_60_000000_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_glass_60_000000_1x400.png -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/images/ui-bg_diagonals-small_50_262626_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/GUI/jquery-ui-1.12.1.custom/images/ui-bg_diagonals-small_50_262626_40x40.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_55_000000_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_55_000000_500x100.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_85_9fda58_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_85_9fda58_500x100.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_95_f6ecd5_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_gloss-wave_95_f6ecd5_500x100.png -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_diagonals-small_50_262626_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/72f393f4a1b9dfecdd32641633e9e896/OotModLoader/HEAD/dev_portal/jquery-ui-1.12.1.custom/images/ui-bg_diagonals-small_50_262626_40x40.png -------------------------------------------------------------------------------- /plugins/packets/link_sound.json: -------------------------------------------------------------------------------- 1 | { 2 | "packet_id": "link_sound", 3 | "readHandler": "bundle", 4 | "bundles": [ 5 | { 6 | "key": "sfx", 7 | "addr": "@OotOnline_Context@", 8 | "offset": "0x88", 9 | "readHandler": "81" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /dev_portal/generate_list.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | let list = []; 4 | 5 | fs.readdirSync("./dist").forEach(file => { 6 | if (file.indexOf(".zip") > -1) { 7 | list.push(file); 8 | } 9 | }); 10 | 11 | fs.writeFileSync("./dist/dist.json", JSON.stringify(list, null, 2)); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | packages/ 3 | node_modules/ 4 | src/for_emulator/Lua/Vanillamizer OoT.bin 5 | OotModLoader-config.json 6 | apache-ant-1.10.5/ 7 | bin/ 8 | dist/ 9 | rom stuff/ 10 | mods/ 11 | temp/ 12 | rom/ 13 | lua tests/ 14 | electron/ 15 | electron_testing/ 16 | turned_off_plugins/ 17 | .vscode/ 18 | -------------------------------------------------------------------------------- /src/command_inject/command_hook.S: -------------------------------------------------------------------------------- 1 | .set command_func, COMMAND_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent command_hook 6 | .type command_hook, @function 7 | command_hook: 8 | 9 | /* call hook function */ 10 | .set noreorder 11 | jal command_func 12 | 13 | .end command_hook 14 | -------------------------------------------------------------------------------- /plugins/payloads_10/spawn_params.payload: -------------------------------------------------------------------------------- 1 | 81600140 0001 2 | 81600142 4600 3 | 81600144 C500 4 | 81600146 4600 5 | 81600148 0000 6 | 8160014A 0000 7 | 8160014C 0000 8 | 8160014E 0000 9 | 81600130 005D 10 | 81600132 0000 11 | 81600134 0000 12 | 81600136 0000 13 | 81600138 0000 14 | 8160013A 0000 15 | 8160013C 0000 16 | 8160013E 0000 -------------------------------------------------------------------------------- /src/command_inject/actor_ctor_hook.S: -------------------------------------------------------------------------------- 1 | .set actor_ctor_func, ACTOR_CTOR_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent actor_ctor_hook 6 | .type actor_ctor_hook, @function 7 | actor_ctor_hook: 8 | 9 | /* call hook function */ 10 | .set noreorder 11 | jal actor_ctor_func 12 | 13 | .end actor_ctor_hook 14 | -------------------------------------------------------------------------------- /src/command_inject/actor_dtor_hook.S: -------------------------------------------------------------------------------- 1 | .set actor_dtor_func, ACTOR_DTOR_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent actor_dtor_hook 6 | .type actor_dtor_hook, @function 7 | actor_dtor_hook: 8 | 9 | /* call hook function */ 10 | .set noreorder 11 | jal actor_dtor_func 12 | 13 | .end actor_dtor_hook 14 | -------------------------------------------------------------------------------- /src/command_inject/actor_main_hook.S: -------------------------------------------------------------------------------- 1 | .set actor_main_func, ACTOR_MAIN_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent actor_main_hook 6 | .type actor_main_hook, @function 7 | actor_main_hook: 8 | 9 | /* call hook function */ 10 | .set noreorder 11 | jal actor_main_func 12 | 13 | .end actor_main_hook 14 | -------------------------------------------------------------------------------- /src/command_inject/room_actor_hook.S: -------------------------------------------------------------------------------- 1 | .set room_actor_func, ROOM_ACTOR_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent room_actor_hook 6 | .type room_actor_hook, @function 7 | room_actor_hook: 8 | 9 | /* call hook function */ 10 | .set noreorder 11 | jal room_actor_func 12 | 13 | .end room_actor_hook 14 | -------------------------------------------------------------------------------- /src/command_inject/tnsn_actor_hook.S: -------------------------------------------------------------------------------- 1 | .set tnsn_actor_func, TNSN_ACTOR_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent tnsn_actor_hook 6 | .type tnsn_actor_hook, @function 7 | tnsn_actor_hook: 8 | 9 | /* call hook function */ 10 | .set noreorder 11 | jal tnsn_actor_func 12 | 13 | .end tnsn_actor_hook 14 | -------------------------------------------------------------------------------- /plugins/versions/10/actor_lists.json: -------------------------------------------------------------------------------- 1 | { 2 | "global": "0x1C84A0", 3 | "table_offset": "0x1C34", 4 | "switch": 0, 5 | "prop_1": 8, 6 | "player": 16, 7 | "bombs": 24, 8 | "npcs": 32, 9 | "enemy": 40, 10 | "prop": 48, 11 | "item_action": 56, 12 | "misc": 64, 13 | "boss": 72, 14 | "door": 80, 15 | "chests": 88 16 | } -------------------------------------------------------------------------------- /plugins/modules/actors/mido.opm: -------------------------------------------------------------------------------- 1 | // Mido 2 | let Mido = { 3 | actor: "Mido", 4 | version_offsets: { 5 | debug: 0x180, 6 | 10: 0x180 7 | }, 8 | readHandler: "actor_behavior", 9 | writeHandler: "actor_behavior", 10 | actorid: 0x016D, 11 | actorCategory: 4, 12 | template: "Behavior" 13 | } 14 | 15 | module.exports = Mido; -------------------------------------------------------------------------------- /plugins/versions/10/ears.json: -------------------------------------------------------------------------------- 1 | [0,0,255,255,255,255,0,0,0,0,0,0,255,255,0,0,0,0,255,255,0,0,0,0,0,97,251,77,255,16,0,1,59,75,11,43,210,132,0,0,234,101,70,169,181,55,0,0,84,22,231,172,240,142,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,0,97,251,77,0,240,0,1,59,75,11,43,45,124,0,0,234,101,70,169,74,201,0,0,171,234,24,84,240,142,0,0,0,0,0,0,0,0,0,0] -------------------------------------------------------------------------------- /plugins/modules/actors/En_Am.opm: -------------------------------------------------------------------------------- 1 | // Armor Statue 2 | let En_Am = { 3 | actor: "En_Am", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x0054, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = En_Am; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Kz.opm: -------------------------------------------------------------------------------- 1 | // King Zora 2 | let En_Kz = { 3 | actor: "En_Kz", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x0164, 12 | actorCategory: 4, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = En_Kz; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Haka.opm: -------------------------------------------------------------------------------- 1 | // Gravestone 2 | let Bg_Haka = { 3 | actor: "Bg_Haka", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x009D, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Bg_Haka; -------------------------------------------------------------------------------- /src/command_inject/spawn_actor_hook.S: -------------------------------------------------------------------------------- 1 | .set spawn_actor_func, SPAWN_ACTOR_FUNC_ADDR 2 | 3 | .section .text 4 | 5 | .ent spawn_actor_hook 6 | .type spawn_actor_hook, @function 7 | spawn_actor_hook: 8 | 9 | /* jump to hook function */ 10 | .set noreorder 11 | move $t9, $ra 12 | jal spawn_actor_func 13 | nop 14 | 15 | .end spawn_actor_hook 16 | -------------------------------------------------------------------------------- /GUI/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "productName": "OotModLoader-GUI", 3 | "name": "ootmodloader", 4 | "version": "1.0.0", 5 | "description": "Online play in Ocarina of Time", 6 | "main": "main.js", 7 | "scripts": { 8 | "start": "electron ." 9 | }, 10 | "author": "Team Ooto", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "electron": "4.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plugins/localization/equipment_packets.txt: -------------------------------------------------------------------------------- 1 | equipment_slot_0 2 | equipment_slot_1 3 | equipment_slot_2 4 | equipment_slot_3 5 | equipment_slot_4 6 | equipment_slot_5 7 | equipment_slot_6 8 | equipment_slot_7 9 | equipment_slot_8 10 | equipment_slot_9 11 | equipment_slot_10 12 | equipment_slot_11 13 | equipment_slot_12 14 | equipment_slot_13 15 | equipment_slot_14 16 | equipment_slot_15 -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Tsubo.opm: -------------------------------------------------------------------------------- 1 | // Pots 2 | let Obj_Tsubo = { 3 | actor: "Obj_Tsubo", 4 | version_offsets: { 5 | debug: 0x118, 6 | 10: 0x118 7 | }, 8 | readHandler: "fourBytes", 9 | writeHandler: "actor_word_copy", 10 | actorid: 0x014E, 11 | actorCategory: 6, 12 | template: "Pickupable_revised" 13 | } 14 | 15 | module.exports = Obj_Tsubo; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ddan_Kd.opm: -------------------------------------------------------------------------------- 1 | // Dodongo stairs 2 | let Bg_Ddan_Kd = { 3 | actor: "Bg_Ddan_Kd", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x005C, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Bg_Ddan_Kd; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Hidan_Dalm.opm: -------------------------------------------------------------------------------- 1 | // Megaton Statue 2 | let Bg_Hidan_Dalm = { 3 | actor: "Bg_Hidan_Dalm", 4 | version_offsets: { 5 | debug: 0x154, 6 | 10: 0x154 7 | }, 8 | readHandler: "actor_behavior", 9 | writeHandler: "actor_behavior", 10 | actorid: 0x0040, 11 | actorCategory: 1, 12 | template: "Behavior" 13 | } 14 | 15 | module.exports = Bg_Hidan_Dalm; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ice_Shelter.opm: -------------------------------------------------------------------------------- 1 | // Red Ice 2 | let Bg_Ice_Shelter = { 3 | actor: "Bg_Ice_Shelter", 4 | version_offsets: { 5 | debug: 0x154, 6 | 10: 0x154 7 | }, 8 | readHandler: "actor_behavior", 9 | writeHandler: "actor_behavior", 10 | actorid: 0x00EF, 11 | actorCategory: 1, 12 | template: "Behavior" 13 | } 14 | 15 | module.exports = Bg_Ice_Shelter; -------------------------------------------------------------------------------- /plugins/modules/actors/Demo_Kankyo.opm: -------------------------------------------------------------------------------- 1 | // Temple of Time Door 2 | let Demo_Kankyo = { 3 | actor: "Demo_Kankyo", 4 | version_offsets: { 5 | debug: 0x168, 6 | 10: 0x158 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0x4, 11 | actorid: 0x008C, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Demo_Kankyo; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Oshihiki.opm: -------------------------------------------------------------------------------- 1 | // Movable Block 2 | let Obj_Oshihiki = { 3 | actor: "Obj_Oshihiki", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x00FF, 12 | actorCategory: 6, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Obj_Oshihiki; -------------------------------------------------------------------------------- /plugins/modules/actors/cobra_statue.opm: -------------------------------------------------------------------------------- 1 | // Cobra Statue 2 | let Cobra_statue = { 3 | actor: "Cobra_statue", 4 | version_offsets: { 5 | debug: 0xB4, 6 | 10: 0xB4 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0x6, 11 | actorid: 0x00FC, 12 | actorCategory: 6, 13 | template: "Rotatable" 14 | } 15 | 16 | module.exports = Cobra_statue; -------------------------------------------------------------------------------- /src/command_inject/notif.inc: -------------------------------------------------------------------------------- 1 | .set notif_buf, 0x806001E0 2 | .set notif_pos, 0x806011E0 3 | .set notif_ctxt, 0x806011E4 4 | .set NOTIF_BUF_LENGTH, 0x00000100 5 | .set NOTIF_CTXT_NONOTIF, 0xFFFFFFFF 6 | .set NOTIF_TNSN_ACTOR, 0x00000001 7 | .set NOTIF_ROOM_ACTOR, 0x00000002 8 | .set NOTIF_SPAWN_ACTOR, 0x00000003 9 | -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Gate_Shutter.opm: -------------------------------------------------------------------------------- 1 | // Kakariko Gate 2 | let Bg_Gate_Shutter = { 3 | actor: "Bg_Gate_Shutter", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x100, 12 | actorCategory: 7, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Bg_Gate_Shutter; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Spot15_Rrbox.opm: -------------------------------------------------------------------------------- 1 | // Milk Crates 2 | let Bg_Spot15_Rrbox = { 3 | actor: "Bg_Spot15_Rrbox", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x0107, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Bg_Spot15_Rrbox; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Haka_Zou.opm: -------------------------------------------------------------------------------- 1 | // Bombable Rubble in Shadow Temple 2 | let Bg_Haka_Zou = { 3 | actor: "Bg_Haka_Zou", 4 | version_offsets: { 5 | debug: 0x154, 6 | 10: 0x154 7 | }, 8 | readHandler: "actor_behavior", 9 | writeHandler: "actor_behavior", 10 | actorid: 0x00BE, 11 | actorCategory: 6, 12 | template: "Behavior" 13 | } 14 | 15 | module.exports = Bg_Haka_Zou; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Heavy_Block.opm: -------------------------------------------------------------------------------- 1 | // Golden Gauntlet Block 2 | let Bg_Heavy_Block = { 3 | actor: "Bg_Heavy_Block", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x0092, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Bg_Heavy_Block; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Sw.opm: -------------------------------------------------------------------------------- 1 | // Golden Skulltulas. 2 | let En_Sw = { 3 | actor: "En_Sw", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | actorid: 0x0095, 10 | actorCategory: 4, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = En_Sw; -------------------------------------------------------------------------------- /plugins/packets/link_loading.json: -------------------------------------------------------------------------------- 1 | { 2 | "packet_id": "link_loading", 3 | "readHandler": "bundle", 4 | "bundles": [ 5 | { 6 | "key": "link_loading", 7 | "addr": "@link_loading@", 8 | "offset": "0x0", 9 | "readHandler": "80" 10 | }, 11 | { 12 | "key": "link_entrance", 13 | "addr": "@last_entrance@", 14 | "offset": "0x0", 15 | "readHandler": "81" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Mori_Bigst.opm: -------------------------------------------------------------------------------- 1 | // Forest temple miniboss room platform 2 | let Bg_Mori_Bigst = { 3 | actor: "Bg_Mori_Bigst", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x0086, 12 | actorCategory: 1, 13 | template: "Pushable" 14 | } 15 | 16 | module.exports = Bg_Mori_Bigst; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ice_Objects.opm: -------------------------------------------------------------------------------- 1 | // Ice Cavern puzzle block. 2 | let Bg_Ice_Objects = { 3 | actor: "Bg_Ice_Objects", 4 | version_offsets: { 5 | debug: 0x24, 6 | 10: 0x24 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x00D6, 12 | actorCategory: 6, 13 | template: "Pushable", 14 | posOnly: true 15 | } 16 | 17 | module.exports = Bg_Ice_Objects; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ice_Turara.opm: -------------------------------------------------------------------------------- 1 | // Icicles 2 | let Bg_Ice_Turara = { 3 | actor: "Bg_Ice_Turara", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | actorid: 0x1C7, 10 | actorCategory: 6, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = Bg_Ice_Turara; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Item00.opm: -------------------------------------------------------------------------------- 1 | // Collectable items. 2 | let En_Item00 = { 3 | actor: "En_Item00", 4 | version_offsets: { 5 | debug: 0x15A, 6 | 10: 0x14A 7 | }, 8 | readHandler: "80", 9 | actorid: 0x0015, 10 | actorCategory: 8, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value !== 0xFF; 14 | } 15 | } 16 | 17 | module.exports = En_Item00; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Bombf_0x01F9.opm: -------------------------------------------------------------------------------- 1 | // Bomb flowers 2 | let En_Bombf = { 3 | actor: "En_Bombf", 4 | version_offsets: { 5 | debug: 0x01F9, 6 | 10: 0x1E9 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x004C, 11 | actorCategory: 6, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = En_Bombf; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Bombiwa.opm: -------------------------------------------------------------------------------- 1 | // Bombiwas. Need I explain? 2 | let Obj_Bombiwa = { 3 | actor: "Obj_Bombiwa", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | actorid: 0x127, 10 | actorCategory: 6, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = Obj_Bombiwa; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Breakwall.opm: -------------------------------------------------------------------------------- 1 | // Bombable Wall 2 | let Bg_Breakwall = { 3 | actor: "Bg_Breakwall", 4 | version_offsets: { 5 | debug: 0x17D, 6 | 10: 0x16D 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x0059, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = Bg_Breakwall; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Dodoago.opm: -------------------------------------------------------------------------------- 1 | // Dodongo's head 2 | let Bg_Dodoago = { 3 | actor: "Bg_Dodoago", 4 | version_offsets: { 5 | debug: 0x00B4, 6 | 10: 0x00B4 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | actorid: 0x003F, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = Bg_Dodoago; -------------------------------------------------------------------------------- /plugins/localization/quest_packets.txt: -------------------------------------------------------------------------------- 1 | quest_slot_0 2 | quest_slot_1 3 | quest_slot_2 4 | quest_slot_3 5 | quest_slot_4 6 | quest_slot_5 7 | quest_slot_6 8 | quest_slot_7 9 | quest_slot_8 10 | quest_slot_9 11 | quest_slot_10 12 | quest_slot_11 13 | quest_slot_12 14 | quest_slot_13 15 | quest_slot_14 16 | quest_slot_15 17 | quest_slot_16 18 | quest_slot_17 19 | quest_slot_18 20 | quest_slot_19 21 | quest_slot_20 22 | quest_slot_21 23 | quest_slot_22 24 | quest_slot_23 -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ydan_Sp.opm: -------------------------------------------------------------------------------- 1 | // Web 2 | let Bg_Ydan_Sp = { 3 | actor: "Bg_Ydan_Sp", 4 | version_offsets: { 5 | debug: 0x181, 6 | 10: 0x171 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x000F, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value === 0xB; 15 | } 16 | } 17 | 18 | module.exports = Bg_Ydan_Sp; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Switch.opm: -------------------------------------------------------------------------------- 1 | // Switch. 2 | let Obj_Switch = { 3 | actor: "Obj_Switch", 4 | version_offsets: { 5 | debug: 0x54, 6 | 10: 0x54 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | actorid: 0x012A, 11 | size: 0x04, 12 | actorCategory: 0, 13 | template: "Conditional", 14 | conditional: function (packet) { 15 | return true; 16 | } 17 | } 18 | 19 | module.exports = Obj_Switch; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Switch_03.opm: -------------------------------------------------------------------------------- 1 | // Switch - Eye variant. 2 | let Obj_Switch = { 3 | actor: "Obj_Switch", 4 | version_offsets: { 5 | debug: 0x171, 6 | 10: 0x161 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x012A, 11 | actorCategory: 0, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = Obj_Switch; -------------------------------------------------------------------------------- /plugins/localization/dungeon_packets.txt: -------------------------------------------------------------------------------- 1 | dungeon_items_0 2 | dungeon_items_1 3 | dungeon_items_2 4 | dungeon_items_3 5 | dungeon_items_4 6 | dungeon_items_5 7 | dungeon_items_6 8 | dungeon_items_7 9 | dungeon_items_8 10 | dungeon_items_9 11 | dungeon_items_10 12 | dungeon_items_11 13 | dungeon_items_12 14 | dungeon_items_13 15 | dungeon_items_14 16 | dungeon_items_15 17 | dungeon_items_16 18 | dungeon_items_17 19 | dungeon_items_18 20 | dungeon_items_19 21 | dungeon_items_20 -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ydan_Sp_0x3.opm: -------------------------------------------------------------------------------- 1 | // Web 2 | let Bg_Ydan_Sp = { 3 | actor: "Bg_Ydan_Sp", 4 | version_offsets: { 5 | debug: 0x3, 6 | 10: 0x3 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x000F, 11 | actorCategory: 1, 12 | template: "ConditionalKill", 13 | conditional: function (packet) { 14 | return packet.data.value === 0xFF; 15 | } 16 | } 17 | 18 | module.exports = Bg_Ydan_Sp; -------------------------------------------------------------------------------- /plugins/modules/actors/2d_bombable_wall.opm: -------------------------------------------------------------------------------- 1 | // 2D Bombable Wall 2 | let bombable_wall_2d = { 3 | actor: "bombable_wall_2d", 4 | version_offsets: { 5 | debug: 0x288, 6 | 10: 0x288 7 | }, 8 | readHandler: "fourBytes", 9 | actorid: 0xD0, 10 | actorCategory: 1, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = bombable_wall_2d; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ydan_Sp_0x130.opm: -------------------------------------------------------------------------------- 1 | // Web 2 | let Bg_Ydan_Sp = { 3 | actor: "Bg_Ydan_Sp", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x000F, 11 | actorCategory: 1, 12 | template: "ConditionalKill", 13 | conditional: function (packet) { 14 | return packet.data.value === 0x0; 15 | } 16 | } 17 | 18 | module.exports = Bg_Ydan_Sp; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Bombf_0x020C.opm: -------------------------------------------------------------------------------- 1 | // Bomb flowers 2 | let En_Bombf = { 3 | actor: "En_Bombf", 4 | version_offsets: { 5 | debug: 0x020C, 6 | 10: 0x1FC 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0x4, 11 | actorid: 0x004C, 12 | actorCategory: 6, 13 | template: "Conditional", 14 | conditional: function (packet) { 15 | return true; 16 | } 17 | } 18 | 19 | module.exports = En_Bombf; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Spot02_Objects.opm: -------------------------------------------------------------------------------- 1 | // Royal Family tombstone 2 | let Bg_Spot02_Objects = { 3 | actor: "Bg_Spot02_Objects", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | actorid: 0x009C, 10 | actorCategory: 1, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = Bg_Spot02_Objects; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Bubble.opm: -------------------------------------------------------------------------------- 1 | // Shabom (Bubble Enemy) 2 | let En_Bubble = { 3 | actor: "En_Bubble", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x002D, 11 | actorCategory: 5, 12 | template: "ConditionalKill", 13 | conditional: function (packet) { 14 | return packet.data.value === 0x0; 15 | } 16 | } 17 | 18 | module.exports = En_Bubble; -------------------------------------------------------------------------------- /plugins/modules/actors/gohma.opm: -------------------------------------------------------------------------------- 1 | // Boss Gohma 2 | let Gohma = { 3 | actor: "Gohma", 4 | version_offsets: { 5 | debug: 0x180, 6 | 10: 0x180 7 | }, 8 | readHandler: "actor_behavior", 9 | actorid: 0x0028, 10 | actorCategory: 9, 11 | template: "Boss", 12 | exit: 0x0209, 13 | cutscene: 0x0000, 14 | conditional: function (packet) { 15 | return packet.data.value === 0x2384; 16 | } 17 | } 18 | 19 | module.exports = Gohma; -------------------------------------------------------------------------------- /plugins/modules/actors/mido_coords.opm: -------------------------------------------------------------------------------- 1 | // Mido 2 | let Mido_walking = { 3 | actor: "Mido_walking", 4 | version_offsets: { 5 | debug: 0x60, 6 | 10: 0x60 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0xC, 11 | actorid: 0x016D, 12 | actorCategory: 4, 13 | template: "Conditional", 14 | conditional: function (packet) { 15 | return true; 16 | } 17 | } 18 | 19 | module.exports = Mido_walking; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Hidan_Kowarerukabe.opm: -------------------------------------------------------------------------------- 1 | // Enemy 2 | let Bg_Hidan_Kowarerukabe = { 3 | actor: "Bg_Hidan_Kowarerukabe", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "fourBytes", 9 | actorid: 0x00CF, 10 | actorCategory: 1, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = Bg_Hidan_Kowarerukabe; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Mizu_Bwall.opm: -------------------------------------------------------------------------------- 1 | // Switch - Eye variant. 2 | let Bg_Mizu_Bwall = { 3 | actor: "Bg_Mizu_Bwall", 4 | version_offsets: { 5 | debug: 0x017D, 6 | 10: 0x016D 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x59, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value > 0; 15 | } 16 | } 17 | 18 | module.exports = Bg_Mizu_Bwall; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Spot16_Bombstone.opm: -------------------------------------------------------------------------------- 1 | // Dodongo's entrance rock. 2 | let Bg_Spot16_Bombstone = { 3 | actor: "Bg_Spot16_Bombstone", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | actorid: 0x00CD, 10 | actorCategory: 6, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = Bg_Spot16_Bombstone; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Item00_0x11A.opm: -------------------------------------------------------------------------------- 1 | // Collectable items. 2 | let En_Item00 = { 3 | actor: "En_Item00", 4 | version_offsets: { 5 | debug: 0x11A, 6 | 10: 0x11A 7 | }, 8 | readHandler: "80", 9 | actorid: 0x0015, 10 | actorCategory: 8, 11 | template: "ConditionalKill", 12 | conditional: function (packet) { 13 | return packet.data.value === 0xAA; 14 | }, 15 | filter: { offset: 0x1D, data: 0x06 } 16 | } 17 | 18 | module.exports = En_Item00; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Lift.opm: -------------------------------------------------------------------------------- 1 | // Falling platform in Deku Tree slingshot room. 2 | let Obj_Lift = { 3 | actor: "Obj_Lift", 4 | version_offsets: { 5 | debug: 0x160, 6 | 10: 0x150 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x012C, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value > 0; 15 | } 16 | } 17 | 18 | module.exports = Obj_Lift; -------------------------------------------------------------------------------- /plugins/modules/actors/morpha.opm: -------------------------------------------------------------------------------- 1 | // Morpha 2 | let Gohma = { 3 | actor: "Morpha", 4 | version_offsets: { 5 | debug: 0xAF, 6 | 10: 0xAF 7 | }, 8 | readHandler: "80", 9 | actorid: 0x00C4, 10 | actorCategory: 9, 11 | template: "Boss", 12 | exit: 0x0102, 13 | cutscene: 0xFFF0, 14 | conditional: function (packet) { 15 | return packet.data.value === 0x0 || packet.data.value >= 100; 16 | } 17 | } 18 | 19 | module.exports = Gohma; 20 | -------------------------------------------------------------------------------- /plugins/modules/actors/volvagia.opm: -------------------------------------------------------------------------------- 1 | // Boss Volvagia 2 | let volvagia = { 3 | actor: "volvagia", 4 | version_offsets: { 5 | debug: 0x180, 6 | 10: 0x180 7 | }, 8 | readHandler: "actor_behavior", 9 | actorid: 0x00A2, 10 | actorCategory: 9, 11 | template: "Boss", 12 | exit: 0x0564, 13 | cutscene: 0x0000, 14 | conditional: function (packet) { 15 | return packet.data.value === 0x19A8; 16 | } 17 | } 18 | 19 | module.exports = volvagia; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Hidan_Sima.opm: -------------------------------------------------------------------------------- 1 | // Fire Temple Sinking Platforms 2 | let Bg_Hidan_Sima = { 3 | actor: "Bg_Hidan_Sima", 4 | version_offsets: { 5 | debug: 0x160, 6 | 10: 0x150 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x0046, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value > 0x0; 15 | } 16 | } 17 | 18 | module.exports = Bg_Hidan_Sima; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Timeblock.opm: -------------------------------------------------------------------------------- 1 | // Song of Time block 2 | let Obj_Timeblock = { 3 | actor: "Obj_Timeblock", 4 | version_offsets: { 5 | debug: 0x174, 6 | 10: 0x164 7 | }, 8 | readHandler: "range", 9 | writeHandler: "actorRange", 10 | size: 0x1, 11 | actorid: 0x1D1, 12 | actorCategory: 7, 13 | template: "Conditional", 14 | conditional: function (packet) { 15 | return true; 16 | } 17 | } 18 | 19 | module.exports = Obj_Timeblock; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Ydan_Maruta.opm: -------------------------------------------------------------------------------- 1 | // Ladder in Deku Tree slingshot room. 2 | let Bg_Ydan_Maruta = { 3 | actor: "Bg_Ydan_Maruta", 4 | version_offsets: { 5 | debug: 0x17D, 6 | 10: 0x16D 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x0051, 11 | actorCategory: 6, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value == 0x0B; 15 | } 16 | } 17 | 18 | module.exports = Bg_Ydan_Maruta; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Box.opm: -------------------------------------------------------------------------------- 1 | // Treasure Chests. 2 | let En_Box = { 3 | actor: "En_Box", 4 | version_offsets: { 5 | debug: 0x1F4, 6 | 10: 0x1E4 7 | }, 8 | readHandler: "81", 9 | writeHandler: "actor", 10 | actorid: 0x000A, 11 | actorCategory: 11, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value !== 0xFFFF || packet.data.value === 0x0078; 15 | }, 16 | value: 0xFF88 17 | } 18 | 19 | module.exports = En_Box; -------------------------------------------------------------------------------- /plugins/modules/actors/En_Door.opm: -------------------------------------------------------------------------------- 1 | // Standard Door 2 | let En_Door = { 3 | actor: "En_Door", 4 | version_offsets: { 5 | debug: 0x197, 6 | 10: 0x187 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x0009, 11 | actorCategory: 10, 12 | template: "Conditional", 13 | overrideSafety: true, 14 | value: 0, 15 | conditional: function (packet) { 16 | return packet.data.value === 0; 17 | } 18 | } 19 | 20 | module.exports = En_Door; -------------------------------------------------------------------------------- /plugins/modules/actors/Ganon_Trials_Magic_Barrier.opm: -------------------------------------------------------------------------------- 1 | let Ganon_Trials_Magic_Barrier = { 2 | actor: "Ganon_Trials_Magic_Barrier", 3 | version_offsets: { 4 | debug: 0x130, 5 | 10: 0x130 6 | }, 7 | readHandler: "80", 8 | actorid: 0x1A7, 9 | actorCategory: 6, 10 | template: "ConditionalKill", 11 | overrideSafety: true, 12 | conditional: function (packet) { 13 | return packet.data.value === 0x0; 14 | } 15 | } 16 | 17 | module.exports = Ganon_Trials_Magic_Barrier; -------------------------------------------------------------------------------- /plugins/modules/actors/phantom_ganon.opm: -------------------------------------------------------------------------------- 1 | // Phantom Ganon 2 | let Phantom_Ganon = { 3 | actor: "Phantom_Ganon", 4 | version_offsets: { 5 | debug: 0x180, 6 | 10: 0x180 7 | }, 8 | readHandler: "actor_behavior", 9 | actorid: 0x0028, 10 | actorCategory: 9, 11 | template: "Boss", 12 | exit: 0x00EE, 13 | cutscene: 0xFFF8, 14 | conditional: function (packet) { 15 | return packet.data.value === 0x260C; 16 | } 17 | } 18 | 19 | module.exports = Phantom_Ganon; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Mori_Kaitenkabe.opm: -------------------------------------------------------------------------------- 1 | //Forest Temple rotating walls from room before boss 2 | let Bg_Mori_Kaitenkabe = { 3 | actor: "Bg_Mori_Kaitenkabe", 4 | version_offsets: { 5 | debug: 0xB6, 6 | 10: 0xB6 7 | }, 8 | readHandler: "81", 9 | writeHandler: "actor", 10 | actorid: 0x0088, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = Bg_Mori_Kaitenkabe; -------------------------------------------------------------------------------- /plugins/modules/actors/Obj_Kibako2.opm: -------------------------------------------------------------------------------- 1 | // Large Crate 2 | let Obj_Kibako2 = { 3 | actor: "Obj_Kibako2", 4 | version_offsets: { 5 | debug: 0x130, 6 | 10: 0x130 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x1A0, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return packet.data.value === 0; 15 | }, 16 | write_offset: 0x19, 17 | value: 0x1 18 | } 19 | 20 | module.exports = Obj_Kibako2; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Mori_Kaitenkabe_2.opm: -------------------------------------------------------------------------------- 1 | //Forest Temple rotating walls from room before boss 2 | let Bg_Mori_Kaitenkabe = { 3 | actor: "Bg_Mori_Kaitenkabe", 4 | version_offsets: { 5 | debug: 0x16, 6 | 10: 0x16 7 | }, 8 | readHandler: "81", 9 | writeHandler: "actor", 10 | actorid: 0x0088, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = Bg_Mori_Kaitenkabe; -------------------------------------------------------------------------------- /plugins/modules/actors/Bg_Mori_Kaitenkabe_3.opm: -------------------------------------------------------------------------------- 1 | //Forest Temple rotating walls from room before boss 2 | let Bg_Mori_Kaitenkabe = { 3 | actor: "Bg_Mori_Kaitenkabe", 4 | version_offsets: { 5 | debug: 0x32, 6 | 10: 0x32 7 | }, 8 | readHandler: "81", 9 | writeHandler: "actor", 10 | actorid: 0x0088, 11 | actorCategory: 1, 12 | template: "Conditional", 13 | conditional: function (packet) { 14 | return true; 15 | } 16 | } 17 | 18 | module.exports = Bg_Mori_Kaitenkabe; -------------------------------------------------------------------------------- /plugins/modules/actors/door_of_time_collision.opm: -------------------------------------------------------------------------------- 1 | // Door of Time Collision 2 | let door_of_time_collision = { 3 | actor: "door_of_time_collision", 4 | version_offsets: { 5 | debug: 0x13C, 6 | 10: 0x13C 7 | }, 8 | readHandler: "80", 9 | writeHandler: "actor_80", 10 | actorid: 0x0070, 11 | actorCategory: 1, 12 | template: "ConditionalKill", 13 | conditional: function (packet) { 14 | return packet.data.value === 0xFF; 15 | } 16 | } 17 | 18 | module.exports = door_of_time_collision; -------------------------------------------------------------------------------- /OotRandoCoop.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/localization/event_flag_packets.txt: -------------------------------------------------------------------------------- 1 | event_flag_0 2 | event_flag_1 3 | event_flag_2 4 | event_flag_3 5 | event_flag_4 6 | event_flag_5 7 | event_flag_6 8 | event_flag_7 9 | event_flag_8 10 | event_flag_9 11 | event_flag_10 12 | event_flag_11 13 | event_flag_12 14 | event_flag_13 15 | event_flag_14 16 | event_flag_15 17 | event_flag_16 18 | event_flag_17 19 | event_flag_18 20 | event_flag_19 21 | event_flag_20 22 | event_flag_21 23 | event_flag_22 24 | event_flag_23 25 | event_flag_24 26 | event_flag_25 27 | event_flag_26 28 | event_flag_27 29 | event_flag_28 -------------------------------------------------------------------------------- /Oot-Rando-Coop.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plugins/modules/actors/barinade.opm: -------------------------------------------------------------------------------- 1 | // Boss Barinade 2 | let Barinade = { 3 | actor: "Barinade", 4 | version_offsets: { 5 | debug: 0x180, 6 | 10: 0x180 7 | }, 8 | readHandler: "actor_behavior", 9 | actorid: 0x00BA, 10 | actorCategory: 9, 11 | template: "Boss", 12 | filter: { 13 | offset: 0x1C, 14 | data: 0xFF 15 | }, 16 | exit: 0x010E, 17 | cutscene: 0xFFF0, 18 | conditional: function (packet) { 19 | return packet.data.value === 0x4160; 20 | } 21 | } 22 | 23 | module.exports = Barinade; -------------------------------------------------------------------------------- /plugins/localization/item_packets.txt: -------------------------------------------------------------------------------- 1 | inventory_slot_13 2 | inventory_slot_24 3 | inventory_slot_22 4 | inventory_slot_4 5 | inventory_slot_12 6 | inventory_slot_7 7 | inventory_slot_9 8 | inventory_slot_19 9 | inventory_slot_18 10 | inventory_slot_20 11 | inventory_slot_21 12 | inventory_slot_3 13 | inventory_slot_0 14 | inventory_slot_14 15 | inventory_slot_8 16 | inventory_slot_11 17 | inventory_slot_23 18 | inventory_slot_5 19 | inventory_slot_16 20 | inventory_slot_6 21 | inventory_slot_2 22 | inventory_slot_1 23 | inventory_slot_10 24 | inventory_slot_17 25 | inventory_slot_15 -------------------------------------------------------------------------------- /plugins/modules/actors/king_d.opm: -------------------------------------------------------------------------------- 1 | // King Dodongo 2 | let King_D = { 3 | actor: "King_D", 4 | version_offsets: { 5 | debug: 0x4, 6 | 10: 0x4 7 | }, 8 | readHandler: "fourBytes", 9 | actorid: 0x0012, 10 | actorCategory: 9, 11 | template: "Boss", 12 | filter: { 13 | offset: 0x1C, 14 | data: 0xFF 15 | }, 16 | exit: 0x013D, 17 | cutscene: 0xFFF1, 18 | conditional: function (packet) { 19 | console.log(packet) 20 | return packet.data.value === 0x00000070; 21 | } 22 | } 23 | 24 | module.exports = King_D; -------------------------------------------------------------------------------- /plugins/modules/actors/locked_doors_sliding.opm: -------------------------------------------------------------------------------- 1 | // Sliding Doors 2 | let sliding_doors = { 3 | actor: "sliding_doors", 4 | version_offsets: { 5 | debug: 0x15E, 6 | 10: 0x15E 7 | }, 8 | readHandler: "81", 9 | writeHandler: "actor", 10 | actorid: 0x002E, 11 | actorCategory: 10, 12 | value: 0, 13 | template: "Conditional", 14 | overrideSafety: true, 15 | conditional: function (packet) { 16 | console.log(JSON.stringify(packet)); 17 | return packet.data.value === 0; 18 | } 19 | } 20 | 21 | module.exports = sliding_doors; -------------------------------------------------------------------------------- /plugins/modules/actors/bongo_bongo.opm: -------------------------------------------------------------------------------- 1 | // Bongo Bongo 2 | let Bongo_Bongo = { 3 | actor: "Bongo_Bongo", 4 | version_offsets: { 5 | debug: 0xAF, 6 | 10: 0xAF 7 | }, 8 | readHandler: "80", 9 | actorid: 0x00E9, 10 | actorCategory: 9, 11 | template: "Boss", 12 | filter: { 13 | offset: 0x1C, 14 | data: 0xFF 15 | }, 16 | exit: 0x0580, 17 | cutscene: 0x0000, 18 | conditional: function (packet) { 19 | return packet.data.value === 0x0 || packet.data.value >= 100; 20 | } 21 | } 22 | 23 | module.exports = Bongo_Bongo; -------------------------------------------------------------------------------- /plugins/modules/actors/twinrova.opm: -------------------------------------------------------------------------------- 1 | // Twinrova 2 | let Twinrova = { 3 | actor: "Twinrova", 4 | version_offsets: { 5 | debug: 0x13C, 6 | 10: 0x13C 7 | }, 8 | readHandler: "actor_behavior", 9 | actorid: 0x00DC, 10 | actorCategory: 9, 11 | template: "Boss", 12 | filter: { 13 | offset: 0x1C, 14 | data: 0x0002, 15 | extended: true 16 | }, 17 | exit: 0x0610, 18 | cutscene: 0x0000, 19 | conditional: function (packet) { 20 | return packet.data.value === 0x6D64; 21 | } 22 | } 23 | 24 | module.exports = Twinrova; -------------------------------------------------------------------------------- /plugins/localization/skulltula_packets.txt: -------------------------------------------------------------------------------- 1 | skulltula_flag_0 2 | skulltula_flag_1 3 | skulltula_flag_2 4 | skulltula_flag_3 5 | skulltula_flag_4 6 | skulltula_flag_5 7 | skulltula_flag_6 8 | skulltula_flag_7 9 | skulltula_flag_8 10 | skulltula_flag_9 11 | skulltula_flag_10 12 | skulltula_flag_11 13 | skulltula_flag_12 14 | skulltula_flag_13 15 | skulltula_flag_14 16 | skulltula_flag_15 17 | skulltula_flag_16 18 | skulltula_flag_17 19 | skulltula_flag_18 20 | skulltula_flag_19 21 | skulltula_flag_20 22 | skulltula_flag_21 23 | skulltula_flag_22 24 | skulltula_flag_23 25 | skulltula_flag_24 26 | skulltula_count -------------------------------------------------------------------------------- /src/command_inject/bin2gsc.lua: -------------------------------------------------------------------------------- 1 | local arg = {...} 2 | if #arg < 3 then 3 | print("usage: gru bin2gsc.lua
") 4 | return 5 | end 6 | 7 | local bin = gru.blob_load(arg[1]) 8 | local gsc = gru.gsc_create() 9 | 10 | local n = 0 11 | local p = 0 12 | local addr = tonumber(arg[2]) & 0x00FFFFFF 13 | while p < bin:size() do 14 | if p < bin:size() - 1 then 15 | gsc:insert(n, addr | 0x81000000, bin:read16be(p)) 16 | else 17 | gsc:insert(n, addr | 0x80000000, bin:read8(p)) 18 | end 19 | n = n + 1 20 | p = p + 2 21 | addr = addr + 2 22 | end 23 | 24 | gsc:save(arg[3]) 25 | -------------------------------------------------------------------------------- /plugins/localization/equipment_numbers.json: -------------------------------------------------------------------------------- 1 | { 2 | "0": { 3 | "0": "equipment_unknown", 4 | "1": "equipment_unknown", 5 | "2": "equipment_unknown", 6 | "3": "equipment_unknown", 7 | "4": "equipment_unknown", 8 | "5": "equipment_unknown", 9 | "6": "equipment_unknown", 10 | "7": "equipment_unknown" 11 | }, 12 | "1": { 13 | "0": "equipment_unknown", 14 | "1": "equipment_unknown", 15 | "2": "equipment_unknown", 16 | "3": "equipment_unknown", 17 | "4": "equipment_unknown", 18 | "5": "equipment_unknown", 19 | "6": "equipment_unknown", 20 | "7": "equipment_unknown" 21 | } 22 | } -------------------------------------------------------------------------------- /plugins/versions/10/tokens.json: -------------------------------------------------------------------------------- 1 | { 2 | "tokens": { 3 | "@link_instance@": "0x1DAA30", 4 | "@link_state@": "0x066C", 5 | "@save_data@": "0x11A5D0", 6 | "@scene@": "0x1C8544", 7 | "@room@": "0x1DA15C", 8 | "@switch_flags@": "0x1CA1C8", 9 | "@chest_flags@": "0x1CA1D8", 10 | "@room_clear@": "0x1CA1DC", 11 | "@link_loading@": "0x1DB09F", 12 | "@last_entrance@": "0x1DA2BA", 13 | "@link_door@": "0x1DA18D", 14 | "@isPaused@": "0x1C6FA0", 15 | "@dlist_start@": "0x5F0000", 16 | "@dlist_end@": "0x5F0004", 17 | "@collectable_flags@": "0x1CA1E4", 18 | "@overlay_table@": "0x0E8530", 19 | "@frame_counter@": "0x1C853C", 20 | "@continue_state@": "0x1C8538" 21 | } 22 | } -------------------------------------------------------------------------------- /src/command_inject/actor_main_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .section .text 5 | 6 | .ent actor_main_func 7 | .type actor_main_func, @function 8 | actor_main_func: 9 | 10 | /* set up stack frame */ 11 | addiu $sp, $sp, -0x0018 12 | sw $ra, 0x0010($sp) 13 | 14 | /* set notification context */ 15 | la $t0, notif_ctxt 16 | sw $a0, 0x0000($t0) 17 | 18 | /* call actor update function, forward arguments */ 19 | jalr $t9 20 | 21 | /* restore notification context */ 22 | la $t0, notif_ctxt 23 | sw $zero, 0x0000($t0) 24 | 25 | /* return */ 26 | lw $ra, 0x0010($sp) 27 | addiu $sp, $sp, 0x0018 28 | jr $ra 29 | 30 | .end actor_main_func 31 | -------------------------------------------------------------------------------- /src/command_inject/actor_ctor_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .section .text 5 | 6 | .ent actor_ctor_func 7 | .type actor_ctor_func, @function 8 | actor_ctor_func: 9 | 10 | /* set up stack frame */ 11 | addiu $sp, $sp, -0x0018 12 | sw $ra, 0x0010($sp) 13 | 14 | /* save and update notification context */ 15 | la $t0, notif_ctxt 16 | lw $t1, 0x0000($t0) 17 | sw $a0, 0x0000($t0) 18 | sw $t1, 0x0014($sp) 19 | /* forward function call */ 20 | jalr $t9 21 | /* restore notification context */ 22 | la $t0, notif_ctxt 23 | lw $t1, 0x0014($sp) 24 | sw $t1, 0x0000($t0) 25 | 26 | /* return */ 27 | lw $ra, 0x0010($sp) 28 | addiu $sp, $sp, 0x0018 29 | jr $ra 30 | 31 | .end actor_ctor_func 32 | -------------------------------------------------------------------------------- /src/command_inject/actor_dtor_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .section .text 5 | 6 | .ent actor_dtor_func 7 | .type actor_dtor_func, @function 8 | actor_dtor_func: 9 | 10 | /* set up stack frame */ 11 | addiu $sp, $sp, -0x0018 12 | sw $ra, 0x0010($sp) 13 | 14 | /* save and update notification context */ 15 | la $t0, notif_ctxt 16 | lw $t1, 0x0000($t0) 17 | sw $a0, 0x0000($t0) 18 | sw $t1, 0x0014($sp) 19 | /* forward function call */ 20 | jalr $v0 21 | /* restore notification context */ 22 | la $t0, notif_ctxt 23 | lw $t1, 0x0014($sp) 24 | sw $t1, 0x0000($t0) 25 | 26 | /* return */ 27 | lw $ra, 0x0010($sp) 28 | addiu $sp, $sp, 0x0018 29 | jr $ra 30 | 31 | .end actor_dtor_func 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oot-rando-coop", 3 | "version": "2.0.0", 4 | "main": "./src/index.html", 5 | "private": true, 6 | "scripts": { 7 | "start": "node ./src/OotModLoader.js" 8 | }, 9 | "bin": "./src/app.js", 10 | "dependencies": { 11 | "aes256": "^1.0.4", 12 | "chalk": "^2.4.1", 13 | "cross-spawn": "^6.0.5", 14 | "download-file": "^0.1.5", 15 | "express": "^4.16.3", 16 | "hex-rgb": "^3.0.0", 17 | "human-readable-ids": "^1.0.4", 18 | "json-socket": "^0.3.0", 19 | "jsonpack": "^1.1.5", 20 | "nat-upnp": "^1.1.1", 21 | "ncp": "^2.0.0", 22 | "plugin-system": "^0.2.1", 23 | "restify": "^7.2.1", 24 | "serve-static-restify": "^2.1.0", 25 | "socket.io": "^2.1.1", 26 | "socket.io-client": "^2.1.1", 27 | "unzip": "^0.1.11" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/for_emulator/Lua/test/Behavior.lua: -------------------------------------------------------------------------------- 1 | require('OotUtils'); 2 | memory.usememorydomain("RDRAM"); 3 | 4 | local actor_instance = 0x1EC9F0; 5 | local actor_offset = 0x180; 6 | local sub_start = 0x0; 7 | local actor_id = 0x0; 8 | 9 | local overlay_table = 0x0E8530; 10 | 11 | function getOverlayEntry(actorid) 12 | return overlay_table + (actorid * 32); 13 | end 14 | 15 | function getBehaviorStart(overlay) 16 | return overlay + 0x10; 17 | end 18 | 19 | function findSubroutineOffset(start, pointer) 20 | return start - pointer; 21 | end 22 | 23 | actor_id = readTwoByteUnsigned(actor_instance); 24 | local o = getOverlayEntry(actor_id); 25 | local bs = getBehaviorStart(o); 26 | local realPointer = readPointer(bs); 27 | sub_start = readPointer(actor_instance + actor_offset); 28 | local sub = findSubroutineOffset(sub_start, realPointer); 29 | 30 | console.log(DEC_HEX(sub)); -------------------------------------------------------------------------------- /src/command_inject/z64defs.inc: -------------------------------------------------------------------------------- 1 | .set z64_SpawnActor, 0x80025110 2 | .set z64_SpawnActorIndirect, 0x800255C4 3 | .set z64_UpdateButtonIcon, 0x8006FB50 4 | .set z64_PlaySound, 0x800C806C 5 | 6 | .set z64_state_ovl_tab, 0x800F1340 7 | .set z64_object_table, 0x800F8FF8 8 | .set z64_scene_table, 0x800FB4E0 9 | .set z64_file, 0x8011A5D0 10 | .set z64_afx, 0x80125630 11 | .set z64_afx_cmd_write_pos, (z64_afx + 0x00005BD8) 12 | .set z64_afx_cmd_buf, (z64_afx + 0x00005C50) 13 | .set z64_ctxt, 0x801C84A0 14 | .set z64_scene_index, (z64_ctxt + 0x000000A4) 15 | .set z64_scene_ptr, (z64_ctxt + 0x000000B0) 16 | .set z64_obj_ctxt, (z64_ctxt + 0x000117A4) 17 | .set z64_room_ctxt, (z64_ctxt + 0x00011CBC) 18 | .set z64_room_list, (z64_ctxt + 0x00011DF0) 19 | -------------------------------------------------------------------------------- /src/OotColors.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const hexRgb = require('hex-rgb'); 20 | 21 | class OotColor { 22 | constructor() { } 23 | 24 | toRBG(hex) { 25 | return hexRgb(hex); 26 | } 27 | } 28 | 29 | module.exports = new OotColor(); -------------------------------------------------------------------------------- /plugins/localization/inf_flag_packets.txt: -------------------------------------------------------------------------------- 1 | inf_table_0 2 | inf_table_1 3 | inf_table_2 4 | inf_table_3 5 | inf_table_4 6 | inf_table_5 7 | inf_table_6 8 | inf_table_7 9 | inf_table_8 10 | inf_table_9 11 | inf_table_10 12 | inf_table_11 13 | inf_table_12 14 | inf_table_13 15 | inf_table_14 16 | inf_table_15 17 | inf_table_16 18 | inf_table_17 19 | inf_table_18 20 | inf_table_19 21 | inf_table_20 22 | inf_table_21 23 | inf_table_22 24 | inf_table_23 25 | inf_table_24 26 | inf_table_25 27 | inf_table_26 28 | inf_table_27 29 | inf_table_28 30 | inf_table_29 31 | inf_table_30 32 | inf_table_31 33 | inf_table_32 34 | inf_table_33 35 | inf_table_34 36 | inf_table_35 37 | inf_table_36 38 | inf_table_37 39 | inf_table_38 40 | inf_table_39 41 | inf_table_40 42 | inf_table_41 43 | inf_table_42 44 | inf_table_43 45 | inf_table_44 46 | inf_table_45 47 | inf_table_46 48 | inf_table_47 49 | inf_table_48 50 | inf_table_49 51 | inf_table_50 52 | inf_table_51 53 | inf_table_52 54 | inf_table_53 55 | inf_table_54 56 | inf_table_55 57 | inf_table_56 58 | inf_table_57 59 | inf_table_58 60 | inf_table_59 61 | inf_table_60 -------------------------------------------------------------------------------- /plugins/packets/scene_flags.json: -------------------------------------------------------------------------------- 1 | { 2 | "packet_id": "scene_flags", 3 | "readHandler": "bundle", 4 | "bundles": [ 5 | { 6 | "key": "room_clear", 7 | "addr": "@room_clear@", 8 | "offset": "0x0", 9 | "readHandler": "range", 10 | "size": "0x4" 11 | }, 12 | { 13 | "key": "switch_flags", 14 | "addr": "@switch_flags@", 15 | "offset": "0x0", 16 | "readHandler": "range", 17 | "size": "0x8" 18 | }, 19 | { 20 | "key": "chest_flags", 21 | "addr": "@chest_flags@", 22 | "offset": "0x0", 23 | "readHandler": "range", 24 | "size": "0x4" 25 | }, 26 | { 27 | "key": "collectable_flags", 28 | "addr": "@collectable_flags@", 29 | "offset": "0x0", 30 | "readHandler": "range", 31 | "size": "0x8" 32 | }, 33 | { 34 | "key": "scene", 35 | "addr": "@scene@", 36 | "offset": "0x0", 37 | "readHandler": "81" 38 | }, 39 | { 40 | "key": "room", 41 | "addr": "@room@", 42 | "offset": "0x0", 43 | "readHandler": "80" 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /OotModLoader.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2041 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "OotModLoader", "OotModLoader.njsproj", "{E13AD930-71BA-4F06-9D9F-482612EEC044}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {E13AD930-71BA-4F06-9D9F-482612EEC044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {E13AD930-71BA-4F06-9D9F-482612EEC044}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {E13AD930-71BA-4F06-9D9F-482612EEC044}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {E13AD930-71BA-4F06-9D9F-482612EEC044}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {823635A6-E55A-4956-9FCD-A7FE8D9FEA58} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /plugins/modules/actors/adult_zelda.opm: -------------------------------------------------------------------------------- 1 | // Zelda 2 | 3 | class Zelda { 4 | constructor() { 5 | this.actor = this.constructor.name; 6 | this.version_offsets = { 7 | debug: 0x130, 8 | 10: 0x130 9 | }; 10 | this.actorCategory = 4; 11 | this.actorid = 0x0179; 12 | this.offset = null; 13 | } 14 | 15 | init(scene_api, api) { 16 | this.offset = this.version_offsets[api.GAME_VERSION]; 17 | scene_api.computeActor(this.actor + "|" + this.offset, this.actorid, scene_api.actorCategories[this.actorCategory], this.offset, "fourBytes"); 18 | (function (inst) { 19 | api.registerClientSidePacketHook(inst.actor + "|" + inst.offset, function (packet) { 20 | if (scene_api._parent._forbidSync) { 21 | return false; 22 | } 23 | packet.addr = packet.data.hash; 24 | packet.offset = inst.offset; 25 | packet.data = packet.data.value; 26 | packet.writeHandler = "actor_word"; 27 | if (packet.data === 0x0) { 28 | api.postEvent({id: "ZeldaDespawned", uuid: packet.addr}); 29 | } 30 | return false; 31 | }); 32 | })(this); 33 | } 34 | } 35 | 36 | module.exports = new Zelda(); -------------------------------------------------------------------------------- /src/OotVersion.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const logger = require('./OotLogger')("Core"); 20 | 21 | class Version { 22 | constructor() { 23 | this._VERSION = "@major@.@minor@.@buildNumber@.@release_type@"; 24 | logger.logQuietly("Oot Mod Loader", "green"); 25 | logger.logQuietly("v" + this._VERSION + " loading...", "green"); 26 | logger.logQuietly("Coded by: denoflions, MelonSpeedruns, Ideka, and glank", "green"); 27 | logger.logQuietly("Testers: Psi-Hate.", "green"); 28 | } 29 | 30 | get VERSION() { 31 | return this._VERSION; 32 | } 33 | } 34 | 35 | module.exports = new Version().VERSION; -------------------------------------------------------------------------------- /plugins/modules/templates/Behavior.opm: -------------------------------------------------------------------------------- 1 | class Behavior { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | } else { 10 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 11 | } 12 | 13 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 14 | if (parent._forbidSync) { 15 | return false; 16 | } 17 | packet.addr = packet.data.hash; 18 | packet.offset = data.offset; 19 | if (data.hasOwnProperty("value")) { 20 | packet.data = data.value; 21 | } else { 22 | packet.data = packet.data.value; 23 | } 24 | packet.writeHandler = data.writeHandler; 25 | console.log(packet); 26 | return true; 27 | }); 28 | 29 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 30 | if (parent._forbidSync) { 31 | return false; 32 | } 33 | return packet; 34 | }); 35 | } 36 | } 37 | 38 | module.exports = new Behavior(); -------------------------------------------------------------------------------- /plugins/modules/templates/Rotatable.opm: -------------------------------------------------------------------------------- 1 | class Rotatable { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | } else { 10 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 11 | } 12 | 13 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 14 | if (parent._forbidSync) { 15 | return false; 16 | } 17 | packet.addr = packet.data.hash; 18 | packet.offset = data.offset; 19 | packet.data = packet.data.value; 20 | packet.writeHandler = data.writeHandler; 21 | return true; 22 | }); 23 | 24 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 25 | if (parent._forbidSync) { 26 | return false; 27 | } 28 | let copy = JSON.parse(JSON.stringify(packet)); 29 | copy["payload"]["offset"] = 0x16; 30 | emulator.sendViaSocket(copy.payload); 31 | console.log(JSON.stringify(copy, null, 2)); 32 | return packet; 33 | }); 34 | } 35 | } 36 | 37 | module.exports = new Rotatable(); -------------------------------------------------------------------------------- /src/OotLogger.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const chalk = require('chalk'); 20 | 21 | class OotLogger { 22 | constructor(name) { 23 | this._name = name; 24 | } 25 | 26 | log(str, color = "white") { 27 | if (typeof (str) === "string") { 28 | console.log("[" + this._name + "]: " + chalk[color](str)); 29 | } else { 30 | console.log("[" + this._name + "]: " + chalk[color](JSON.stringify(str))); 31 | } 32 | } 33 | 34 | logQuietly(str, color = "white") { 35 | if (typeof (str) === "string") { 36 | console.log(chalk[color](str)); 37 | } else { 38 | console.log(chalk[color](JSON.stringify(str))); 39 | } 40 | } 41 | } 42 | 43 | module.exports = function (str) { 44 | return new OotLogger(str); 45 | }; -------------------------------------------------------------------------------- /plugins/modules/templates/Pushable.opm: -------------------------------------------------------------------------------- 1 | class Pushable { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | } else { 10 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 11 | } 12 | 13 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 14 | if (parent._forbidSync) { 15 | return false; 16 | } 17 | packet.addr = packet.data.hash; 18 | packet.offset = data.offset; 19 | packet.data = packet.data.value; 20 | packet.writeHandler = data.writeHandler; 21 | console.log(packet); 22 | return true; 23 | }); 24 | 25 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 26 | if (parent._forbidSync) { 27 | return false; 28 | } 29 | if (!data.hasOwnProperty("posOnly")){ 30 | let copy = JSON.parse(JSON.stringify(packet)); 31 | copy["payload"]["offset"] = 0x08; 32 | emulator.sendViaSocket(copy.payload); 33 | console.log(JSON.stringify(copy, null, 2)); 34 | } 35 | return packet; 36 | }); 37 | } 38 | } 39 | 40 | module.exports = new Pushable(); -------------------------------------------------------------------------------- /plugins/modules/templates/ConditionalKill.opm: -------------------------------------------------------------------------------- 1 | class ConditionalKill { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | } else { 10 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 11 | } 12 | 13 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 14 | if (parent._forbidSync) { 15 | if (data.hasOwnProperty("overrideSafety")){ 16 | }else{ 17 | return false; 18 | } 19 | } 20 | if (!data.conditional(packet)) { 21 | return false; 22 | } 23 | packet.addr = packet.data.hash; 24 | packet.offset = 0x130; 25 | packet.data = 0x00000000; 26 | packet.writeHandler = "actor_word"; 27 | console.log(packet); 28 | return true; 29 | }); 30 | 31 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 32 | if (parent._forbidSync) { 33 | if (data.hasOwnProperty("overrideSafety")){ 34 | }else{ 35 | return false; 36 | } 37 | } 38 | let copy = JSON.parse(JSON.stringify(packet)); 39 | copy["payload"]["offset"] = 0x134; 40 | emulator.sendViaSocket(copy.payload); 41 | return packet; 42 | }); 43 | } 44 | } 45 | 46 | module.exports = new ConditionalKill(); -------------------------------------------------------------------------------- /src/command_inject/room_actor_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .section .text 5 | 6 | .ent room_actor_func 7 | .type room_actor_func, @function 8 | room_actor_func: 9 | 10 | /* set up stack frame */ 11 | addiu $sp, $sp, -0x0018 12 | sw $ra, 0x0010($sp) 13 | sw $a1, 0x001C($sp) 14 | 15 | /* disable regular actor spawn notifications */ 16 | la $t0, notif_ctxt 17 | la $t1, NOTIF_CTXT_NONOTIF 18 | sw $t1, 0x0000($t0) 19 | 20 | /* forward arguments to z64_SpawnActorIndirect */ 21 | jal z64_SpawnActorIndirect 22 | /* notify even on failure i guess, don't bother checking */ 23 | 24 | /* enable regular actor spawn notifications */ 25 | la $t0, notif_ctxt 26 | sw $zero, 0x0000($t0) 27 | 28 | /* look up vrom address of room actor table entry */ 29 | la $t0, z64_room_ctxt 30 | la $t1, z64_room_list 31 | lb $t2, 0x0000($t0) 32 | lw $t1, 0x0000($t1) 33 | sll $t2, $t2, 0x0003 /* multiply by 0x0008 */ 34 | addu $t1, $t1, $t2 35 | lw $t1, 0x0000($t1) 36 | lw $t2, 0x000C($t0) 37 | lw $a1, 0x001C($sp) 38 | subu $t7, $a1, $t2 39 | addu $t7, $t7, $t1 40 | 41 | /* compute notification address */ 42 | la $t0, notif_pos 43 | la $t1, notif_buf 44 | lbu $t2, 0x0000($t0) 45 | sll $t3, $t2, 0x0004 /* multiply by 0x0010 */ 46 | addu $t1, $t1, $t3 47 | 48 | /* increment notification pos */ 49 | addiu $t2, $t2, 0x0001 50 | sb $t2, 0x0000($t0) 51 | 52 | /* set notification */ 53 | la $t0, NOTIF_ROOM_ACTOR 54 | lh $t2, 0x0000($a1) 55 | lh $t3, 0x000E($a1) 56 | sw $v0, 0x0004($t1) 57 | sw $t7, 0x0008($t1) 58 | sh $t2, 0x000C($t1) 59 | sh $t3, 0x000E($t1) 60 | sw $t0, 0x0000($t1) 61 | 62 | /* return */ 63 | lw $ra, 0x0010($sp) 64 | addiu $sp, $sp, 0x0018 65 | jr $ra 66 | 67 | .end room_actor_func 68 | -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery-ui 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | Copyright and related rights for sample code are waived via CC0. Sample 34 | code is defined as all source code contained within the demos directory. 35 | 36 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 37 | 38 | ==== 39 | 40 | All files located in the node_modules and external directories are 41 | externally maintained libraries used by this software which have their 42 | own licenses; we recommend you read them, as their terms may differ from 43 | the terms above. 44 | -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery-ui 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | Copyright and related rights for sample code are waived via CC0. Sample 34 | code is defined as all source code contained within the demos directory. 35 | 36 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 37 | 38 | ==== 39 | 40 | All files located in the node_modules and external directories are 41 | externally maintained libraries used by this software which have their 42 | own licenses; we recommend you read them, as their terms may differ from 43 | the terms above. 44 | -------------------------------------------------------------------------------- /src/command_inject/spawn_actor_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .section .text 5 | 6 | .ent spawn_actor_func 7 | .type spawn_actor_func, @function 8 | spawn_actor_func: 9 | 10 | /* set up stack frame */ 11 | addiu $sp, $sp, -0x0030 12 | sw $t9, 0x0028($sp) 13 | move $t9, $ra 14 | sw $a2, 0x0038($sp) 15 | 16 | /* forward arguments to z64_SpawnActor */ 17 | lw $t0, 0x0040($sp) 18 | lw $t1, 0x0044($sp) 19 | lw $t2, 0x0048($sp) 20 | lw $t3, 0x004C($sp) 21 | lw $t4, 0x0050($sp) 22 | lw $t5, 0x0054($sp) 23 | sw $t0, 0x0010($sp) 24 | sw $t1, 0x0014($sp) 25 | sw $t2, 0x0018($sp) 26 | sw $t3, 0x001C($sp) 27 | sw $t4, 0x0020($sp) 28 | sw $t5, 0x0024($sp) 29 | /* continue hooked function */ 30 | addiu $sp, $sp, -0x0058 /* } */ 31 | sw $a2, 0x0060($sp) /* } */ 32 | sll $a2, $a2, 0x10 /* } copy of overwritten function prologue */ 33 | jalr $t9 34 | 35 | /* check if notifications are enabled */ 36 | la $t0, notif_ctxt 37 | lw $t0, 0x0000($t0) 38 | la $t1, NOTIF_CTXT_NONOTIF 39 | beq $t0, $t1, no_notif 40 | 41 | /* compute notification address */ 42 | la $t0, notif_pos 43 | la $t1, notif_buf 44 | lbu $t2, 0x0000($t0) 45 | sll $t3, $t2, 0x0004 /* multiply by 0x0010 */ 46 | addu $t1, $t1, $t3 47 | 48 | /* increment notification pos */ 49 | addiu $t2, $t2, 0x0001 50 | sb $t2, 0x0000($t0) 51 | 52 | /* set notification */ 53 | la $t0, NOTIF_SPAWN_ACTOR 54 | la $t2, notif_ctxt 55 | lw $t2, 0x0000($t2) 56 | lw $t3, 0x0038($sp) 57 | lw $t4, 0x0054($sp) 58 | sw $v0, 0x0004($t1) 59 | sw $t2, 0x0008($t1) 60 | sh $t3, 0x000C($t1) 61 | sh $t4, 0x000E($t1) 62 | sw $t0, 0x0000($t1) 63 | 64 | no_notif: 65 | 66 | /* return */ 67 | lw $ra, 0x0028($sp) 68 | addiu $sp, $sp, 0x0030 69 | jr $ra 70 | 71 | .end spawn_actor_func 72 | -------------------------------------------------------------------------------- /plugins/modules/templates/Conditional.opm: -------------------------------------------------------------------------------- 1 | class Conditional { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | } else { 10 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 11 | } 12 | 13 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 14 | console.log(packet); 15 | if (parent._forbidSync) { 16 | if (data.hasOwnProperty("overrideSafety")){ 17 | }else{ 18 | return false; 19 | } 20 | } 21 | if (!data.conditional(packet)) { 22 | return false; 23 | } 24 | packet.addr = packet.data.hash; 25 | if (data.hasOwnProperty("write_offset")) { 26 | packet.offset = data.write_offset; 27 | } else { 28 | packet.offset = data.offset; 29 | } 30 | if (data.hasOwnProperty("value")) { 31 | packet.data = data.value; 32 | } else { 33 | packet.data = packet.data.value; 34 | } 35 | packet.writeHandler = data.writeHandler; 36 | return true; 37 | }); 38 | 39 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 40 | if (parent._forbidSync) { 41 | if (data.hasOwnProperty("overrideSafety")){ 42 | }else{ 43 | return false; 44 | } 45 | } 46 | console.log(packet); 47 | return packet; 48 | }); 49 | } 50 | } 51 | 52 | module.exports = new Conditional(); -------------------------------------------------------------------------------- /dev_portal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OotModLoader Dev Builds 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 33 | 48 | 49 | 50 | 51 |
52 | 55 |
56 | 57 |
58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /src/OotLocalizer.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const fs = require("fs"); 20 | const logger = require('./OotLogger')("Localization"); 21 | 22 | class OotLocalizer{ 23 | 24 | constructor(file){ 25 | logger.log("Loading file: " + file + "."); 26 | this._data = JSON.parse(fs.readFileSync(process.cwd() + '/plugins/localization/' + file + ".json")); 27 | } 28 | 29 | getLocalizedString(key){ 30 | return this._data[key]; 31 | } 32 | 33 | } 34 | 35 | class OotIconizer{ 36 | constructor(file){ 37 | logger.log("Loading file: " + file + "."); 38 | this._data = JSON.parse(fs.readFileSync(process.cwd() + '/plugins/localization/' + file + ".json")); 39 | } 40 | 41 | getIcon(key){ 42 | return this._data[key]; 43 | } 44 | } 45 | 46 | class OotTextReader{ 47 | constructor(file){ 48 | logger.log("Loading file: " + file + "."); 49 | let original = fs.readFileSync(process.cwd() + '/plugins/localization/' + file, "utf8"); 50 | this._data = original.split(/\r?\n/); 51 | } 52 | 53 | getData(){ 54 | return this._data; 55 | } 56 | } 57 | 58 | module.exports = {create: function(file){ 59 | return new OotLocalizer(file); 60 | }, icons: function(file){ 61 | return new OotIconizer(file); 62 | }, text: function(file){ 63 | return new OotTextReader(file); 64 | }}; -------------------------------------------------------------------------------- /GUI/jquery-ui-1.12.1.custom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-ui", 3 | "title": "jQuery UI", 4 | "description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.", 5 | "version": "1.12.1", 6 | "homepage": "http://jqueryui.com", 7 | "author": { 8 | "name": "jQuery Foundation and other contributors", 9 | "url": "https://github.com/jquery/jquery-ui/blob/1.12.1/AUTHORS.txt" 10 | }, 11 | "main": "ui/widget.js", 12 | "maintainers": [ 13 | { 14 | "name": "Scott González", 15 | "email": "scott.gonzalez@gmail.com", 16 | "url": "http://scottgonzalez.com" 17 | }, 18 | { 19 | "name": "Jörn Zaefferer", 20 | "email": "joern.zaefferer@gmail.com", 21 | "url": "http://bassistance.de" 22 | }, 23 | { 24 | "name": "Mike Sherov", 25 | "email": "mike.sherov@gmail.com", 26 | "url": "http://mike.sherov.com" 27 | }, 28 | { 29 | "name": "TJ VanToll", 30 | "email": "tj.vantoll@gmail.com", 31 | "url": "http://tjvantoll.com" 32 | }, 33 | { 34 | "name": "Felix Nagel", 35 | "email": "info@felixnagel.com", 36 | "url": "http://www.felixnagel.com" 37 | }, 38 | { 39 | "name": "Alex Schmitz", 40 | "email": "arschmitz@gmail.com", 41 | "url": "https://github.com/arschmitz" 42 | } 43 | ], 44 | "repository": { 45 | "type": "git", 46 | "url": "git://github.com/jquery/jquery-ui.git" 47 | }, 48 | "bugs": "https://bugs.jqueryui.com/", 49 | "license": "MIT", 50 | "scripts": { 51 | "test": "grunt" 52 | }, 53 | "dependencies": {}, 54 | "devDependencies": { 55 | "commitplease": "2.3.0", 56 | "grunt": "0.4.5", 57 | "grunt-bowercopy": "1.2.4", 58 | "grunt-cli": "0.1.13", 59 | "grunt-compare-size": "0.4.0", 60 | "grunt-contrib-concat": "0.5.1", 61 | "grunt-contrib-csslint": "0.5.0", 62 | "grunt-contrib-jshint": "0.12.0", 63 | "grunt-contrib-qunit": "1.0.1", 64 | "grunt-contrib-requirejs": "0.4.4", 65 | "grunt-contrib-uglify": "0.11.1", 66 | "grunt-git-authors": "3.1.0", 67 | "grunt-html": "6.0.0", 68 | "grunt-jscs": "2.1.0", 69 | "load-grunt-tasks": "3.4.0", 70 | "rimraf": "2.5.1", 71 | "testswarm": "1.1.0" 72 | }, 73 | "keywords": [] 74 | } 75 | -------------------------------------------------------------------------------- /src/GamesharkToInjectConverter.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const fs = require("fs"); 20 | 21 | function toHex(d) { 22 | return "0x" + parseInt(d, 16).toString(16).toUpperCase() 23 | } 24 | 25 | class Gameshark { 26 | constructor() { 27 | } 28 | 29 | read(path) { 30 | let original = fs.readFileSync(path, "utf8"); 31 | 32 | let lines = original.split(/\r?\n/); 33 | let commands = { 34 | params: {}, 35 | codes: [] 36 | }; 37 | for (let i = 0; i < lines.length; i++) { 38 | if (lines[i].substr(0, 2) === "--") { 39 | continue; 40 | } 41 | if (lines[i].substr(0, 1) === "#") { 42 | let params = lines[i].replace("#", "").split(":"); 43 | for (let k = 0; k < params.length; k += 2) { 44 | commands.params[params[k]] = params[k + 1]; 45 | } 46 | continue; 47 | } 48 | let a = lines[i].substr(0, 2); 49 | let b = lines[i].substr(2, lines[i].length); 50 | let c = "0x" + b.split(" ")[0]; 51 | let d = b.split(" ")[1]; 52 | commands.codes.push({ type: a, addr: c, payload: toHex(d) }); 53 | } 54 | return commands; 55 | } 56 | } 57 | 58 | let gs = new Gameshark(); 59 | 60 | module.exports = gs; -------------------------------------------------------------------------------- /dev_portal/jquery-ui-1.12.1.custom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-ui", 3 | "title": "jQuery UI", 4 | "description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.", 5 | "version": "1.12.1", 6 | "homepage": "http://jqueryui.com", 7 | "author": { 8 | "name": "jQuery Foundation and other contributors", 9 | "url": "https://github.com/jquery/jquery-ui/blob/1.12.1/AUTHORS.txt" 10 | }, 11 | "main": "ui/widget.js", 12 | "maintainers": [ 13 | { 14 | "name": "Scott González", 15 | "email": "scott.gonzalez@gmail.com", 16 | "url": "http://scottgonzalez.com" 17 | }, 18 | { 19 | "name": "Jörn Zaefferer", 20 | "email": "joern.zaefferer@gmail.com", 21 | "url": "http://bassistance.de" 22 | }, 23 | { 24 | "name": "Mike Sherov", 25 | "email": "mike.sherov@gmail.com", 26 | "url": "http://mike.sherov.com" 27 | }, 28 | { 29 | "name": "TJ VanToll", 30 | "email": "tj.vantoll@gmail.com", 31 | "url": "http://tjvantoll.com" 32 | }, 33 | { 34 | "name": "Felix Nagel", 35 | "email": "info@felixnagel.com", 36 | "url": "http://www.felixnagel.com" 37 | }, 38 | { 39 | "name": "Alex Schmitz", 40 | "email": "arschmitz@gmail.com", 41 | "url": "https://github.com/arschmitz" 42 | } 43 | ], 44 | "repository": { 45 | "type": "git", 46 | "url": "git://github.com/jquery/jquery-ui.git" 47 | }, 48 | "bugs": "https://bugs.jqueryui.com/", 49 | "license": "MIT", 50 | "scripts": { 51 | "test": "grunt" 52 | }, 53 | "dependencies": {}, 54 | "devDependencies": { 55 | "commitplease": "2.3.0", 56 | "grunt": "0.4.5", 57 | "grunt-bowercopy": "1.2.4", 58 | "grunt-cli": "0.1.13", 59 | "grunt-compare-size": "0.4.0", 60 | "grunt-contrib-concat": "0.5.1", 61 | "grunt-contrib-csslint": "0.5.0", 62 | "grunt-contrib-jshint": "0.12.0", 63 | "grunt-contrib-qunit": "1.0.1", 64 | "grunt-contrib-requirejs": "0.4.4", 65 | "grunt-contrib-uglify": "0.11.1", 66 | "grunt-git-authors": "3.1.0", 67 | "grunt-html": "6.0.0", 68 | "grunt-jscs": "2.1.0", 69 | "load-grunt-tasks": "3.4.0", 70 | "rimraf": "2.5.1", 71 | "testswarm": "1.1.0" 72 | }, 73 | "keywords": [] 74 | } 75 | -------------------------------------------------------------------------------- /src/OotEncoder.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const zlib = require('zlib'); 20 | const VERSION = require('./OotVersion'); 21 | const jpack = require('jsonpack'); 22 | const aes256 = require('aes256'); 23 | const logger = require('./OotLogger')("Encoder"); 24 | let enc_key = aes256.encrypt(VERSION, VERSION); 25 | 26 | class VersionMismatchError extends Error { 27 | constructor(message) { 28 | super(message); 29 | this.name = this.constructor.name; 30 | Error.captureStackTrace(this, this.constructor); 31 | } 32 | } 33 | 34 | class Encoder { 35 | 36 | setEncKey(key){ 37 | enc_key = aes256(VERSION, key) 38 | } 39 | 40 | compressData(data) { 41 | let pack = jpack.pack(data); 42 | let compress = zlib.deflateSync(pack); 43 | let base = Buffer.from(compress).toString('base64'); 44 | return base; 45 | } 46 | 47 | decompressData(data) { 48 | try { 49 | let buffer = Buffer.from(data, 'base64'); 50 | let decompress = zlib.inflateSync(buffer).toString(); 51 | let unpack = jpack.unpack(decompress); 52 | return unpack; 53 | } catch (err) { 54 | if (err) { 55 | logger.log(err.message) 56 | throw new VersionMismatchError(); 57 | } 58 | } 59 | } 60 | 61 | } 62 | 63 | module.exports = new Encoder(); -------------------------------------------------------------------------------- /src/command_inject/tnsn_actor_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .section .text 5 | 6 | .ent tnsn_actor_func 7 | .type tnsn_actor_func, @function 8 | tnsn_actor_func: 9 | 10 | /* set up stack frame */ 11 | addiu $sp, $sp, -0x0030 12 | sw $ra, 0x0028($sp) 13 | sw $a2, 0x0038($sp) 14 | 15 | /* disable regular actor spawn notifications */ 16 | la $t0, notif_ctxt 17 | la $t1, NOTIF_CTXT_NONOTIF 18 | sw $t1, 0x0000($t0) 19 | 20 | /* forward arguments to z64_SpawnActor */ 21 | lw $t0, 0x0040($sp) 22 | lw $t1, 0x0044($sp) 23 | lw $t2, 0x0048($sp) 24 | lw $t3, 0x004C($sp) 25 | lw $t4, 0x0050($sp) 26 | lw $t5, 0x0054($sp) 27 | sw $t0, 0x0010($sp) 28 | sw $t1, 0x0014($sp) 29 | sw $t2, 0x0018($sp) 30 | sw $t3, 0x001C($sp) 31 | sw $t4, 0x0020($sp) 32 | sw $t5, 0x0024($sp) 33 | jal z64_SpawnActor 34 | /* notify even on failure i guess, don't bother checking */ 35 | 36 | /* enable regular actor spawn notifications */ 37 | la $t0, notif_ctxt 38 | sw $zero, 0x0000($t0) 39 | 40 | /* look up vrom address of transition actor table entry */ 41 | la $t0, z64_scene_table 42 | la $t1, z64_scene_index 43 | la $t2, z64_scene_ptr 44 | lhu $t1, 0x0000($t1) 45 | lw $t2, 0x0000($t2) 46 | sll $t3, $t1, 0x0002 /* } */ 47 | addu $t3, $t3, $t1 /* } */ 48 | sll $t3, $t3, 0x0002 /* } multiply by 0x0014 */ 49 | addu $t0, $t0, $t3 50 | lw $t0, 0x0000($t0) 51 | /* the calling function keeps the table entry pointer in $s0 */ 52 | /* bit of a hack relying on this but whatever, it works */ 53 | subu $t7, $s0, $t2 54 | addu $t7, $t7, $t0 55 | 56 | /* compute notification address */ 57 | la $t0, notif_pos 58 | la $t1, notif_buf 59 | lbu $t2, 0x0000($t0) 60 | sll $t3, $t2, 0x0004 /* multiply by 0x0010 */ 61 | addu $t1, $t1, $t3 62 | 63 | /* increment notification pos */ 64 | addiu $t2, $t2, 0x0001 65 | sb $t2, 0x0000($t0) 66 | 67 | /* set notification */ 68 | la $t0, NOTIF_TNSN_ACTOR 69 | lw $t2, 0x0038($sp) 70 | lw $t3, 0x0054($sp) 71 | sw $v0, 0x0004($t1) 72 | sw $t7, 0x0008($t1) 73 | sh $t2, 0x000C($t1) 74 | sh $t3, 0x000E($t1) 75 | sw $t0, 0x0000($t1) 76 | 77 | /* return */ 78 | lw $ra, 0x0028($sp) 79 | addiu $sp, $sp, 0x0030 80 | jr $ra 81 | 82 | .end tnsn_actor_func 83 | -------------------------------------------------------------------------------- /GUI/renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // All of the Node.js APIs are available in this process. 4 | var ipcRenderer = require('electron').ipcRenderer; 5 | 6 | const RENDER_OBJ = {}; 7 | 8 | RENDER_OBJ["console"] = function(msg){ 9 | console.log(msg); 10 | } 11 | 12 | ipcRenderer.on('GUI_ConfigLoaded', function (wtfisthis, event) { 13 | processConfigObject(event.config); 14 | }); 15 | 16 | ipcRenderer.on('onConsoleMessage', function (wtfisthis, event) { 17 | RENDER_OBJ.console(event.msg); 18 | }); 19 | 20 | ipcRenderer.on('onBizHawkInstall', function (wtfisthis, event) { 21 | if (!event.done){ 22 | document.getElementById("connect").textContent = "Installing BizHawk..."; 23 | }else{ 24 | document.getElementById("connect").textContent = "Connect to Server"; 25 | } 26 | }); 27 | 28 | let config_to_element_map = {}; 29 | 30 | function processConfigObject(config){ 31 | console.log(config); 32 | Object.keys(config).forEach(function(key){ 33 | console.log(key); 34 | let ele = document.getElementById(key); 35 | if (ele){ 36 | if (typeof config[key] === "boolean"){ 37 | ele.checked = config[key]; 38 | config_to_element_map[key] = {ele: ele, isBoolean: true}; 39 | }else{ 40 | ele.value = config[key]; 41 | config_to_element_map[key] = {ele: ele, isBoolean: false}; 42 | } 43 | } 44 | if (key === "_tunic_colors"){ 45 | processConfigObject(config[key]); 46 | } 47 | }); 48 | } 49 | 50 | function sendToMainProcess(id, event){ 51 | ipcRenderer.send(id, event); 52 | } 53 | 54 | function configChanged(){ 55 | let cfg = {}; 56 | Object.keys(config_to_element_map).forEach(function(key){ 57 | if (config_to_element_map[key].isBoolean){ 58 | cfg[key] = config_to_element_map[key].ele.checked; 59 | }else{ 60 | cfg[key] = config_to_element_map[key].ele.value; 61 | } 62 | }); 63 | console.log(cfg); 64 | sendToMainProcess("postEvent", {id: "GUI_ConfigChanged", config: cfg}); 65 | } 66 | 67 | function startClient(){ 68 | configChanged(); 69 | document.getElementById("connect").textContent = "Starting client, please wait..."; 70 | setTimeout(function(){ 71 | document.getElementById("connect").textContent = "Client Started."; 72 | }, 10000); 73 | document.getElementById("connect").disabled = true; 74 | sendToMainProcess("postEvent", {id: "GUI_StartButtonPressed", start: true}) 75 | } 76 | 77 | RENDER_OBJ["onConfigChanged"] = configChanged; 78 | RENDER_OBJ["onStartClient"] = startClient; 79 | 80 | module.exports = RENDER_OBJ; -------------------------------------------------------------------------------- /GUI/main.js: -------------------------------------------------------------------------------- 1 | // Modules to control application life and create native browser window 2 | const {app, BrowserWindow, ipcMain} = require('electron') 3 | let ooto; 4 | 5 | // Keep a global reference of the window object, if you don't, the window will 6 | // be closed automatically when the JavaScript object is garbage collected. 7 | let mainWindow 8 | 9 | function createWindow () { 10 | // Create the browser window. 11 | mainWindow = new BrowserWindow({ 12 | width: 800, 13 | height: 600, 14 | webPreferences: { 15 | nodeIntegration: true 16 | }, 17 | icon: "" 18 | }) 19 | 20 | // and load the index.html of the app. 21 | mainWindow.loadFile('index.html') 22 | 23 | // Open the DevTools. 24 | // mainWindow.webContents.openDevTools() 25 | 26 | // Emitted when the window is closed. 27 | mainWindow.on('closed', function () { 28 | // Dereference the window object, usually you would store windows 29 | // in an array if your app supports multi windows, this is the time 30 | // when you should delete the corresponding element. 31 | mainWindow = null 32 | }) 33 | 34 | setTimeout(setupModLoader, 1000); 35 | 36 | } 37 | 38 | function setupModLoader(){ 39 | ooto = require('./OotModLoader') 40 | let event_reg = function(id){ 41 | ooto.api.registerEventHandler(id, function(event){ 42 | console.log(event) 43 | mainWindow.webContents.send(event.id, event); 44 | }); 45 | } 46 | event_reg("onBizHawkInstall"); 47 | ipcMain.on('postEvent', (event, arg) => { 48 | console.log(arg); 49 | ooto.api.postEvent(arg); 50 | }) 51 | mainWindow.webContents.send("GUI_ConfigLoaded", ooto); 52 | setInterval(function(){ 53 | if (ooto.console.length > 0){ 54 | mainWindow.webContents.send("onConsoleMessage", {id: "onConsoleMessage", msg: ooto.console.shift()}) 55 | } 56 | }, 100); 57 | } 58 | 59 | // This method will be called when Electron has finished 60 | // initialization and is ready to create browser windows. 61 | // Some APIs can only be used after this event occurs. 62 | app.on('ready', createWindow) 63 | 64 | // Quit when all windows are closed. 65 | app.on('window-all-closed', function () { 66 | // On macOS it is common for applications and their menu bar 67 | // to stay active until the user quits explicitly with Cmd + Q 68 | if (process.platform !== 'darwin') { 69 | app.quit() 70 | } 71 | }) 72 | 73 | app.on('activate', function () { 74 | // On macOS it's common to re-create a window in the app when the 75 | // dock icon is clicked and there are no other windows open. 76 | if (mainWindow === null) { 77 | createWindow() 78 | } 79 | }) 80 | 81 | // In this file you can include the rest of your app's specific main process 82 | // code. You can also put them in separate files and require them here. 83 | -------------------------------------------------------------------------------- /luasocket/lua/mime.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | -- MIME support for the Lua language. 3 | -- Author: Diego Nehab 4 | -- Conforming to RFCs 2045-2049 5 | -- RCS ID: $Id: mime.lua,v 1.29 2007/06/11 23:44:54 diego Exp $ 6 | ----------------------------------------------------------------------------- 7 | 8 | ----------------------------------------------------------------------------- 9 | -- Declare module and import dependencies 10 | ----------------------------------------------------------------------------- 11 | local base = _G 12 | local ltn12 = require("ltn12") 13 | local mime = require("mime.core") 14 | local io = require("io") 15 | local string = require("string") 16 | module("mime") 17 | 18 | -- encode, decode and wrap algorithm tables 19 | encodet = {} 20 | decodet = {} 21 | wrapt = {} 22 | 23 | -- creates a function that chooses a filter by name from a given table 24 | local function choose(table) 25 | return function(name, opt1, opt2) 26 | if base.type(name) ~= "string" then 27 | name, opt1, opt2 = "default", name, opt1 28 | end 29 | local f = table[name or "nil"] 30 | if not f then 31 | base.error("unknown key (" .. base.tostring(name) .. ")", 3) 32 | else return f(opt1, opt2) end 33 | end 34 | end 35 | 36 | -- define the encoding filters 37 | encodet['base64'] = function() 38 | return ltn12.filter.cycle(b64, "") 39 | end 40 | 41 | encodet['quoted-printable'] = function(mode) 42 | return ltn12.filter.cycle(qp, "", 43 | (mode == "binary") and "=0D=0A" or "\r\n") 44 | end 45 | 46 | -- define the decoding filters 47 | decodet['base64'] = function() 48 | return ltn12.filter.cycle(unb64, "") 49 | end 50 | 51 | decodet['quoted-printable'] = function() 52 | return ltn12.filter.cycle(unqp, "") 53 | end 54 | 55 | local function format(chunk) 56 | if chunk then 57 | if chunk == "" then return "''" 58 | else return string.len(chunk) end 59 | else return "nil" end 60 | end 61 | 62 | -- define the line-wrap filters 63 | wrapt['text'] = function(length) 64 | length = length or 76 65 | return ltn12.filter.cycle(wrp, length, length) 66 | end 67 | wrapt['base64'] = wrapt['text'] 68 | wrapt['default'] = wrapt['text'] 69 | 70 | wrapt['quoted-printable'] = function() 71 | return ltn12.filter.cycle(qpwrp, 76, 76) 72 | end 73 | 74 | -- function that choose the encoding, decoding or wrap algorithm 75 | encode = choose(encodet) 76 | decode = choose(decodet) 77 | wrap = choose(wrapt) 78 | 79 | -- define the end-of-line normalization filter 80 | function normalize(marker) 81 | return ltn12.filter.cycle(eol, 0, marker) 82 | end 83 | 84 | -- high level stuffing filter 85 | function stuff() 86 | return ltn12.filter.cycle(dot, 2) 87 | end 88 | -------------------------------------------------------------------------------- /src/OotTimeEmulation.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 4 | Copyright (C) 2019 Team Ooto 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | const api = require('./OotAPI'); 20 | const logger = require('./OotLogger')("TimeEmulator"); 21 | const encoder = require('./OotEncoder'); 22 | 23 | class OotTimeEmulation { 24 | constructor(room, master_server) { 25 | this._room = room; 26 | this._worldTime = 0x8000; 27 | this._maxTime = 65555; 28 | this._tickRate = 60; 29 | this._counter = {}; 30 | this._sender = {}; 31 | this._checker = {}; 32 | this._addr = 0x15E660; 33 | this._changeRates = { 34 | day: 0xC, 35 | night: 0x12 36 | }; 37 | this._ms = master_server; 38 | (function (inst) { 39 | inst._counter = setInterval(function () { 40 | if (inst._worldTime >= 0x4500 && inst._worldTime <= 0xC000) { 41 | inst._worldTime += inst._changeRates.day; 42 | } else { 43 | inst._worldTime += inst._changeRates.night; 44 | } 45 | if (inst._worldTime > inst._maxTime) { 46 | inst._worldTime = 0; 47 | } 48 | }, inst._tickRate); 49 | 50 | inst._sender = setInterval(function () { 51 | //inst._ms._ws_server.sockets.to(inst._room).emit('msg', { packet_id: "time", nickname: "System", uuid: "-1", payload: encoder.compressData({ packet_id: "time", writeHandler: "81", addr: inst._addr, offset: 0x00C, data: inst._worldTime }) }); 52 | }, 60); 53 | 54 | inst._checker = setInterval(function () { 55 | if (!inst._ms.doesRoomExist(inst._room)) { 56 | clearInterval(inst._checker); 57 | clearInterval(inst._counter); 58 | clearInterval(inst._sender); 59 | //api.unregisterEventHandler("onSceneChange", inst._sender); 60 | } 61 | }, 50); 62 | })(this); 63 | logger.log("Created time emulator for room " + this._room + "."); 64 | } 65 | } 66 | 67 | module.exports = function (room, server) { 68 | return new OotTimeEmulation(room, server); 69 | } -------------------------------------------------------------------------------- /plugins/modules/templates/Pickupable_revised.opm: -------------------------------------------------------------------------------- 1 | class Pickupable_revised { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | } else { 10 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 11 | } 12 | 13 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 14 | if (parent._forbidSync) { 15 | return false; 16 | } 17 | packet.addr = packet.data.hash; 18 | if (data.hasOwnProperty("write_offset")) { 19 | packet.offset = data.write_offset; 20 | } else { 21 | packet.offset = data.offset; 22 | } 23 | if (data.hasOwnProperty("value")) { 24 | packet.data = data.value; 25 | } else { 26 | packet.data = packet.data.value; 27 | } 28 | packet.writeHandler = data.writeHandler; 29 | return true; 30 | }); 31 | 32 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 33 | if (parent._forbidSync) { 34 | return false; 35 | } 36 | if (packet.payload.data > 0) { 37 | let ooto = api.getModule("OotOnline"); 38 | let puppet_pointer = ooto.PuppetMap[ooto._playerToPuppetMap[packet.uuid]].puppet._pointer; 39 | packet.payload.data = puppet_pointer; 40 | let copy = JSON.parse(JSON.stringify(packet)); 41 | copy.payload.addr = puppet_pointer; 42 | copy.payload["isPointer"] = true; 43 | copy.payload.writeHandler = "actor_word_copy_reverse"; 44 | copy.payload.data = packet.payload.addr; 45 | copy.payload.offset = 0x11C; 46 | emulator.sendViaSocket(copy.payload); 47 | console.log(copy); 48 | console.log(packet); 49 | } else { 50 | let ooto = api.getModule("OotOnline"); 51 | let puppet_pointer = ooto.PuppetMap[ooto._playerToPuppetMap[packet.uuid]].puppet._pointer; 52 | packet.payload.data = puppet_pointer; 53 | let copy = JSON.parse(JSON.stringify(packet)); 54 | copy.payload.addr = puppet_pointer; 55 | copy.payload["isPointer"] = true; 56 | copy.payload.writeHandler = "fourBytes"; 57 | copy.payload.data = 0x0000000; 58 | copy.payload.offset = 0x11C; 59 | emulator.sendViaSocket(copy.payload); 60 | console.log(copy); 61 | return null; 62 | } 63 | return packet; 64 | }); 65 | } 66 | } 67 | 68 | module.exports = new Pickupable_revised(); -------------------------------------------------------------------------------- /plugins/modules/templates/Boss.opm: -------------------------------------------------------------------------------- 1 | class Boss { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("overrideActorID")){ 8 | data.actorid = data.overrideActorID; 9 | } 10 | if (data.hasOwnProperty("filter")) { 11 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 12 | } else { 13 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 14 | } 15 | 16 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 17 | if (parent._forbidSync) { 18 | if (data.hasOwnProperty("overrideSafety")){ 19 | }else{ 20 | return false; 21 | } 22 | } 23 | console.log(packet); 24 | if (!data.conditional(packet)) { 25 | return false; 26 | } 27 | packet.addr = packet.data.hash; 28 | if (data.hasOwnProperty("write_offset")) { 29 | packet.offset = data.write_offset; 30 | } else { 31 | packet.offset = data.offset; 32 | } 33 | if (data.hasOwnProperty("value")) { 34 | packet.data = data.value; 35 | } else { 36 | packet.data = packet.data.value; 37 | } 38 | packet.writeHandler = "Null"; 39 | return true; 40 | }); 41 | 42 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 43 | if (parent._forbidSync) { 44 | if (data.hasOwnProperty("overrideSafety")){ 45 | }else{ 46 | return false; 47 | } 48 | } 49 | let bundle = { 50 | packet_id: "gohma_die_dammit", 51 | writeHandler: "bundle", 52 | data: [ 53 | { 54 | packet_id: "gohma_stuff", 55 | writeHandler: "81", 56 | data: data.exit, 57 | addr: 0x600108, 58 | offset: 0x4 59 | }, 60 | { 61 | packet_id: "gohma_stuff", 62 | writeHandler: "81", 63 | data: data.cutscene, 64 | addr: 0x600108, 65 | offset: 0x6 66 | }, 67 | { 68 | packet_id: "gohma_stuff", 69 | writeHandler: "fourBytes", 70 | data: 0x00000005, 71 | addr: 0x600108, 72 | offset: 0x0 73 | }, 74 | ] 75 | }; 76 | console.log(JSON.stringify(bundle, null, 2)); 77 | emulator.sendViaSocket(bundle); 78 | return null; 79 | }); 80 | } 81 | } 82 | 83 | module.exports = new Boss(); -------------------------------------------------------------------------------- /plugins/packets/link_packet.json: -------------------------------------------------------------------------------- 1 | { 2 | "packet_id": "OotOnline", 3 | "readHandler": "bundle", 4 | "protocol": "udp", 5 | "bundles": [ 6 | { 7 | "key": "link_pos", 8 | "addr": "@link_instance@", 9 | "offset": "0x24", 10 | "readHandler": "range", 11 | "size": "0xC" 12 | }, 13 | { 14 | "key": "link_rot", 15 | "addr": "@link_instance@", 16 | "offset": "0xB4", 17 | "readHandler": "range", 18 | "size": "0x8" 19 | }, 20 | { 21 | "key": "link_anim", 22 | "addr": "0x600000", 23 | "offset": "0x0", 24 | "readHandler": "range", 25 | "size": "0x86" 26 | }, 27 | { 28 | "key": "puppet_0x140", 29 | "addr": "@link_instance@", 30 | "offset": "0x150", 31 | "readHandler": "range", 32 | "size": "0xC" 33 | }, 34 | { 35 | "key": "puppet_0x14C", 36 | "addr": "@link_instance@", 37 | "offset": "0x14C", 38 | "readHandler": "range", 39 | "size": "0x3" 40 | }, 41 | { 42 | "key": "link_tunic_color", 43 | "addr": "@link_instance@", 44 | "offset": "0x13C", 45 | "readHandler": "80" 46 | }, 47 | { 48 | "key": "puppet_0x159", 49 | "addr": "@link_instance@", 50 | "offset": "0x1D9", 51 | "readHandler": "80" 52 | }, 53 | { 54 | "key": "puppet_0x15A", 55 | "addr": "@save_data@", 56 | "offset": "0x37", 57 | "readHandler": "80" 58 | }, 59 | { 60 | "key": "puppet_0x160", 61 | "addr": "@link_instance@", 62 | "offset": "0x84C", 63 | "readHandler": "fourBytes" 64 | }, 65 | { 66 | "key": "puppet_0x164", 67 | "addr": "@link_instance@", 68 | "offset": "0x6B4", 69 | "readHandler": "fourBytes" 70 | }, 71 | { 72 | "key": "puppet_0x15B", 73 | "addr": "@link_instance@", 74 | "offset": "0x144", 75 | "readHandler": "80" 76 | }, 77 | { 78 | "key": "puppet_0x16C", 79 | "addr": "@link_instance@", 80 | "offset": "0x68", 81 | "readHandler": "fourBytes" 82 | }, 83 | { 84 | "key": "puppet_0x171", 85 | "addr": "@link_instance@", 86 | "offset": "0x13F", 87 | "readHandler": "80" 88 | }, 89 | { 90 | "key": "puppet_0x172", 91 | "addr": "@link_instance@", 92 | "offset": "0x14F", 93 | "readHandler": "80" 94 | }, 95 | { 96 | "key": "link_gauntlets", 97 | "addr": "@save_data@", 98 | "offset": "0xA3", 99 | "readHandler": "80" 100 | }, 101 | { 102 | "key": "puppet_0x174", 103 | "addr": "@link_instance@", 104 | "offset": "0x13D", 105 | "readHandler": "81" 106 | }, 107 | { 108 | "key": "link_age", 109 | "addr": "@link_instance@", 110 | "offset": "0x0668", 111 | "readHandler": "fourBytes" 112 | }, 113 | { 114 | "key": "link_health", 115 | "addr": "@save_data@", 116 | "offset": "0x0030", 117 | "readHandler": "81" 118 | }, 119 | { 120 | "key": "link_shadow", 121 | "addr": "@link_instance@", 122 | "offset": "0xC0", 123 | "readHandler": "range", 124 | "size": "0x40" 125 | } 126 | ] 127 | } -------------------------------------------------------------------------------- /src/for_emulator/Lua/ActorDataHandler.lua: -------------------------------------------------------------------------------- 1 | --[[/* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */]]-- 18 | 19 | require("OotUtils") 20 | 21 | local context = 0x600000 22 | local offset = 0x1E0 23 | local counter = readByte(context + 0x11E0) 24 | 25 | local ACTOR_DATA_HANDLER = {} 26 | ACTOR_DATA_HANDLER["console"] = {} 27 | ACTOR_DATA_HANDLER.console["log"] = function(msg) end 28 | ACTOR_DATA_HANDLER["send"] = function(data) end 29 | ACTOR_DATA_HANDLER["reset"] = function() counter = 0 end 30 | 31 | ACTOR_DATA_HANDLER["hook"] = function() 32 | local addr = context + offset + (counter * 16) 33 | local package = {} 34 | package["type"] = readFourBytesUnsigned(addr) 35 | if (package.type ~= 0 and package.type ~= 0xFFFFFFFF) then 36 | if (package.type ~= 0 and package.type ~= 1 and package.type ~= 2 and package.type ~= 3) then 37 | writeFourBytesUnsigned(addr, 0xFFFFFFFF) 38 | package.type = readFourBytesUnsigned(addr) 39 | counter = counter + 1 40 | if (counter == 0x100) then counter = 0x0 end 41 | return; 42 | end 43 | if (package.type == 3) then 44 | package["pointer"] = readPointer(addr + 4) 45 | if (package.pointer > 0) then 46 | writeTwoByteUnsigned(addr + 12, readTwoByteUnsigned(package.pointer)) 47 | package["actorID"] = readTwoByteUnsigned(addr + 12) 48 | package["variable"] = readTwoByteUnsigned(addr + 14) 49 | package["uuid"] = package["actorID"] .. "_" .. package["variable"] .. "_" .. readTwoByteUnsigned(0x1C8544) .. "_" .. readByte(0x1DA15C) .. "_" .. hashRange(package["pointer"] + 0x8, 0x12) 50 | ACTOR_DATA_HANDLER.send(package) 51 | writeFourBytesUnsigned(addr, 0x00000000) 52 | else 53 | writeFourBytesUnsigned(addr, 0xFFFFFFFF) 54 | end 55 | else 56 | if (readFourBytesUnsigned(addr + 4) > 0) then 57 | package["pointer"] = readPointer(addr + 4) 58 | package["uuid"] = readFourBytesUnsigned(addr + 8) 59 | writeTwoByteUnsigned(addr + 12, readTwoByteUnsigned(package.pointer)) 60 | package["actorID"] = readTwoByteUnsigned(addr + 12) 61 | if (package.pointer > 0 and package.uuid > 0) then ACTOR_DATA_HANDLER.send(package) end 62 | writeFourBytesUnsigned(addr, 0x00000000) 63 | else 64 | writeFourBytesUnsigned(addr, 0xFFFFFFFF) 65 | end 66 | end 67 | counter = counter + 1 68 | if (counter == 0x100) then counter = 0x0 end 69 | end 70 | end 71 | 72 | return ACTOR_DATA_HANDLER 73 | -------------------------------------------------------------------------------- /plugins/packets/save_data_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "packet_id": "save_data", 3 | "readHandler": "bundle", 4 | "notEveryFrame": true, 5 | "bundles": [ 6 | { 7 | "key": "death_counter", 8 | "addr": "@save_data@", 9 | "offset": "0x0022", 10 | "readHandler": "81" 11 | }, 12 | { 13 | "key": "heart_containers", 14 | "addr": "@save_data@", 15 | "offset": "0x002E", 16 | "readHandler": "81" 17 | }, 18 | { 19 | "key": "biggoron_sword_flag", 20 | "addr": "@save_data@", 21 | "offset": "0x003E", 22 | "readHandler": "80" 23 | }, 24 | { 25 | "key": "inventory", 26 | "addr": "@save_data@", 27 | "offset": "0x0074", 28 | "readHandler": "range", 29 | "size": "0x18" 30 | }, 31 | { 32 | "key": "magic_beans", 33 | "addr": "@save_data@", 34 | "offset": "0x009B", 35 | "readHandler": "80" 36 | }, 37 | { 38 | "key": "equipment", 39 | "addr": "@save_data@", 40 | "offset": "0x009C", 41 | "readHandler": "range", 42 | "size": "0x2" 43 | }, 44 | { 45 | "key": "upgrades", 46 | "addr": "@save_data@", 47 | "offset": "0x00A1", 48 | "readHandler": "range", 49 | "size": "0x3" 50 | }, 51 | { 52 | "key": "quest_items", 53 | "addr": "@save_data@", 54 | "offset": "0x00A5", 55 | "readHandler": "range", 56 | "size": "0x3" 57 | }, 58 | { 59 | "key": "dungeon_items", 60 | "addr": "@save_data@", 61 | "offset": "0x00A8", 62 | "readHandler": "range", 63 | "size": "0x14" 64 | }, 65 | { 66 | "key": "double_defense", 67 | "addr": "@save_data@", 68 | "offset": "0x00CF", 69 | "readHandler": "80" 70 | }, 71 | { 72 | "key": "skulltula_count", 73 | "addr": "@save_data@", 74 | "offset": "0x00D0", 75 | "readHandler": "81" 76 | }, 77 | { 78 | "key": "skulltula_c_flags", 79 | "addr": "@save_data@", 80 | "offset": "0x0E9C", 81 | "readHandler": "range", 82 | "size": "0x18" 83 | }, 84 | { 85 | "key": "scene_data", 86 | "addr": "@save_data@", 87 | "offset": "0x00D4", 88 | "readHandler": "range", 89 | "size": "0x0B0C" 90 | }, 91 | { 92 | "key": "event_flags", 93 | "addr": "@save_data@", 94 | "offset": "0x0ED4", 95 | "readHandler": "range", 96 | "size": "0x1C" 97 | }, 98 | { 99 | "key": "item_flags", 100 | "addr": "@save_data@", 101 | "offset": "0x0EF0", 102 | "readHandler": "range", 103 | "size": "0x8" 104 | }, 105 | { 106 | "key": "inf_table", 107 | "addr": "@save_data@", 108 | "offset": "0x0EF8", 109 | "readHandler": "range", 110 | "size": "0x3C" 111 | }, 112 | { 113 | "key": "poe_score_card", 114 | "addr": "@save_data@", 115 | "offset": "0x0EBE", 116 | "readHandler": "81" 117 | }, 118 | { 119 | "key": "magic_bool", 120 | "addr": "@save_data@", 121 | "offset": "0x3A", 122 | "readHandler": "80" 123 | }, 124 | { 125 | "key": "magic_size", 126 | "addr": "@save_data@", 127 | "offset": "0x3C", 128 | "readHandler": "80" 129 | }, 130 | { 131 | "key": "magic_limit", 132 | "addr": "@save_data@", 133 | "offset": "0x13F4", 134 | "readHandler": "81" 135 | } 136 | ] 137 | } -------------------------------------------------------------------------------- /src/command_inject/makefile: -------------------------------------------------------------------------------- 1 | AS = mips64-gcc 2 | OBJCOPY = mips64-objcopy 3 | BIN2GSC = gru bin2gsc.lua 4 | ASMFLAGS = -Os 5 | CPPFLAGS = 6 | ACTOR_CTOR_FUNC_ADDR = 0x80609200 7 | ACTOR_CTOR_HOOK_ADDR = 0x800210D0 8 | ACTOR_DTOR_FUNC_ADDR = 0x80609300 9 | ACTOR_DTOR_HOOK_ADDR = 0x80021104 10 | ROOM_ACTOR_FUNC_ADDR = 0x80609400 11 | ROOM_ACTOR_HOOK_ADDR = 0x80023DE8 12 | ACTOR_MAIN_FUNC_ADDR = 0x80609500 13 | ACTOR_MAIN_HOOK_ADDR = 0x800240D8 14 | SPAWN_ACTOR_FUNC_ADDR = 0x80609600 15 | SPAWN_ACTOR_HOOK_ADDR = 0x80025110 16 | TNSN_ACTOR_FUNC_ADDR = 0x80609700 17 | TNSN_ACTOR_HOOK_ADDR = 0x8002557C 18 | COMMAND_FUNC_ADDR = 0x80609800 19 | COMMAND_HOOK_ADDR = 0x800A0BF8 20 | 21 | GSC = actor_ctor_hook.gsc \ 22 | actor_dtor_hook.gsc \ 23 | room_actor_hook.gsc \ 24 | actor_main_hook.gsc \ 25 | spawn_actor_hook.gsc \ 26 | tnsn_actor_hook.gsc \ 27 | command_hook.gsc \ 28 | actor_ctor_func.gsc \ 29 | actor_dtor_func.gsc \ 30 | room_actor_func.gsc \ 31 | actor_main_func.gsc \ 32 | spawn_actor_func.gsc \ 33 | tnsn_actor_func.gsc \ 34 | command_func.gsc 35 | 36 | all : all.gsc 37 | clean : 38 | rm -f *.o *.bin *.gsc 39 | .PHONY : all clean 40 | 41 | %.o : %.S 42 | $(AS) $(CPPFLAGS) $(ASMFLAGS) -c $< -o $@ 43 | %.bin : %.o 44 | $(OBJCOPY) -j .text -j .data -O binary $< $@ 45 | %.gsc : %.bin 46 | $(BIN2GSC) $< $(GSC_ADDR) $@ 47 | all.gsc : $(GSC) 48 | cat $^ > $@ 49 | 50 | actor_ctor_hook.gsc : CPPFLAGS += -DACTOR_CTOR_FUNC_ADDR=$(ACTOR_CTOR_FUNC_ADDR) 51 | actor_dtor_hook.gsc : CPPFLAGS += -DACTOR_DTOR_FUNC_ADDR=$(ACTOR_DTOR_FUNC_ADDR) 52 | room_actor_hook.gsc : CPPFLAGS += -DROOM_ACTOR_FUNC_ADDR=$(ROOM_ACTOR_FUNC_ADDR) 53 | actor_main_hook.gsc : CPPFLAGS += -DACTOR_MAIN_FUNC_ADDR=$(ACTOR_MAIN_FUNC_ADDR) 54 | spawn_actor_hook.gsc : CPPFLAGS += -DSPAWN_ACTOR_FUNC_ADDR=$(SPAWN_ACTOR_FUNC_ADDR) 55 | tnsn_actor_hook.gsc : CPPFLAGS += -DTNSN_ACTOR_FUNC_ADDR=$(TNSN_ACTOR_FUNC_ADDR) 56 | command_hook.gsc : CPPFLAGS += -DCOMMAND_FUNC_ADDR=$(COMMAND_FUNC_ADDR) 57 | 58 | actor_ctor_func.gsc : GSC_ADDR = $(ACTOR_CTOR_FUNC_ADDR) 59 | actor_ctor_hook.gsc : GSC_ADDR = $(ACTOR_CTOR_HOOK_ADDR) 60 | actor_dtor_func.gsc : GSC_ADDR = $(ACTOR_DTOR_FUNC_ADDR) 61 | actor_dtor_hook.gsc : GSC_ADDR = $(ACTOR_DTOR_HOOK_ADDR) 62 | room_actor_func.gsc : GSC_ADDR = $(ROOM_ACTOR_FUNC_ADDR) 63 | room_actor_hook.gsc : GSC_ADDR = $(ROOM_ACTOR_HOOK_ADDR) 64 | actor_main_func.gsc : GSC_ADDR = $(ACTOR_MAIN_FUNC_ADDR) 65 | actor_main_hook.gsc : GSC_ADDR = $(ACTOR_MAIN_HOOK_ADDR) 66 | spawn_actor_func.gsc : GSC_ADDR = $(SPAWN_ACTOR_FUNC_ADDR) 67 | spawn_actor_hook.gsc : GSC_ADDR = $(SPAWN_ACTOR_HOOK_ADDR) 68 | tnsn_actor_func.gsc : GSC_ADDR = $(TNSN_ACTOR_FUNC_ADDR) 69 | tnsn_actor_hook.gsc : GSC_ADDR = $(TNSN_ACTOR_HOOK_ADDR) 70 | command_func.gsc : GSC_ADDR = $(COMMAND_FUNC_ADDR) 71 | command_hook.gsc : GSC_ADDR = $(COMMAND_HOOK_ADDR) 72 | -------------------------------------------------------------------------------- /plugins/localization/scene_numbers.json: -------------------------------------------------------------------------------- 1 | { 2 | "0": "scene_inside_the_deku_tree", 3 | "1": "scene_dodongo_cavern", 4 | "2": "scene_inside_jabu_jabu_belly", 5 | "3": "scene_forest_temple", 6 | "4": "scene_fire_temple", 7 | "5": "scene_water_temple", 8 | "6": "scene_spirit_temple", 9 | "7": "scene_shadow_temple", 10 | "8": "scene_bottom_of_the_well", 11 | "9": "scene_ice_cavern", 12 | "10": "scene_ganon_tower", 13 | "11": "scene_gerudo_training_ground", 14 | "12": "scene_thieves_hideout", 15 | "13": "scene_inside_ganon_castle", 16 | "14": "scene_ganon_tower_collapsing", 17 | "15": "scene_inside_ganon_castle_collapsing", 18 | "16": "scene_treasure_box_shop", 19 | "17": "scene_gohma_lair", 20 | "18": "scene_king_dodongo_lair", 21 | "19": "scene_barinade_lair", 22 | "20": "scene_phantom_ganon_lair", 23 | "21": "scene_volvagia_lair", 24 | "22": "scene_morpha_lair", 25 | "23": "scene_twinrova_lair_and_nabooru_mini_boss_room", 26 | "24": "scene_bongo_bongo_lair", 27 | "25": "scene_ganondorf_lair", 28 | "26": "tower_collapse_exterior", 29 | "27": "scene_market_entrance_child_day", 30 | "28": "scene_market_entrance_child_night", 31 | "29": "scene_market_entrance_child_ruins", 32 | "30": "scene_back_alley_child_day", 33 | "31": "scene_back_alley_child_night", 34 | "32": "scene_market_child_day", 35 | "33": "scene_market_child_night", 36 | "34": "scene_market_ruins", 37 | "35": "scene_temple_of_time_exterior_child_day", 38 | "36": "scene_temple_of_time_exterior_child_night", 39 | "37": "scene_temple_of_time_exterior_ruins", 40 | "38": "scene_know_it_all_brothers_house", 41 | "39": "scene_house_of_twins", 42 | "40": "scene_mido_house", 43 | "41": "scene_saria_house", 44 | "42": "scene_carpenter_boss_house", 45 | "43": "scene_back_alley_house_man_in_green", 46 | "44": "scene_bazaar", 47 | "45": "scene_kokiri_shop", 48 | "46": "scene_goron_shop", 49 | "47": "scene_zora_shop", 50 | "48": "scene_kakariko_potion_shop", 51 | "49": "scene_market_potion_shop", 52 | "50": "scene_bombchu_shop", 53 | "51": "scene_happy_mask_shop", 54 | "52": "scene_link_house", 55 | "53": "scene_back_alley_house_dog_lady", 56 | "54": "scene_stable", 57 | "55": "scene_impa_house", 58 | "56": "scene_lakeside_laboratory", 59 | "57": "scene_carpenters_tent", 60 | "58": "scene_gravekeeper_hut", 61 | "59": "scene_great_fairy_fountain_upgrades", 62 | "60": "scene_fairy_fountain", 63 | "61": "scene_great_fairy_fountain_spells", 64 | "62": "scene_grottos", 65 | "63": "scene_grave_redead", 66 | "64": "scene_grave_fairy_fountain", 67 | "65": "scene_royal_family_tomb", 68 | "66": "scene_shooting_gallery", 69 | "67": "scene_temple_of_time", 70 | "68": "scene_chamber_of_sages", 71 | "69": "scene_castle_hedge_maze_day", 72 | "70": "scene_castle_hedge_maze_night", 73 | "71": "scene_cutscene_map", 74 | "72": "scene_dampe_grave_and_windmill", 75 | "73": "scene_fishing_pond", 76 | "74": "scene_castle_courtyard", 77 | "75": "scene_bombchu_bowling_alley", 78 | "76": "scene_ranch_house_and_silo", 79 | "77": "scene_guard_house", 80 | "78": "scene_granny_potion_shop", 81 | "79": "scene_ganon_tower_collapse_and_battle_arena", 82 | "80": "scene_house_of_skulltula", 83 | "81": "scene_hyrule_field", 84 | "82": "scene_kakariko_village", 85 | "83": "scene_graveyard", 86 | "84": "scene_zora_river", 87 | "85": "scene_kokiri_forest", 88 | "86": "scene_sacred_forest_meadow", 89 | "87": "scene_lake_hylia", 90 | "88": "scene_zora_domain", 91 | "89": "scene_zora_fountain", 92 | "90": "scene_gerudo_valley", 93 | "91": "scene_lost_woods", 94 | "92": "scene_desert_colossus", 95 | "93": "scene_gerudo_fortress", 96 | "94": "scene_haunted_wasteland", 97 | "95": "scene_hyrule_castle", 98 | "96": "scene_death_mountain_trail", 99 | "97": "scene_death_mountain_crater", 100 | "98": "scene_goron_city", 101 | "99": "scene_lon_lon_ranch", 102 | "100": "scene_ganon_castle_exterior" 103 | } -------------------------------------------------------------------------------- /luasocket/lua/socket/tp.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | -- Unified SMTP/FTP subsystem 3 | -- LuaSocket toolkit. 4 | -- Author: Diego Nehab 5 | -- RCS ID: $Id: tp.lua,v 1.22 2006/03/14 09:04:15 diego Exp $ 6 | ----------------------------------------------------------------------------- 7 | 8 | ----------------------------------------------------------------------------- 9 | -- Declare module and import dependencies 10 | ----------------------------------------------------------------------------- 11 | local base = _G 12 | local string = require("string") 13 | local socket = require("socket") 14 | local ltn12 = require("ltn12") 15 | module("socket.tp") 16 | 17 | ----------------------------------------------------------------------------- 18 | -- Program constants 19 | ----------------------------------------------------------------------------- 20 | TIMEOUT = 60 21 | 22 | ----------------------------------------------------------------------------- 23 | -- Implementation 24 | ----------------------------------------------------------------------------- 25 | -- gets server reply (works for SMTP and FTP) 26 | local function get_reply(c) 27 | local code, current, sep 28 | local line, err = c:receive() 29 | local reply = line 30 | if err then return nil, err end 31 | code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) 32 | if not code then return nil, "invalid server reply" end 33 | if sep == "-" then -- reply is multiline 34 | repeat 35 | line, err = c:receive() 36 | if err then return nil, err end 37 | current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) 38 | reply = reply .. "\n" .. line 39 | -- reply ends with same code 40 | until code == current and sep == " " 41 | end 42 | return code, reply 43 | end 44 | 45 | -- metatable for sock object 46 | local metat = { __index = {} } 47 | 48 | function metat.__index:check(ok) 49 | local code, reply = get_reply(self.c) 50 | if not code then return nil, reply end 51 | if base.type(ok) ~= "function" then 52 | if base.type(ok) == "table" then 53 | for i, v in base.ipairs(ok) do 54 | if string.find(code, v) then 55 | return base.tonumber(code), reply 56 | end 57 | end 58 | return nil, reply 59 | else 60 | if string.find(code, ok) then return base.tonumber(code), reply 61 | else return nil, reply end 62 | end 63 | else return ok(base.tonumber(code), reply) end 64 | end 65 | 66 | function metat.__index:command(cmd, arg) 67 | if arg then 68 | return self.c:send(cmd .. " " .. arg.. "\r\n") 69 | else 70 | return self.c:send(cmd .. "\r\n") 71 | end 72 | end 73 | 74 | function metat.__index:sink(snk, pat) 75 | local chunk, err = c:receive(pat) 76 | return snk(chunk, err) 77 | end 78 | 79 | function metat.__index:send(data) 80 | return self.c:send(data) 81 | end 82 | 83 | function metat.__index:receive(pat) 84 | return self.c:receive(pat) 85 | end 86 | 87 | function metat.__index:getfd() 88 | return self.c:getfd() 89 | end 90 | 91 | function metat.__index:dirty() 92 | return self.c:dirty() 93 | end 94 | 95 | function metat.__index:getcontrol() 96 | return self.c 97 | end 98 | 99 | function metat.__index:source(source, step) 100 | local sink = socket.sink("keep-open", self.c) 101 | local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step) 102 | return ret, err 103 | end 104 | 105 | -- closes the underlying c 106 | function metat.__index:close() 107 | self.c:close() 108 | return 1 109 | end 110 | 111 | -- connect with server and return c object 112 | function connect(host, port, timeout, create) 113 | local c, e = (create or socket.tcp)() 114 | if not c then return nil, e end 115 | c:settimeout(timeout or TIMEOUT) 116 | local r, e = c:connect(host, port) 117 | if not r then 118 | c:close() 119 | return nil, e 120 | end 121 | return base.setmetatable({c = c}, metat) 122 | end 123 | 124 | -------------------------------------------------------------------------------- /src/OotPluginLoader.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const loadPlugins = require('plugin-system'); 20 | const logger = require('./OotLogger')("PluginManager"); 21 | const fs = require("fs"); 22 | const gameshark = require(global.OotRunDir + "/GamesharkToInjectConverter"); 23 | const emulator = require(global.OotRunDir + "/OotBizHawk"); 24 | var util = require('util'); 25 | const api = require(global.OotRunDir + "/OotAPI"); 26 | 27 | class PluginLoader { 28 | constructor() { 29 | } 30 | 31 | load(callback) { 32 | loadPlugins( 33 | { 34 | paths: [ 35 | process.cwd() + '/plugins/', 36 | ], 37 | custom: [], 38 | }) 39 | .then(function onSuccess(plugins) { 40 | logger.log("Starting preinit phase.", "green"); 41 | for (let i = 0; i < plugins.length; i++) { 42 | logger.log("Plugin Preinit: " + plugins[i]._name); 43 | plugins[i].preinit(); 44 | } 45 | logger.log("Starting init phase.", "green"); 46 | for (let i = 0; i < plugins.length; i++) { 47 | logger.log("Plugin Init: " + plugins[i]._name); 48 | plugins[i].init(); 49 | } 50 | logger.log("Starting postinit phase.", "green"); 51 | for (let i = 0; i < plugins.length; i++) { 52 | logger.log("Plugin Postinit: " + plugins[i]._name); 53 | plugins[i].postinit(); 54 | } 55 | logger.log("Plugin loading complete.", "green"); 56 | callback(); 57 | }) 58 | .catch(function onError(err) { 59 | logger.log(err, "red"); 60 | logger.log(err.stack, "red"); 61 | }); 62 | let payloads = fs.readdirSync(process.cwd() + '/plugins/payloads_10'); 63 | let p = []; 64 | logger.log("Starting payload loading phase.", "green"); 65 | Object.keys(payloads).forEach(function (key) { 66 | if (payloads[key].indexOf(".payload") > -1) { 67 | logger.log("Loading payload: " + payloads[key] + "."); 68 | let j = gameshark.read(process.cwd() + '/plugins/payloads_10/' + payloads[key]); 69 | p.push(j); 70 | } 71 | }); 72 | emulator.setConnectedFn(function () { 73 | for (let i = 0; i < p.length; i++) { 74 | if (p[i].params.event !== undefined) { 75 | api.registerEventHandler(p[i].params.event, function (event) { 76 | emulator.sendViaSocket({ packet_id: "gs", codes: p[i].codes }); 77 | }); 78 | } else { 79 | if (p[i].params.delay !== undefined) { 80 | emulator.sendViaSocket({ packet_id: "gs", codes: p[i].codes, delay: Number(p[i].params.delay) }); 81 | } else { 82 | emulator.sendViaSocket({ packet_id: "gs", codes: p[i].codes }); 83 | } 84 | api.registerEventHandler("onSoftReset_Post", function (event) { 85 | if (p[i].params.delay !== undefined) { 86 | emulator.sendViaSocket({ packet_id: "gs", codes: p[i].codes, delay: Number(p[i].params.delay) }); 87 | } else { 88 | emulator.sendViaSocket({ packet_id: "gs", codes: p[i].codes }); 89 | } 90 | }); 91 | } 92 | } 93 | }); 94 | } 95 | } 96 | 97 | module.exports = new PluginLoader(); -------------------------------------------------------------------------------- /luasocket/lua/socket.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | -- LuaSocket helper module 3 | -- Author: Diego Nehab 4 | -- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $ 5 | ----------------------------------------------------------------------------- 6 | 7 | ----------------------------------------------------------------------------- 8 | -- Declare module and import dependencies 9 | ----------------------------------------------------------------------------- 10 | local base = _G 11 | local string = require("string") 12 | local math = require("math") 13 | local socket = require("socket.core") 14 | module("socket") 15 | 16 | ----------------------------------------------------------------------------- 17 | -- Exported auxiliar functions 18 | ----------------------------------------------------------------------------- 19 | function connect(address, port, laddress, lport) 20 | local sock, err = socket.tcp() 21 | if not sock then return nil, err end 22 | if laddress then 23 | local res, err = sock:bind(laddress, lport, -1) 24 | if not res then return nil, err end 25 | end 26 | local res, err = sock:connect(address, port) 27 | if not res then return nil, err end 28 | return sock 29 | end 30 | 31 | function bind(host, port, backlog) 32 | local sock, err = socket.tcp() 33 | if not sock then return nil, err end 34 | sock:setoption("reuseaddr", true) 35 | local res, err = sock:bind(host, port) 36 | if not res then return nil, err end 37 | res, err = sock:listen(backlog) 38 | if not res then return nil, err end 39 | return sock 40 | end 41 | 42 | try = newtry() 43 | 44 | function choose(table) 45 | return function(name, opt1, opt2) 46 | if base.type(name) ~= "string" then 47 | name, opt1, opt2 = "default", name, opt1 48 | end 49 | local f = table[name or "nil"] 50 | if not f then base.error("unknown key (".. base.tostring(name) ..")", 3) 51 | else return f(opt1, opt2) end 52 | end 53 | end 54 | 55 | ----------------------------------------------------------------------------- 56 | -- Socket sources and sinks, conforming to LTN12 57 | ----------------------------------------------------------------------------- 58 | -- create namespaces inside LuaSocket namespace 59 | sourcet = {} 60 | sinkt = {} 61 | 62 | BLOCKSIZE = 2048 63 | 64 | sinkt["close-when-done"] = function(sock) 65 | return base.setmetatable({ 66 | getfd = function() return sock:getfd() end, 67 | dirty = function() return sock:dirty() end 68 | }, { 69 | __call = function(self, chunk, err) 70 | if not chunk then 71 | sock:close() 72 | return 1 73 | else return sock:send(chunk) end 74 | end 75 | }) 76 | end 77 | 78 | sinkt["keep-open"] = function(sock) 79 | return base.setmetatable({ 80 | getfd = function() return sock:getfd() end, 81 | dirty = function() return sock:dirty() end 82 | }, { 83 | __call = function(self, chunk, err) 84 | if chunk then return sock:send(chunk) 85 | else return 1 end 86 | end 87 | }) 88 | end 89 | 90 | sinkt["default"] = sinkt["keep-open"] 91 | 92 | sink = choose(sinkt) 93 | 94 | sourcet["by-length"] = function(sock, length) 95 | return base.setmetatable({ 96 | getfd = function() return sock:getfd() end, 97 | dirty = function() return sock:dirty() end 98 | }, { 99 | __call = function() 100 | if length <= 0 then return nil end 101 | local size = math.min(socket.BLOCKSIZE, length) 102 | local chunk, err = sock:receive(size) 103 | if err then return nil, err end 104 | length = length - string.len(chunk) 105 | return chunk 106 | end 107 | }) 108 | end 109 | 110 | sourcet["until-closed"] = function(sock) 111 | local done 112 | return base.setmetatable({ 113 | getfd = function() return sock:getfd() end, 114 | dirty = function() return sock:dirty() end 115 | }, { 116 | __call = function() 117 | if done then return nil end 118 | local chunk, err, partial = sock:receive(socket.BLOCKSIZE) 119 | if not err then return chunk 120 | elseif err == "closed" then 121 | sock:close() 122 | done = 1 123 | return partial 124 | else return nil, err end 125 | end 126 | }) 127 | end 128 | 129 | 130 | sourcet["default"] = sourcet["until-closed"] 131 | 132 | source = choose(sourcet) 133 | 134 | -------------------------------------------------------------------------------- /src/OotBizHawk.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const net = require('net'); 20 | JsonSocket = require('json-socket'); 21 | const CONFIG = require('./OotConfig'); 22 | const udp = require('./OotUDP'); 23 | const logger = require('./OotLogger')("BizHawkTCP"); 24 | const LOCAL_PORT = 1337; 25 | const LOCAL_PORT_UDP = 60001; 26 | 27 | class EmuConnection { 28 | constructor() { 29 | this._emuhawk = null; 30 | this._packet_buffer = ""; 31 | this._awaiting_send = []; 32 | this._processDataFn = function () { }; 33 | this._connectedtoEmuCallcack = function () { }; 34 | this._dynamicPackets = []; 35 | this._udp = udp.server(LOCAL_PORT, "BizHawkUDP"); 36 | this._droppedPackets = 0; 37 | this._jSocket = null; 38 | if (CONFIG.isClient) { 39 | (function (inst) { 40 | inst._zServer = net.createServer(function (socket) { 41 | inst._emuhawk = socket; 42 | inst._jSocket = new JsonSocket(socket); 43 | logger.log("Connected to BizHawk!"); 44 | inst._connectedtoEmuCallcack(); 45 | inst._dynamicPackets.forEach(function (packet) { 46 | inst.sendViaSocket(packet); 47 | }); 48 | inst._jSocket.on('message', function (data) { 49 | inst._processDataFn(data); 50 | }); 51 | inst._jSocket.on('error', function(error){ 52 | //logger.log(error, "red"); 53 | }); 54 | while (inst._awaiting_send.length > 0) { 55 | let p = inst._awaiting_send.shift(); 56 | inst.sendViaSocket(p); 57 | } 58 | }); 59 | inst._zServer.listen(LOCAL_PORT, '127.0.0.1', function () { 60 | logger.log("Awaiting connection. Please load the .lua script in Bizhawk."); 61 | inst._udp.setDataFn(inst._processDataFn); 62 | inst._udp.setup(); 63 | }); 64 | })(this); 65 | } 66 | } 67 | 68 | registerDynamicPacket(packet) { 69 | return this._dynamicPackets[this._dynamicPackets.push(packet) - 1]; 70 | } 71 | 72 | setDataParseFn(fn) { 73 | this._processDataFn = fn; 74 | } 75 | 76 | setConnectedFn(fn) { 77 | this._connectedtoEmuCallcack = fn; 78 | } 79 | 80 | sendViaUDP(data) { 81 | this._udp.sendTo_InternalUseOnly("127.0.0.1", LOCAL_PORT_UDP, data); 82 | } 83 | 84 | sendViaSocket(data) { 85 | try { 86 | let json = JSON.stringify(data); 87 | if (this._emuhawk === null) { 88 | this.awaiting_send.push(data); 89 | } else { 90 | this._emuhawk.write(json + "\r\n"); 91 | } 92 | } catch (error) { 93 | } 94 | } 95 | 96 | get emuhawk() { 97 | return this._emuhawk; 98 | } 99 | 100 | set emuhawk(value) { 101 | this._emuhawk = value; 102 | } 103 | 104 | get packet_buffer() { 105 | return this._packet_buffer; 106 | } 107 | 108 | set packet_buffer(value) { 109 | this._packet_buffer = value; 110 | } 111 | 112 | get awaiting_send() { 113 | return this._awaiting_send; 114 | } 115 | 116 | set awaiting_send(value) { 117 | this._awaiting_send = value; 118 | } 119 | 120 | get zServer() { 121 | return this._zServer; 122 | } 123 | 124 | set zServer(value) { 125 | this._zServer = value; 126 | } 127 | 128 | get server() { 129 | return this._server; 130 | } 131 | 132 | set server(value) { 133 | this._server = value; 134 | } 135 | } 136 | 137 | module.exports = new EmuConnection(); -------------------------------------------------------------------------------- /GUI/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OotModLoader Launcher 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 44 | 45 | 46 | 47 |
48 | 55 |
56 |

Server Settings

57 |
58 |
59 |
60 |

Client Settings

61 |
62 |
63 |
64 |
66 | 69 |
70 |
71 | 72 |
73 |
74 |
75 |
77 |
79 |
81 |
82 |
83 | Nothing on this tab currently works, sorry!
84 | Connection Status:
  • Not connected.
  • 85 |
    86 | Player List: 87 |
  • None.
  • 88 |
    89 |
    90 | Coming soon™. 91 |
    92 |
    93 |
    94 |
    95 |
    96 | 97 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/OotUDP.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const dgram = require('dgram'); 20 | const encoder = require('./OotEncoder'); 21 | 22 | class OotUDPServer { 23 | constructor(port, name) { 24 | this._server = dgram.createSocket('udp4'); 25 | this._port = port; 26 | this._logger = require('./OotLogger')(name); 27 | this._onDataFn = function (msg) { }; 28 | } 29 | 30 | get logger() { 31 | return this._logger; 32 | } 33 | 34 | get port() { 35 | return this._port; 36 | } 37 | 38 | set port(p) { 39 | this._port = p; 40 | } 41 | 42 | get server() { 43 | return this._server; 44 | } 45 | 46 | setDataFn(fn) { 47 | this._onDataFn = fn; 48 | } 49 | 50 | sendTo(address, port, msg) { 51 | let data = JSON.stringify(msg); 52 | this._server.send(Buffer.from(data.length + "#" + data), port, address, (err) => { 53 | }); 54 | } 55 | 56 | sendTo_InternalUseOnly(address, port, msg) { 57 | let data = JSON.stringify(msg) + "\r\n"; 58 | this._server.send(Buffer.from(data), port, address, (err) => { 59 | }); 60 | } 61 | 62 | send(address, msg) { 63 | let data = JSON.stringify(msg); 64 | this._server.send(Buffer.from(data.length + "#" + data), this.port, address, (err) => { 65 | }); 66 | } 67 | 68 | setup() { 69 | (function (inst) { 70 | inst.server.on('message', (msg, rinfo) => { 71 | inst._onDataFn(JSON.parse(Buffer.from(msg).toString().split("#")[1])); 72 | }); 73 | 74 | inst.server.on('listening', () => { 75 | const address = inst.server.address(); 76 | inst.logger.log(`listening ${address.address}:${address.port}`); 77 | inst.port = address.port; 78 | }); 79 | inst.server.bind(inst.port); 80 | })(this); 81 | } 82 | } 83 | 84 | class OotUDPClient { 85 | constructor(port, name) { 86 | this._server = dgram.createSocket('udp4'); 87 | this._port = port; 88 | this._logger = require('./OotLogger')(name); 89 | this._onDataFn = function (msg) { }; 90 | } 91 | 92 | get logger() { 93 | return this._logger; 94 | } 95 | 96 | get port() { 97 | return this._port; 98 | } 99 | 100 | set port(p) { 101 | this._port = p; 102 | } 103 | 104 | get server() { 105 | return this._server; 106 | } 107 | 108 | setDataFn(fn) { 109 | this._onDataFn = fn; 110 | } 111 | 112 | sendTo(address, port, msg) { 113 | let data = JSON.stringify(msg); 114 | this._server.send(Buffer.from(data.length + "#" + data), port, address, (err) => { 115 | }); 116 | } 117 | 118 | send(address, msg) { 119 | let data = JSON.stringify(msg); 120 | this._server.send(Buffer.from(data.length + "#" + data), this.port, address, (err) => { 121 | }); 122 | } 123 | 124 | setup() { 125 | (function (inst) { 126 | inst.server.on('message', (msg, rinfo) => { 127 | let p = JSON.parse(Buffer.from(msg).toString().split("#")[1]); 128 | if (p.hasOwnProperty("payload")) { 129 | p.payload = encoder.decompressData(p.payload); 130 | } 131 | inst._onDataFn(p); 132 | }); 133 | 134 | inst.server.on('listening', () => { 135 | const address = inst.server.address(); 136 | inst.logger.log(`listening ${address.address}:${address.port}`); 137 | inst.port = address.port; 138 | }); 139 | inst.server.bind(inst.port); 140 | })(this); 141 | } 142 | } 143 | 144 | function createNewServer(port, name) { 145 | return new OotUDPServer(port, name); 146 | } 147 | 148 | function createNewClient(port, name) { 149 | return new OotUDPClient(port, name); 150 | } 151 | 152 | module.exports = { server: createNewServer, client: createNewClient }; -------------------------------------------------------------------------------- /src/fake_test_client.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | // This is Lynn the fake test client. 20 | // She mimics a normal OotRandoCoop client for testing purposes during development. 21 | 22 | const IO_Client = require('socket.io-client'); 23 | const crypto = require('crypto'); 24 | const fs = require("fs"); 25 | const jpack = require('jsonpack'); 26 | 27 | let master_server_ip = "127.0.0.1"; 28 | let master_server_port = "8081"; 29 | let GAME_ROOM = "test"; 30 | let nickname = "Lynn"; 31 | let my_uuid = ""; 32 | let logger = require('./OotLogger')("Lynn"); 33 | 34 | let encoder = require('./OotEncoder'); 35 | 36 | const socket = IO_Client.connect("http://" + master_server_ip + ":" + master_server_port); 37 | 38 | function sendDataToMaster(data){ 39 | socket.emit('msg', { 40 | channel: 'msg', 41 | room: GAME_ROOM, 42 | uuid: my_uuid, 43 | nickname: nickname, 44 | payload: encoder.compressData(data) 45 | }); 46 | } 47 | 48 | function sendDataToMasterRaw(data){ 49 | socket.emit('msg', { 50 | channel: 'msg', 51 | room: GAME_ROOM, 52 | uuid: my_uuid, 53 | nickname: nickname, 54 | payload: data 55 | }); 56 | } 57 | 58 | function sendDataToMasterOnChannel(channel, data){ 59 | socket.emit('msg', { 60 | channel: channel, 61 | room: GAME_ROOM, 62 | uuid: my_uuid, 63 | nickname: nickname, 64 | payload: encoder.compressData(data) 65 | }); 66 | } 67 | 68 | let o = false; 69 | let int = null; 70 | 71 | function runDemo(){ 72 | setTimeout(function(){ 73 | console.log("Starting demo..."); 74 | let m = JSON.parse(fs.readFileSync("movement_test.json")); 75 | setTimeout(function(){ 76 | int = setInterval(function(){ 77 | if (m.length > 0){ 78 | let packet = m.shift(); 79 | sendDataToMasterRaw(packet); 80 | }else{ 81 | clearInterval(int); 82 | int = null; 83 | logger.log("Demo end."); 84 | } 85 | }, 50); 86 | }, 100); 87 | }, 5000); 88 | } 89 | 90 | let save = []; 91 | 92 | let recording = false; 93 | 94 | let minutes = 5; 95 | 96 | function startRecording(scene){ 97 | console.log("Starting recording..."); 98 | sendDataToMasterOnChannel('scene', {packet_id: "scene", writeHandler: "81", data: scene}); 99 | setTimeout(stopRecording, (minutes * 60) * 1000); 100 | recording = true; 101 | } 102 | 103 | function stopRecording(){ 104 | sendDataToMasterOnChannel('scene', {packet_id: "scene", writeHandler: "81", data: -1}); 105 | console.log("Stopping recording..."); 106 | recording = false; 107 | } 108 | 109 | function record(data){ 110 | if (recording){ 111 | save.push(data); 112 | fs.writeFileSync("movement_test.json", JSON.stringify(save)); 113 | } 114 | } 115 | 116 | socket.on('connect', function(){ 117 | o = false; 118 | socket.on('id', function(data){ 119 | my_uuid = data.id; 120 | logger.log("Client: My UUID: " + my_uuid); 121 | socket.emit('room', {room: GAME_ROOM}); 122 | }); 123 | socket.on('room', function(data){ 124 | logger.log(data.msg); 125 | socket.emit('room_ping', {room: GAME_ROOM, uuid: my_uuid, nickname: nickname}); 126 | }); 127 | socket.on('joined', function(data){ 128 | logger.log(data.uuid + " joined."); 129 | }); 130 | socket.on('room_ping', function(data){ 131 | logger.log("Got ping from " + data.nickname + "."); 132 | socket.emit('room_pong', {room: GAME_ROOM, uuid: my_uuid, nickname: nickname}); 133 | }); 134 | socket.on('room_pong', function(data){ 135 | logger.log("Got pong from " + data.nickname + "."); 136 | }); 137 | socket.on('msg', function(data){ 138 | if (!o){ 139 | //startRecording(encoder.decompressData(data.payload).data); 140 | runDemo(); 141 | o = true; 142 | } 143 | record(data.payload); 144 | }); 145 | }); -------------------------------------------------------------------------------- /plugins/MaskKeeper.js: -------------------------------------------------------------------------------- 1 | /* 2 | MaskKeeper - Retain your mask through loading zones and removing it from the C-buttons. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const emulator = require(global.OotRunDir + "/OotBizHawk"); 20 | const api = require(global.OotRunDir + "/OotAPI"); 21 | const logger = require(global.OotRunDir + "/OotLogger")("MaskKeeper"); 22 | 23 | class MaskKeeper { 24 | constructor() { 25 | this._name = "MaskKeeper"; 26 | this._lastKnownMask = 0; 27 | this._isSceneChanging = false; 28 | this._isChild = false; 29 | } 30 | 31 | preinit() { 32 | api.registerPacket({ 33 | packet_id: "mask_id", 34 | addr: "@link_instance@", 35 | offset: "0x14F", 36 | readHandler: "80" 37 | }); 38 | api.registerEvent("onMaskChange"); 39 | } 40 | 41 | init() { 42 | api.registerClientSidePacketHook("mask_id", function (packet) { 43 | if (packet.data !== 0xFF) { 44 | api.postEvent({ id: "onMaskChange", mask: packet.data }); 45 | } 46 | return false; 47 | }); 48 | } 49 | 50 | postinit() { 51 | (function (inst) { 52 | emulator.sendViaSocket({ 53 | packet_id: "masksStay", 54 | writeHandler: "freeze", 55 | writeHandler_freeze: "fourBytes", 56 | addr: "0x38a8bc", 57 | offset: 0, 58 | data: 0x00000000 59 | }); 60 | api.registerEventHandler("onMaskChange", function (event) { 61 | if (!inst._isSceneChanging && inst._isChild) { 62 | inst._lastKnownMask = event.mask; 63 | logger.log(event); 64 | } 65 | }); 66 | api.registerEventHandler("preSceneChange", function (event) { 67 | inst._isSceneChanging = true; 68 | }); 69 | api.registerEventHandler("onStateChanged", function (event) { 70 | if (event.state !== 0) { 71 | inst._isSceneChanging = true; 72 | } else { 73 | inst._isSceneChanging = false; 74 | } 75 | }); 76 | api.registerEventHandler("onLinkRespawn", function (event) { 77 | setTimeout(function () { 78 | inst._isSceneChanging = false; 79 | if (inst._isChild) { 80 | let packet = { 81 | packet_id: "changeMask", 82 | writeHandler: "80", 83 | addr: api.getTokenStorage()["@link_instance@"], 84 | offset: "0x14F", 85 | data: inst._lastKnownMask 86 | } 87 | emulator.sendViaSocket(packet); 88 | logger.log(packet); 89 | } 90 | }, 1000); 91 | }); 92 | api.registerEventHandler("onAgeChanged", function (event) { 93 | if (event.player.isMe) { 94 | if (event.age === 0x803A9D5C) { 95 | inst._isChild = true; 96 | logger.log("Player is now child link."); 97 | if (inst._isChild) { 98 | let packet = { 99 | packet_id: "changeMask", 100 | writeHandler: "80", 101 | addr: api.getTokenStorage()["@link_instance@"], 102 | offset: "0x14F", 103 | data: inst._lastKnownMask 104 | } 105 | emulator.sendViaSocket(packet); 106 | logger.log(packet); 107 | } 108 | } else { 109 | logger.log("Player is now adult link."); 110 | inst._isChild = false; 111 | } 112 | } 113 | }); 114 | })(this) 115 | } 116 | } 117 | 118 | module.exports = new MaskKeeper(); -------------------------------------------------------------------------------- /src/OotAPI.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const emulator = require(global.OotRunDir + "/OotBizHawk"); 20 | const logger = require('./OotLogger')("API"); 21 | 22 | class OotAPI { 23 | constructor() { 24 | this._transformerFn = function () { }; 25 | this._eventHandlers = {}; 26 | this._routeFn = function () { }; 27 | this._clienthookFn = function () { }; 28 | this._tokenStorage = {}; 29 | this._channelFn = function () { }; 30 | this.GAME_VERSION = "10"; 31 | this._plugindir = ""; 32 | this._serverSideStorage = function () { }; 33 | this._ModuleStorage = {}; 34 | } 35 | 36 | set plugindir(dir) { 37 | logger.log("Plugin directory set to " + dir + "."); 38 | this._plugindir = dir; 39 | } 40 | 41 | registerModule(name, m) { 42 | this._ModuleStorage[name] = m; 43 | } 44 | 45 | getModule(name) { 46 | return this._ModuleStorage[name]; 47 | } 48 | 49 | getServerSideStorage(room) { 50 | return this._serverSideStorage(room); 51 | } 52 | 53 | setServerSideStorage(fn) { 54 | this._serverSideStorage = fn; 55 | } 56 | 57 | getTokenStorage() { 58 | return this._tokenStorage; 59 | } 60 | 61 | setTransformerFn(fn) { 62 | this._transformerFn = fn; 63 | } 64 | 65 | setRouteFn(fn) { 66 | this._routeFn = fn; 67 | } 68 | 69 | setClientHookFn(fn) { 70 | this._clienthookFn = fn; 71 | } 72 | 73 | setChannelFn(fn) { 74 | this._channelFn = fn; 75 | } 76 | 77 | postEvent(event) { 78 | if (this._eventHandlers.hasOwnProperty(event.id)) { 79 | for (let i = 0; i < this._eventHandlers[event.id].length; i++) { 80 | try { 81 | this._eventHandlers[event.id][i](event); 82 | } catch (err) { 83 | logger.log("Error posting event " + event.id + " due to:", "red"); 84 | logger.log(err.stack, "red"); 85 | continue; 86 | } 87 | } 88 | } 89 | } 90 | 91 | registerClientSidePacketHook(packet_id, hook) { 92 | this._clienthookFn(packet_id, hook); 93 | } 94 | 95 | registerPacketRoute(packet_id, route) { 96 | this._routeFn(packet_id, route); 97 | } 98 | 99 | registerServerChannel(name, fn) { 100 | this._channelFn(name, fn); 101 | } 102 | 103 | registerConfigCategory(name, options) { 104 | //stub 105 | } 106 | 107 | registerPacket(packet) { 108 | let p = packet; 109 | if (typeof packet === "string") { 110 | p = require(packet); 111 | } 112 | emulator.registerDynamicPacket({ packet_id: "registerPacket", data: p }); 113 | } 114 | 115 | registerEvent(eventid) { 116 | if (!this._eventHandlers.hasOwnProperty(eventid)){ 117 | this._eventHandlers[eventid] = []; 118 | } 119 | } 120 | 121 | registerEventHandler(eventid, handler) { 122 | if (!this._eventHandlers.hasOwnProperty(eventid)) { 123 | this.registerEvent(eventid); 124 | } 125 | return this._eventHandlers[eventid].push(handler) - 1; 126 | } 127 | 128 | unregisterEventHandler(eventid, handlerid) { 129 | this._eventHandlers[eventid].splice(handlerid, 1); 130 | } 131 | 132 | registerToken(token) { 133 | let p = token; 134 | if (typeof token === "string") { 135 | p = require(token); 136 | } 137 | emulator.registerDynamicPacket({ packet_id: "registerToken", data: p }); 138 | this.getTokenStorage()[p.token] = p.replace; 139 | } 140 | 141 | registerPacketTransformer(packet_id, fn) { 142 | this._transformerFn(packet_id, fn); 143 | } 144 | 145 | loadVariables(name) { 146 | try { 147 | let LOAD_YOU = require(this._plugindir + 148 | "/versions/" + 149 | this.GAME_VERSION + 150 | "/" + 151 | name); 152 | return LOAD_YOU; 153 | } catch (err) { 154 | logger.log(err.stack, "red"); 155 | } 156 | } 157 | } 158 | 159 | module.exports = new OotAPI(); 160 | -------------------------------------------------------------------------------- /src/for_emulator/Lua/test/PuppetTester.lua: -------------------------------------------------------------------------------- 1 | memory.usememorydomain("RDRAM") 2 | require("OotUtils") 3 | 4 | local context = 0x600000 5 | local buffer_offset = 0x90 6 | local link_instance = 0x1DAA30 7 | 8 | function getPuppet(slot) 9 | local slots = {} 10 | local s = 0; 11 | for i=1,3,1 do 12 | if (i == 1) then 13 | s = s + 4; 14 | else 15 | s = s + 8; 16 | end 17 | table.insert(slots, s); 18 | end 19 | console.log(slots); 20 | return readPointer(context + buffer_offset + tonumber(slots[slot])) 21 | end 22 | 23 | function hex2rgb(hex) 24 | hex = hex:gsub("#", "") 25 | return tonumber("0x" .. hex:sub(1, 2)), tonumber("0x" .. hex:sub(3, 4)), tonumber("0x" .. hex:sub(5, 6)) 26 | end 27 | 28 | function ranndomHexColor() 29 | local r = math.random(255); 30 | local g = math.random(255); 31 | local b = math.random(255); 32 | return r, g, b 33 | end 34 | 35 | local run = true 36 | 37 | form = forms.newform( 38 | 250, 39 | 500, 40 | "OotOnline Puppet Debugger", 41 | function() run = false end 42 | ) 43 | local ypos = 0 44 | 45 | function increasePos() ypos = ypos + 20 end 46 | 47 | function drawString(str, pos) 48 | local pb = forms.pictureBox(form, 0, pos, 500, 20) 49 | forms.drawString(pb, 0, 0, str) 50 | end 51 | 52 | function drawLabel(str, pos) forms.label(form, str, 0, pos, 500, 20) end 53 | 54 | local locked_puppet = getPuppet(1) 55 | 56 | drawString("Puppet Found: " .. DEC_HEX(locked_puppet), ypos) 57 | increasePos() 58 | 59 | forms.button( 60 | form, 61 | "Move Puppet to me.", 62 | function() 63 | local pos = readByteRange(link_instance + 0x24, 0xC) 64 | writeByteRange(locked_puppet + 0x24, pos) 65 | end, 66 | 0, 67 | ypos, 68 | 200, 69 | 20 70 | ) 71 | increasePos() 72 | 73 | local anim_box = forms.checkbox(form, "Animate it.", 5, ypos) 74 | increasePos() 75 | increasePos() 76 | drawLabel("Tunic Color", ypos) 77 | increasePos() 78 | local color = forms.textbox(form, "#eb41f4", 50, 50, nil, 5, ypos) 79 | increasePos() 80 | drawLabel("Right Hand", ypos) 81 | increasePos() 82 | local rhand = forms.dropdown( 83 | form, 84 | {"Empty", "OoT", "Closed Fist", "Bow", "Hookshot"}, 85 | 5, 86 | ypos, 87 | 100, 88 | 20 89 | ) 90 | increasePos() 91 | 92 | local rhand_table = {} 93 | rhand_table["Empty"] = 0x800F7918 94 | rhand_table["OoT"] = 0x800F7988 95 | rhand_table["Closed Fist"] = 0x800F7928 96 | rhand_table["Bow"] = 0x800F7938 97 | rhand_table["Hookshot"] = 0x800F79A8 98 | 99 | drawLabel("Left Hand", ypos) 100 | increasePos() 101 | local lhand = forms.dropdown(form, {"Empty", "Bottle"}, 5, ypos, 100, 20) 102 | increasePos() 103 | 104 | local lhand_table = {} 105 | lhand_table["Empty"] = 0x800F78D8 106 | lhand_table["Bottle"] = 0x800F79D8 107 | 108 | drawLabel("Sheath", ypos) 109 | increasePos() 110 | local sheath = forms.dropdown(form, {"Empty", "Master Sword"}, 5, ypos, 100, 20) 111 | increasePos() 112 | 113 | local sheath_table = {} 114 | sheath_table["Empty"] = 0x800F7958 115 | sheath_table["Master Sword"] = 0x800F77F8 116 | 117 | local frameHooks = {} 118 | 119 | function addFramehook(fn, max) table.insert(frameHooks, {fn = fn, max = max, count = 0}) end 120 | 121 | for i = 1, 3, 1 do 122 | addFramehook( 123 | function() 124 | local p = getPuppet(i) 125 | console.log(DEC_HEX(p)); 126 | local anim = readByteRange(context, 0x86) 127 | writeByteRange(p + 0x1E0, anim) 128 | writeFourBytesUnsigned(p + 0x140, rhand_table[forms.gettext(rhand)]) 129 | writeFourBytesUnsigned(p + 0x144, lhand_table[forms.gettext(lhand)]) 130 | writeFourBytesUnsigned(p + 0x148, sheath_table[forms.gettext(sheath)]) 131 | local pos = readByteRange(link_instance + 0x24, 0xC) 132 | local r, g, b = ranndomHexColor() 133 | writeByte(p + 0x154, r) 134 | writeByte(p + 0x155, g) 135 | writeByte(p + 0x156, b) 136 | writeByteRange(p + 0x24, pos) 137 | end, 138 | 100 139 | ) 140 | end 141 | 142 | while run do 143 | if (forms.ischecked(anim_box)) then 144 | local anim = readByteRange(context, 0x86) 145 | writeByteRange(locked_puppet + 0x1E0, anim) 146 | end 147 | pcall(function() 148 | local r, g, b = hex2rgb(forms.gettext(color)) 149 | writeByte(locked_puppet + 0x154, r) 150 | writeByte(locked_puppet + 0x155, g) 151 | writeByte(locked_puppet + 0x156, b) 152 | end) 153 | writeFourBytesUnsigned( 154 | locked_puppet + 0x140, 155 | rhand_table[forms.gettext(rhand)] 156 | ) 157 | writeFourBytesUnsigned( 158 | locked_puppet + 0x144, 159 | lhand_table[forms.gettext(lhand)] 160 | ) 161 | writeFourBytesUnsigned( 162 | locked_puppet + 0x148, 163 | sheath_table[forms.gettext(sheath)] 164 | ) 165 | if (next(frameHooks) ~= nil) then 166 | if (frameHooks[1].count >= frameHooks[1].max) then 167 | local n = table.remove(frameHooks, 1) 168 | n.fn() 169 | else 170 | frameHooks[1].count = frameHooks[1].count + 1 171 | end 172 | end 173 | emu.frameadvance() 174 | end 175 | -------------------------------------------------------------------------------- /src/command_inject/command_func.S: -------------------------------------------------------------------------------- 1 | .include "z64defs.inc" 2 | .include "notif.inc" 3 | 4 | .set command_buf, 0x80600090 5 | .set COMMAND_BUF_LENGTH, 0x00000010 6 | .set COMMAND_SPAWN_ACTOR, 0x00000001 7 | .set COMMAND_UPDATE_BUTTON, 0x00000002 8 | .set COMMAND_PLAY_SOUND, 0x00000003 9 | .set COMMAND_LOAD_OBJECT, 0x00000004 10 | .set COMMAND_WARP, 0x00000005 11 | .set COMMAND_PLAY_MUSIC, 0x00000006 12 | 13 | .section .text 14 | 15 | .ent command_func 16 | .type command_func, @function 17 | command_func: 18 | 19 | /* set up stack frame */ 20 | addiu $sp, $sp, -0x0040 21 | sw $ra, 0x0030($sp) 22 | sw $s0, 0x0034($sp) 23 | sw $s1, 0x0038($sp) 24 | sw $a0, 0x0040($sp) 25 | 26 | /* process commands */ 27 | move $s0, $zero 28 | la $s1, command_buf 29 | cmd_loop_head: 30 | lw $v0, 0x0000($s1) 31 | lw $v1, 0x0004($s1) 32 | 33 | /* check command type */ 34 | la $t0, COMMAND_SPAWN_ACTOR 35 | beq $v0, $t0, cmd_spawn_actor 36 | la $t0, COMMAND_UPDATE_BUTTON 37 | beq $v0, $t0, cmd_update_button 38 | la $t0, COMMAND_PLAY_SOUND 39 | beq $v0, $t0, cmd_play_sound 40 | la $t0, COMMAND_LOAD_OBJECT 41 | beq $v0, $t0, cmd_load_object 42 | la $t0, COMMAND_WARP 43 | beq $v0, $t0, cmd_warp 44 | la $t0, COMMAND_PLAY_MUSIC 45 | beq $v0, $t0, cmd_play_music 46 | b cmd_loop_latch 47 | 48 | /* spawn actor */ 49 | cmd_spawn_actor: 50 | la $t0, notif_ctxt 51 | la $t1, NOTIF_CTXT_NONOTIF 52 | sw $t1, 0x0000($t0) /* disable notifications */ 53 | lw $a2, 0x0040($sp) 54 | addiu $a0, $a2, 0x1C24 55 | move $a1, $v1 56 | jal z64_SpawnActorIndirect 57 | sw $v0, 0x0004($s1) 58 | la $t0, notif_ctxt 59 | sw $zero, 0x0000($t0) /* enable notifications */ 60 | b cmd_loop_latch 61 | 62 | /* update button */ 63 | cmd_update_button: 64 | lw $a0, 0x0040($sp) 65 | move $a1, $v1 66 | jal z64_UpdateButtonIcon 67 | sw $zero, 0x0004($s1) 68 | b cmd_loop_latch 69 | 70 | /* play sound */ 71 | cmd_play_sound: 72 | addiu $a1, $sp, 0x0020 73 | addiu $a3, $sp, 0x0024 74 | la $t0, 0x3F800000 75 | sw $zero, 0x0000($a1) 76 | sw $t0, 0x0000($a3) 77 | sw $a3, 0x0010($sp) 78 | sw $a1, 0x0014($sp) 79 | la $a2, 0x04 80 | lw $a0, 0x0004($s1) 81 | jal z64_PlaySound 82 | sw $zero, 0x0004($s1) 83 | b cmd_loop_latch 84 | 85 | /* load object */ 86 | cmd_load_object: 87 | la $t0, z64_obj_ctxt 88 | la $t1, z64_object_table 89 | /* check that the object is not loaded already, or marked for loading */ 90 | subu $t2, $zero, $v1 91 | li $t3, 0x0000 92 | lbu $t4, 0x0008($t0) 93 | addiu $t5, $t0, 0x000C 94 | 0: 95 | beq $t3, $t4, 0f 96 | lh $t6, 0x0000($t5) 97 | beq $t6, $v1, 1f 98 | beq $t6, $t2, 1f 99 | addiu $t3, $t3, 0x0001 100 | addiu $t5, $t5, 0x0044 101 | b 0b 102 | 0: 103 | /* look up the object size */ 104 | sll $t6, $v1, 0x0003 105 | addu $t6, $t1, $t6 106 | lw $t7, 0x0000($t6) 107 | lw $t8, 0x0004($t6) 108 | subu $t6, $t8, $t7 109 | /* mark object for loading */ 110 | sh $t2, 0x0000($t5) 111 | sw $zero, 0x0008($t5) 112 | lw $t3, 0x0004($t5) 113 | addu $t3, $t3, $t6 114 | sw $t3, 0x0048($t5) 115 | /* increment object count */ 116 | addiu $t4, $t4, 0x0001 117 | sb $t4, 0x0008($t0) 118 | 1: 119 | b cmd_loop_latch 120 | 121 | /* warp */ 122 | cmd_warp: 123 | la $t0, z64_ctxt 124 | la $t1, z64_file 125 | la $t2, z64_state_ovl_tab 126 | sra $t3, $v1, 0x0010 127 | andi $t4, $v1, 0xFFFF 128 | sw $t3, 0x0000($t1) 129 | sh $t4, 0x000A($t1) 130 | lw $t3, (0x0030 * 3 + 0x0018)($t2) 131 | lw $t4, (0x0030 * 3 + 0x002C)($t2) 132 | sw $t3, 0x000C($t0) 133 | sw $t4, 0x0010($t0) 134 | sw $zero, 0x0098($t0) 135 | b cmd_loop_latch 136 | 137 | /* play music sequence on sequencer 0 */ 138 | cmd_play_music: 139 | la $t0, z64_afx_cmd_write_pos 140 | la $t1, z64_afx_cmd_buf 141 | lbu $t2, 0x0000($t0) 142 | sll $t3, $t2, 0x0003 143 | addu $t3, $t1, $t3 144 | la $t4, 0x82000000 145 | andi $t5, $v1, 0x00FF 146 | sll $t5, $t5, 0x0008 147 | or $t4, $t4, $t5 148 | sw $t4, 0x0000($t3) 149 | sw $zero, 0x0004($t3) 150 | addiu $t2, $t2, 0x0001 151 | sb $t2, 0x0000($t0) 152 | b cmd_loop_latch 153 | 154 | /* loop */ 155 | cmd_loop_latch: 156 | la $t0, COMMAND_BUF_LENGTH 157 | sw $zero, 0x0000($s1) 158 | addiu $s0, $s0, 0x0001 159 | addiu $s1, $s1, 0x0008 160 | bne $s0, $t0, cmd_loop_head 161 | 162 | /* execute context main */ 163 | lw $a0, 0x0040($sp) 164 | lw $t9, 0x0004($a0) 165 | jalr $t9 166 | 167 | /* return */ 168 | lw $ra, 0x0030($sp) 169 | lw $s0, 0x0034($sp) 170 | lw $s1, 0x0038($sp) 171 | addiu $sp, $sp, 0x0040 172 | jr $ra 173 | 174 | .end command_func 175 | -------------------------------------------------------------------------------- /plugins/localization/item_numbers.json: -------------------------------------------------------------------------------- 1 | { 2 | "0": "item_deku_stick", 3 | "1": "item_deku_nut", 4 | "2": "item_bomb", 5 | "3": "item_fairy_bow", 6 | "4": "item_fire_arrow", 7 | "5": "item_din_fire", 8 | "6": "item_fairy_slingshot", 9 | "7": "item_fairy_ocarina", 10 | "8": "item_ocarina_of_time", 11 | "9": "item_bombchu", 12 | "10": "item_hookshot", 13 | "11": "item_longshot", 14 | "12": "item_ice_arrow", 15 | "13": "item_farore_wind", 16 | "14": "item_boomerang", 17 | "15": "item_lens_of_truth", 18 | "16": "item_magic_bean", 19 | "17": "item_megaton_hammer", 20 | "18": "item_light_arrow", 21 | "19": "item_nayru_love", 22 | "20": "item_empty_bottle", 23 | "21": "item_red_potion", 24 | "22": "item_green_potion", 25 | "23": "item_blue_potion", 26 | "24": "item_bottled_fairy", 27 | "25": "item_fish", 28 | "26": "item_lon_lon_milk", 29 | "27": "item_ruto_letter", 30 | "28": "item_blue_fire", 31 | "29": "item_bug", 32 | "30": "item_big_poe", 33 | "31": "item_lon_lon_milk_half", 34 | "32": "item_poe", 35 | "33": "item_weird_egg", 36 | "34": "item_chicken", 37 | "35": "item_zelda_letter", 38 | "36": "item_keaton_mask", 39 | "37": "item_skull_mask", 40 | "38": "item_spooky_mask", 41 | "39": "item_bunny_hood", 42 | "40": "item_goron_mask", 43 | "41": "item_zora_mask", 44 | "42": "item_gerudo_mask", 45 | "43": "item_mask_of_truth", 46 | "44": "item_SOLD_OUT", 47 | "45": "item_pocket_egg", 48 | "46": "item_pocket_cucco", 49 | "47": "item_cojiro", 50 | "48": "item_odd_mushroom", 51 | "49": "item_odd_potion", 52 | "50": "item_poacher_saw", 53 | "51": "item_goron_sword_broken", 54 | "52": "item_prescription", 55 | "53": "item_eyeball_frog", 56 | "54": "item_eye_drops", 57 | "55": "item_claim_check", 58 | "56": "item_fairy_bow_and_fire_arrows", 59 | "57": "item_fairy_bow_and_ice_arrows", 60 | "58": "item_fairy_bow_and_light_arrows", 61 | "59": "item_kokiri_sword", 62 | "60": "item_master_sword", 63 | "61": "item_giant_knife_and_biggoron_sword", 64 | "62": "item_deku_shield", 65 | "63": "item_hylian_shield", 66 | "64": "item_mirror_shield", 67 | "65": "item_kokiri_tunic", 68 | "66": "item_goron_tunic", 69 | "67": "item_zora_tunic", 70 | "68": "item_kokiri_boots", 71 | "69": "item_iron_boots", 72 | "70": "item_hover_boots", 73 | "71": "item_bullet_bag_30", 74 | "72": "item_bullet_bag_40", 75 | "73": "item_bullet_bag_50", 76 | "74": "item_quiver_30", 77 | "75": "item_big_quiver_40", 78 | "76": "item_biggest_quiver_50", 79 | "77": "item_bomb_bag_20", 80 | "78": "item_big_bomb_bag_30", 81 | "79": "item_biggest_bomb_bag_40", 82 | "80": "item_goron_bracelet", 83 | "81": "item_silver_gauntlets", 84 | "82": "item_golden_gauntlets", 85 | "83": "item_silver_scale", 86 | "84": "item_golden_scale", 87 | "85": "item_giant_knife_broken", 88 | "86": "item_adult_wallet", 89 | "87": "item_giant_wallet", 90 | "88": "item_deku_seeds", 91 | "89": "item_fishing_pole", 92 | "90": "item_minuet_of_forest", 93 | "91": "item_bolero_of_fire", 94 | "92": "item_serenade_of_water", 95 | "93": "item_requiem_of_spirit", 96 | "94": "item_nocturne_of_shadow", 97 | "95": "item_prelude_of_light", 98 | "96": "item_zelda_lullaby", 99 | "97": "item_epona_song", 100 | "98": "item_saria_song", 101 | "99": "item_sun_song", 102 | "100": "item_song_of_time", 103 | "101": "item_song_of_storms", 104 | "102": "item_forest_medallion", 105 | "103": "item_fire_medallion", 106 | "104": "item_water_medallion", 107 | "105": "item_spirit_medallion", 108 | "106": "item_shadow_medallion", 109 | "107": "item_light_medallion", 110 | "108": "item_kokiri_emerald", 111 | "109": "item_goron_ruby", 112 | "110": "item_zora_sapphire", 113 | "111": "item_stone_of_agony", 114 | "112": "item_gerudo_card", 115 | "113": "item_gold_skulltula_token", 116 | "114": "item_heart_container", 117 | "115": "item_unknown", 118 | "116": "item_big_key", 119 | "117": "item_compass", 120 | "118": "item_dungeon_map", 121 | "119": "item_small_key", 122 | "120": "item_small_magic_jar", 123 | "121": "item_large_magic_jar", 124 | "122": "item_piece_of_heart", 125 | "123": "item_unknown", 126 | "124": "item_unknown", 127 | "125": "item_unknown", 128 | "126": "item_unknown", 129 | "127": "item_unknown", 130 | "128": "item_unknown", 131 | "129": "item_unknown", 132 | "130": "item_lon_lon_milk", 133 | "131": "item_recovery_heart", 134 | "132": "item_green_rupee", 135 | "133": "item_blue_rupee", 136 | "134": "item_red_rupee", 137 | "135": "item_purple_rupee", 138 | "136": "item_huge_rupee", 139 | "137": "item_unknown", 140 | "138": "item_deku_sticks_5", 141 | "139": "item_deku_sticks_10", 142 | "140": "item_deku_nuts_5", 143 | "141": "item_deku_nuts_10", 144 | "142": "item_bombs_5", 145 | "143": "item_bombs_10", 146 | "144": "item_bombs_20", 147 | "145": "item_bombs_30", 148 | "146": "item_arrows_5_or_10", 149 | "147": "item_arrows_10_or_30", 150 | "148": "item_arrows_30_or_50", 151 | "149": "item_deku_seeds_30", 152 | "150": "item_bombchu_5", 153 | "151": "item_bombchu_20", 154 | "152": "item_deku_stick_upgrade_20", 155 | "153": "item_deku_stick_upgrade_30", 156 | "154": "item_deku_nut_upgrade_30", 157 | "155": "item_deku_nut_upgrade_40", 158 | "255": "no_item" 159 | } -------------------------------------------------------------------------------- /src/OotConfig.js: -------------------------------------------------------------------------------- 1 | /* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | const hri = require('human-readable-ids').hri; 20 | const crypto = require('crypto'); 21 | const fs = require("fs"); 22 | 23 | // Config 24 | class Configuration { 25 | 26 | constructor() { 27 | this._my_uuid = ""; 28 | this.file = "./OotModLoader-config.json"; 29 | this.cfg = {}; 30 | if (fs.existsSync(this.file)) { 31 | this.cfg = JSON.parse(fs.readFileSync(this.file)); 32 | } else { 33 | this.cfg["SERVER"] = {}; 34 | this.cfg.SERVER["master_server_ip"] = "192.99.70.23"; 35 | this.cfg.SERVER["master_server_port"] = "8082"; 36 | this.cfg.SERVER["isMaster"] = false; 37 | this.cfg["CLIENT"] = {}; 38 | this.cfg.CLIENT["isClient"] = true; 39 | this.cfg.CLIENT["nickname"] = "Player"; 40 | this.cfg.CLIENT["game_room"] = hri.random(); 41 | this.cfg.CLIENT["game_password"] = ""; 42 | this.cfg.CLIENT["tunic_colors"] = { 43 | kokiri: "", 44 | goron: "", 45 | zora: "" 46 | }; 47 | this.cfg.CLIENT["patchFile"] = ""; 48 | fs.writeFileSync(this.file, JSON.stringify(this.cfg, null, 2)); 49 | } 50 | this._master_server_ip = this.cfg.SERVER.master_server_ip; 51 | this._master_server_port = this.cfg.SERVER.master_server_port; 52 | this._isMaster = this.cfg.SERVER.isMaster; 53 | this._isClient = this.cfg.CLIENT.isClient; 54 | this._nickname = this.cfg.CLIENT.nickname; 55 | this._GAME_ROOM = this.cfg.CLIENT.game_room; 56 | this._game_password = this.cfg.CLIENT.game_password; 57 | this._master_server_udp = 1; 58 | this._tunic_colors = this.cfg.CLIENT.tunic_colors; 59 | this._patchFile = this.cfg.CLIENT.patchFile; 60 | if (this._GAME_ROOM === "") { 61 | this._GAME_ROOM = hri.random(); 62 | this.save(); 63 | } 64 | } 65 | 66 | set master_server_udp(value) { 67 | this._master_server_udp = value; 68 | } 69 | 70 | get master_server_udp() { 71 | return this._master_server_udp; 72 | } 73 | 74 | get game_password() { 75 | return this._game_password; 76 | } 77 | 78 | set game_password(value) { 79 | this._game_password = value; 80 | } 81 | 82 | get my_uuid() { 83 | return this._my_uuid; 84 | } 85 | 86 | set my_uuid(value) { 87 | this._my_uuid = value; 88 | } 89 | 90 | get master_server_ip() { 91 | return this._master_server_ip; 92 | } 93 | 94 | set master_server_ip(value) { 95 | this._master_server_ip = value; 96 | } 97 | 98 | get master_server_port() { 99 | return this._master_server_port; 100 | } 101 | 102 | set master_server_port(value) { 103 | this._master_server_port = value; 104 | } 105 | 106 | get isMaster() { 107 | return this._isMaster; 108 | } 109 | 110 | set isMaster(value) { 111 | this._isMaster = value; 112 | } 113 | 114 | get isClient() { 115 | return this._isClient; 116 | } 117 | 118 | set isClient(value) { 119 | this._isClient = value; 120 | } 121 | 122 | get nickname() { 123 | return this._nickname; 124 | } 125 | 126 | set nickname(value) { 127 | this._nickname = value; 128 | } 129 | 130 | get GAME_ROOM() { 131 | return this._GAME_ROOM; 132 | } 133 | 134 | set GAME_ROOM(value) { 135 | this._GAME_ROOM = value; 136 | } 137 | 138 | get PatchFile(){ 139 | return this._patchFile; 140 | } 141 | 142 | get TunicColors() { 143 | return this._tunic_colors; 144 | } 145 | 146 | getPasswordHash() { 147 | return crypto.createHash('md5').update(this.game_password).digest("hex"); 148 | } 149 | 150 | save() { 151 | this.cfg.SERVER["master_server_ip"] = this._master_server_ip; 152 | this.cfg.SERVER["master_server_port"] = this._master_server_port; 153 | this.cfg.SERVER["isMaster"] = this._isMaster; 154 | this.cfg.CLIENT["isTracker"] = this._isTracker; 155 | this.cfg.CLIENT["isClient"] = this._isClient; 156 | this.cfg.CLIENT["nickname"] = this._nickname; 157 | this.cfg.CLIENT["game_room"] = this._GAME_ROOM; 158 | this.cfg.CLIENT["game_password"] = this._game_password; 159 | fs.writeFileSync(this.file, JSON.stringify(this.cfg, null, 2)); 160 | } 161 | } 162 | 163 | module.exports = new Configuration(); -------------------------------------------------------------------------------- /plugins/modules/templates/Pickupable.opm: -------------------------------------------------------------------------------- 1 | class Pickupable { 2 | constructor() { 3 | this.id = this.constructor.name; 4 | } 5 | 6 | template(parent, api, emulator, data) { 7 | if (data.hasOwnProperty("filter")) { 8 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size, data.filter); 9 | parent.api.computeActor(data.actor + "|" + data.offset2, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset2, data.readHandler2, data.size, data.filter); 10 | parent.api.computeActor(data.actor + "|" + data.offset3, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset3, data.readHandler3, data.size, data.filter); 11 | parent.api.computeActor(data.actor + "|" + data.offset4, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset4, data.readHandler4, data.size4, data.filter); 12 | } else { 13 | parent.api.computeActor(data.actor + "|" + data.offset, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset, data.readHandler, data.size); 14 | parent.api.computeActor(data.actor + "|" + data.offset2, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset2, data.readHandler2, data.size); 15 | parent.api.computeActor(data.actor + "|" + data.offset3, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset3, data.readHandler3, data.size); 16 | parent.api.computeActor(data.actor + "|" + data.offset4, data.actorid, parent.api.actorCategories[data.actorCategory], data.offset4, data.readHandler4, data.size4); 17 | } 18 | 19 | api.registerClientSidePacketHook(data.actor + "|" + data.offset, function (packet) { 20 | if (parent._forbidSync) { 21 | return false; 22 | } 23 | packet.addr = packet.data.hash; 24 | packet.offset = 0x130; 25 | packet.data = 0x00000000; 26 | packet.writeHandler = "actor_word"; 27 | return true; 28 | }); 29 | 30 | api.registerPacketTransformer(data.actor + "|" + data.offset, function (packet) { 31 | if (parent._forbidSync) { 32 | return false; 33 | } 34 | let copy = JSON.parse(JSON.stringify(packet)); 35 | copy["payload"]["offset"] = 0x134; 36 | emulator.sendViaSocket(copy.payload); 37 | return packet; 38 | }); 39 | 40 | api.registerClientSidePacketHook(data.actor + "|" + data.offset2, function (packet) { 41 | if (parent._forbidSync) { 42 | return false; 43 | } 44 | packet.addr = packet.data.hash; 45 | packet.offset = data.offset2; 46 | packet.data = packet.data.value; 47 | packet.writeHandler = data.writeHandler2; 48 | return true; 49 | }); 50 | 51 | api.registerPacketTransformer(data.actor + "|" + data.offset2, function (packet) { 52 | if (parent._forbidSync) { 53 | return false; 54 | } 55 | let copy = JSON.parse(JSON.stringify(packet)); 56 | copy["payload"]["offset"] = 0x08; 57 | emulator.sendViaSocket(copy.payload); 58 | return packet; 59 | }); 60 | 61 | api.registerClientSidePacketHook(data.actor + "|" + data.offset3, function (packet) { 62 | if (parent._forbidSync) { 63 | return false; 64 | } 65 | packet.addr = packet.data.hash; 66 | if (data.hasOwnProperty("write_offset3")) { 67 | packet.offset = data.write_offset3; 68 | } else { 69 | packet.offset = data.offset3; 70 | } 71 | if (data.hasOwnProperty("value3")) { 72 | packet.data = data.value3; 73 | } else { 74 | packet.data = packet.data.value; 75 | } 76 | packet.writeHandler = data.writeHandler3; 77 | return true; 78 | }); 79 | 80 | api.registerPacketTransformer(data.actor + "|" + data.offset3, function (packet) { 81 | if (parent._forbidSync) { 82 | return false; 83 | } 84 | return packet; 85 | }); 86 | 87 | api.registerClientSidePacketHook(data.actor + "|" + data.offset4, function (packet) { 88 | if (parent._forbidSync) { 89 | return false; 90 | } 91 | packet.addr = packet.data.hash; 92 | if (data.hasOwnProperty("write_offset4")) { 93 | packet.offset = data.write_offset4; 94 | } else { 95 | packet.offset = data.offset4; 96 | } 97 | if (data.hasOwnProperty("value4")) { 98 | packet.data = data.value4; 99 | } else { 100 | packet.data = packet.data.value; 101 | } 102 | packet.writeHandler = data.writeHandler4; 103 | return true; 104 | }); 105 | 106 | api.registerPacketTransformer(data.actor + "|" + data.offset4, function (packet) { 107 | if (parent._forbidSync) { 108 | return false; 109 | } 110 | return packet; 111 | }); 112 | } 113 | } 114 | 115 | module.exports = new Pickupable(); -------------------------------------------------------------------------------- /src/for_emulator/Lua/OotUtils.lua: -------------------------------------------------------------------------------- 1 | --[[/* 2 | OotModLoader - Adding networking functions and mod loading capability to Ocarina of Time. 3 | Copyright (C) 2019 Team Ooto 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */]]-- 18 | 19 | function toBits(num) 20 | -- returns a table of bits, most significant first. 21 | bits = 8; 22 | local t = {} -- will contain the bits 23 | for b = bits, 1, -1 do 24 | t[b] = math.fmod(num, 2) 25 | num = math.floor((num - t[b]) / 2) 26 | end 27 | return t 28 | end 29 | 30 | function fromBits(b) 31 | local binary = tonumber(table.concat(b)); 32 | if (binary == nil) then 33 | return 0; 34 | end 35 | local bin = string.reverse(binary) 36 | local sum = 0 37 | local num; 38 | for i = 1, string.len(bin) do 39 | num = string.sub(bin, i, i) == "1" and 1 or 0 40 | sum = sum + num * math.pow(2, i - 1) 41 | end 42 | return sum; 43 | end 44 | 45 | function DEC_HEX(IN) 46 | return "0x" .. bizstring.hex(IN); 47 | end 48 | 49 | function serializeDumpStraight(d) 50 | local save_me = {}; 51 | for k, v in pairs(d) do 52 | save_me[k + 1] = v; 53 | end 54 | return save_me 55 | end 56 | 57 | function serializeDumpStraight_asBinaryHex(d) 58 | local save_me = {}; 59 | for k, v in pairs(d) do 60 | save_me[DEC_HEX(k)] = toBits(v); 61 | end 62 | return save_me 63 | end 64 | 65 | function reverseDumpStraight_asBinaryHex(base, data) 66 | local t = {}; 67 | for k, v in pairs(data) do 68 | t[base + tonumber(k)] = fromBits(v); 69 | end 70 | return t; 71 | end 72 | 73 | function serializeDumpStraight_asBinary(d) 74 | local save_me = {}; 75 | for k, v in pairs(d) do 76 | save_me[k + 1] = toBits(v); 77 | end 78 | return save_me 79 | end 80 | 81 | function reverseDumpStraight_asBinary(base, data) 82 | local t = {}; 83 | for k, v in pairs(data) do 84 | t[base + (tonumber(k) - 1)] = fromBits(v); 85 | end 86 | return t; 87 | end 88 | 89 | function reverseDumpStraight(base, data) 90 | local t = {}; 91 | for k, v in pairs(data) do 92 | t[base + (tonumber(k) - 1)] = v; 93 | end 94 | return t; 95 | end 96 | 97 | function equals(o1, o2, ignore_mt) 98 | if o1 == o2 then return true end 99 | local o1Type = type(o1) 100 | local o2Type = type(o2) 101 | if o1Type ~= o2Type then return false end 102 | if o1Type ~= 'table' then return false end 103 | 104 | if not ignore_mt then 105 | local mt1 = getmetatable(o1) 106 | if mt1 and mt1.__eq then 107 | --compare using built in method 108 | return o1 == o2 109 | end 110 | end 111 | 112 | local keySet = {} 113 | 114 | for key1, value1 in pairs(o1) do 115 | local value2 = o2[key1] 116 | if value2 == nil or equals(value1, value2, ignore_mt) == false then 117 | return false 118 | end 119 | keySet[key1] = true 120 | end 121 | 122 | for key2, _ in pairs(o2) do 123 | if not keySet[key2] then return false end 124 | end 125 | return true 126 | end 127 | 128 | function hashRange(addr, size) 129 | return memory.hash_region(addr, size); 130 | end 131 | 132 | function readTwoByteUnsigned(addr) 133 | return memory.read_u16_be(addr); 134 | end 135 | 136 | function writeTwoByteUnsigned(addr, value) 137 | memory.write_u16_be(addr, value); 138 | end 139 | 140 | function readByte(addr) 141 | return memory.readbyte(addr); 142 | end 143 | 144 | function readByteAsBinary(addr) 145 | return toBits(readByte(addr)); 146 | end 147 | 148 | function writeByte(addr, value) 149 | memory.writebyte(addr, value); 150 | end 151 | 152 | function writeByteAsBinary(addr, value) 153 | writeByte(addr, fromBits(value)); 154 | end 155 | 156 | function readFourBytesUnsigned(addr) 157 | return memory.read_u32_be(addr); 158 | end 159 | 160 | function writeFourBytesUnsigned(addr, value) 161 | return memory.write_u32_be(addr, value); 162 | end 163 | 164 | function readByteRange(base, size) 165 | return serializeDumpStraight(memory.readbyterange(base, size)); 166 | end 167 | 168 | function readByteRange_asBinary(base, size) 169 | return serializeDumpStraight_asBinary(memory.readbyterange(base, size)); 170 | end 171 | 172 | function writeByteRange_asBinary(base, data) 173 | memory.writebyterange(reverseDumpStraight_asBinary(base, data)); 174 | end 175 | 176 | function readByteRange_asBinaryHex(base, size) 177 | return serializeDumpStraight_asBinaryHex(memory.readbyterange(base, size)); 178 | end 179 | 180 | function writeByteRange_asBinaryHex(base, data) 181 | memory.writebyterange(reverseDumpStraight_asBinaryHex(base, data)); 182 | end 183 | 184 | function writeByteRange(base, data) 185 | memory.writebyterange(reverseDumpStraight(base, data)); 186 | end 187 | 188 | function readPointer(base) 189 | return memory.read_u32_be(base) - 0x80000000; 190 | end 191 | 192 | function readRomByte(addr) 193 | return memory.readbyte(addr, "ROM"); 194 | end 195 | 196 | function drawSprite(path, sx, sy, sw, sh, x, y) 197 | gui.drawImageRegion(path, sx, sy, sw, sh, x, y); 198 | end --------------------------------------------------------------------------------