├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cli └── main.c ├── common ├── base32.c ├── base32.h ├── build.h ├── challenge.c ├── challenge.h ├── chaos.c ├── chaos.h ├── chests.c ├── chests.h ├── crc64.c ├── crc64.h ├── credit_music.c ├── credit_music.h ├── dungeon_maps.c ├── dungeon_maps.h ├── dwr.c ├── dwr.h ├── dwr_types.h ├── expansion.c ├── expansion.h ├── map.c ├── map.h ├── mt19937-64.c ├── mt64.h ├── patch.c ├── patch.h ├── polyfit.c ├── polyfit.h ├── sprites.c ├── sprites.h ├── stair_shuffle.c └── stair_shuffle.h ├── compile_commands.json ├── electron ├── .gitignore ├── base32.js ├── build │ ├── icon.ico │ └── icons │ │ ├── icon_1024x1024.png │ │ ├── icon_128x128.png │ │ ├── icon_16x16.png │ │ ├── icon_256x256.png │ │ ├── icon_32x32.png │ │ ├── icon_512x512.png │ │ └── icon_64x64.png ├── dwrandomizer.js ├── dwrandomizer.wasm ├── index.css ├── index.html ├── index.js ├── interface.js ├── logo.png ├── main.js ├── modal.js ├── package.json ├── preload.js ├── renderer.js └── sprites ├── expansion ├── bank_0.asm ├── bank_3_patch.asm ├── bank_7.asm ├── base.asm ├── build.sh ├── chr_rom.chr ├── credits.asm ├── defs.asm ├── empty.asm ├── exp_bank_3.asm ├── exp_bank_4.asm ├── exp_bank_5.asm ├── famistudio_asm6.asm ├── famistudio_conf.asm └── music │ ├── 1943.fms │ ├── batman.fms │ ├── bloody_tears.fms │ ├── bubble_man.fms │ ├── danger_and_determination.fms │ ├── flash_man.fms │ ├── gimmick_2A03.fms │ ├── guardian_legend.fms │ ├── journey_to_silius.fms │ ├── moving_forward.fms │ ├── ninja_gaiden.fms │ ├── on_the_hunt.fms │ ├── shadow_of_the_ninja.fms │ ├── shatterhand.fms │ ├── shovel_knight_2A03.fms │ ├── silver_surfer.fms │ ├── tecmo_world_wrestling.fms │ ├── the_end.fms │ └── wood_man.fms ├── hud.lua ├── notes ├── enemy_data.txt ├── free_space.txt ├── items.txt ├── maps.txt ├── music.txt ├── ram.txt ├── rom.txt ├── sprites.txt └── warps.txt ├── release.sh ├── resources └── dwrandomizer.desktop ├── tools ├── build_expansion.py ├── build_music.py ├── curve_data │ ├── mon_agi.txt │ ├── mon_dodge.txt │ ├── mon_gold.txt │ ├── mon_hp.txt │ ├── mon_hr.txt │ ├── mon_sleep.txt │ ├── mon_stop.txt │ ├── mon_str.txt │ ├── mon_xp.txt │ ├── player_agi.txt │ ├── player_hp.txt │ ├── player_mp.txt │ ├── player_str.txt │ ├── player_xp.txt │ ├── vanilla_stats.txt │ └── weapons.txt ├── ips.py ├── patchgen.py └── polyfit.py └── webui ├── base32.js ├── index.css ├── index.html ├── index.js ├── interface.js ├── logo.png ├── modal.js └── sprites ├── Arkista's Ring Christine.png ├── Barry Sanders.png ├── Blaster Master Jason.png ├── Blinky.png ├── Bo Jackson.png ├── Bomberman.png ├── Clyde.png ├── DW2 Prince of Cannock.png ├── DW2 Prince of Midenhall.png ├── DW2 Princess of Moonbrooke.png ├── DW3 Female Fighter.png ├── DW3 Female Goof-off.png ├── DW3 Female Merchant.png ├── DW3 Female Pilgrim.png ├── DW3 Female Sage.png ├── DW3 Female Soldier.png ├── DW3 Female Wizard.png ├── DW3 Ghost.png ├── DW3 Hero.png ├── DW3 Male Fighter.png ├── DW3 Male Goof-off.png ├── DW3 Male Merchant.png ├── DW3 Male Pilgrim.png ├── DW3 Male Sage.png ├── DW3 Male Soldier.png ├── DW3 Male Wizard.png ├── DW4 Alena.png ├── DW4 Brey.png ├── DW4 Celia.png ├── DW4 Cristo.png ├── DW4 Doran.png ├── DW4 Healie.png ├── DW4 Hero.png ├── DW4 Heroine.png ├── DW4 Mara.png ├── DW4 Nara.png ├── DW4 Ragnar.png ├── DW4 Taloon.png ├── DW4 Tov (The Dog).png ├── DW4 Yeti.png ├── DoaE Guan Yu.png ├── DoaE Huang Zhong.png ├── DoaE Jiang Wei.png ├── DoaE Lu Bu.png ├── DoaE Ma Chao.png ├── DoaE Zhang Fei.png ├── DoaE Zhao Yun.png ├── DoaE Zhuge Liang.png ├── Dragonlord.png ├── FF Black Belt.png ├── FF Black Mage.png ├── FF Black Wizard.png ├── FF Fighter.png ├── FF Knight.png ├── FF Master.png ├── FF Ninja.png ├── FF Red Mage.png ├── FF Red Wizard.png ├── FF Thief.png ├── FF White Mage.png ├── FF White Wizard.png ├── FF4 DK Cecil.png ├── FF4 Edge.png ├── Gwaelin.png ├── Inky.png ├── Jerry Rice.png ├── Kirby.png ├── Lala.png ├── Link.png ├── Lolo.png ├── Loto.png ├── Luigi.png ├── Mario.png ├── Metal Slime.png ├── Mina the Hollower.png ├── Ms. Pac-Man.png ├── Pac-Man.png ├── Pinky.png ├── Plumplim.png ├── Random.png ├── Red Slime.png ├── Slime.png ├── StarTropics Mike.png ├── Sue.png ├── Waluigi.png ├── Wario.png └── Yoshi.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.nes 3 | *.ips 4 | *.zip 5 | *.exe 6 | *.o 7 | .vim 8 | map.html 9 | report.py 10 | .idea 11 | sdcard 12 | dwrandomizer 13 | cmake_install.cmake 14 | CMakeCache.txt 15 | Makefile 16 | cli-build/ 17 | build/ 18 | builds/ 19 | __pycache__ 20 | CMakeFiles 21 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This is the cmake build file for the project. This works on Linux, but 2 | # not Windows, so I will be using qmake instead. Keeping this around for 3 | # a bit, just in case. 4 | 5 | cmake_minimum_required(VERSION 3.7) 6 | project(dwrandomizer) 7 | 8 | set(CMAKE_CXX_STANDARD 11) 9 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 10 | if (DEBUG) 11 | set(CMAKE_BUILD_TYPE Debug) 12 | endif() 13 | 14 | # file(GLOB music_files "${CMAKE_SOURCE_DIR}/expansion/music/*.txt") 15 | # foreach(music_file IN ITEMS ${music_files}) 16 | # if(${music_file} IS_NEWER_THAN "${CMAKE_SOURCE_DIR}/common/credits_music.c") 17 | # message("${music_file} has changed, Rebuilding music file...") 18 | # execute_process(COMMAND "${CMAKE_SOURCE_DIR}/tools/build_music.py") 19 | # break() 20 | # endif() 21 | # endforeach() 22 | # 23 | # file(GLOB asm_files "${CMAKE_SOURCE_DIR}/expansion/*.asm") 24 | # foreach(asm_file IN ITEMS ${asm_files}) 25 | # if(${asm_file} IS_NEWER_THAN "${CMAKE_SOURCE_DIR}/common/expansion.c") 26 | # message("${asm_file} has changed, Rebuilding expansion file...") 27 | # execute_process(COMMAND "${CMAKE_SOURCE_DIR}/tools/build_expansion.py") 28 | # break() 29 | # endif() 30 | # endforeach() 31 | 32 | # Compile the command line version 33 | include_directories(common) 34 | 35 | set(SOURCE_FILES 36 | common/crc64.c 37 | common/sprites.c 38 | common/dwr.c 39 | common/map.c 40 | common/dungeon_maps.c 41 | common/stair_shuffle.c 42 | common/chests.c 43 | common/expansion.c 44 | common/mt19937-64.c 45 | common/chaos.c 46 | common/patch.c 47 | common/challenge.c 48 | common/polyfit.c 49 | common/base32.c 50 | common/credit_music.c) 51 | 52 | if (ALPHA) 53 | add_definitions(-DDWR_ALPHA) 54 | elseif(RELEASE) 55 | add_definitions(-DDWR_RELEASE) 56 | endif() 57 | if (CLEAR_UNUSED) 58 | add_definitions(-DCLEAR_ALL_UNUSED_DATA) 59 | endif() 60 | 61 | # emscripten build command (Archlinux) 62 | # cmake -DCMAKE_TOOLCHAIN_FILE=/usr/lib/emscripten/cmake/Modules/Platform/Emscripten.cmake .. 63 | # emscripten build command (Ubuntu/Pop) 64 | # cmake -DCMAKE_TOOLCHAIN_FILE=/usr/share/emscripten/cmake/Modules/Platform/Emscripten.cmake .. 65 | if (EMSCRIPTEN) 66 | add_executable(dwrandomizer ${SOURCE_FILES}) 67 | target_link_libraries(dwrandomizer m) 68 | target_link_options(dwrandomizer PRIVATE 69 | "SHELL: 70 | -s EXPORTED_FUNCTIONS='_dwr_randomize,_sprite_name,_version' 71 | -s EXPORTED_RUNTIME_METHODS='ccall,cwrap' 72 | -s WASM_BIGINT") 73 | file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/release/) 74 | file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/release/) 75 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/index.html ${CMAKE_BINARY_DIR}/release/index.html) 76 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/logo.png ${CMAKE_BINARY_DIR}/release/logo.png) 77 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/index.js ${CMAKE_BINARY_DIR}/release/index.js) 78 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/index.css ${CMAKE_BINARY_DIR}/release/index.css) 79 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/base32.js ${CMAKE_BINARY_DIR}/release/base32.js) 80 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/interface.js ${CMAKE_BINARY_DIR}/release/interface.js) 81 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/modal.js ${CMAKE_BINARY_DIR}/release/modal.js) 82 | file(CREATE_LINK ${CMAKE_SOURCE_DIR}/webui/sprites ${CMAKE_BINARY_DIR}/release/sprites SYMBOLIC) 83 | add_custom_command(TARGET dwrandomizer POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/dwrandomizer.js ${CMAKE_BINARY_DIR}/release/) 84 | add_custom_command(TARGET dwrandomizer POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/dwrandomizer.wasm ${CMAKE_BINARY_DIR}/release/) 85 | else() 86 | add_executable(dwrandomizer cli/main.c ${SOURCE_FILES}) 87 | target_link_libraries(dwrandomizer m) 88 | endif() 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2024 Thomas McGrew 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /cli/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "dwr.h" 8 | #include "dwr_types.h" 9 | #include "map.h" 10 | #include "sprites.h" 11 | 12 | 13 | static void print_usage(const char *command, char *default_flags) 14 | { 15 | size_t i; 16 | 17 | printf("Usage %s [flags [seed [sprite]]] \n", command); 18 | printf("\n"); 19 | printf("A randomizer for Dragon Warrior for NES\n"); 20 | printf("\n"); 21 | printf("\n"); 22 | printf("If flags are not specified, the flags \"%s\" will be used\n", 23 | default_flags); 24 | printf("If the seed is not specified, a random seed will be chosen\n"); 25 | printf("\n"); 26 | printf("Sprite should be one of: "); 27 | for(i=0; i < sprite_count(); i++) { 28 | if (i) { 29 | printf(", %s", dwr_sprite_names[i]); 30 | } else { 31 | printf("%s", dwr_sprite_names[i]); 32 | } 33 | } 34 | printf("\n"); 35 | } 36 | 37 | int main(int argc, char **argv) 38 | { 39 | uint64_t seed; 40 | const char *sprite; 41 | char *flags; 42 | char default_flags[] = DEFAULT_FLAGS; 43 | char *input_file, *output_dir; 44 | 45 | printf("DWRandomizer version %s\n", VERSION); 46 | if (argc < 3) { 47 | print_usage(argv[0], default_flags); 48 | exit(0); 49 | } 50 | 51 | input_file = argv[1]; 52 | output_dir = argv[argc-1]; 53 | if (argc >= 4) { 54 | flags = argv[2]; 55 | } else { 56 | flags = default_flags; 57 | } 58 | if (argc < 5 || sscanf(argv[3], "%"PRIu64, &seed) != 1) { 59 | srand(time(NULL)); 60 | seed = ((uint64_t)rand() << 32) | ((uint64_t)rand() & 0xffffffffL); 61 | } 62 | if (argc > 5) { 63 | sprite = argv[4]; 64 | } else { 65 | sprite = "Random"; 66 | } 67 | 68 | printf("Randomizing using seed: %"PRIu64" with flags %s\n", seed, flags); 69 | 70 | dwr_randomize(input_file, seed, flags, sprite, output_dir); 71 | 72 | return 0; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /common/base32.c: -------------------------------------------------------------------------------- 1 | /** 2 | * base32 (de)coder implementation as specified by RFC4648. 3 | * 4 | * Copyright (c) 2010 Adrien Kunysz 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | **/ 24 | 25 | #include // assert() 26 | #include // CHAR_BIT 27 | 28 | #include "base32.h" 29 | 30 | /** 31 | * Let this be a sequence of plain data before encoding: 32 | * 33 | * 01234567 01234567 01234567 01234567 01234567 34 | * +--------+--------+--------+--------+--------+ 35 | * |< 0 >< 1| >< 2 ><|.3 >< 4.|>< 5 ><.|6 >< 7 >| 36 | * +--------+--------+--------+--------+--------+ 37 | * 38 | * There are 5 octets of 8 bits each in each sequence. 39 | * There are 8 blocks of 5 bits each in each sequence. 40 | * 41 | * You probably want to refer to that graph when reading the algorithms in this 42 | * file. We use "octet" instead of "byte" intentionnaly as we really work with 43 | * 8 bits quantities. This implementation will probably not work properly on 44 | * systems that don't have exactly 8 bits per (unsigned) char. 45 | **/ 46 | 47 | static size_t min(size_t x, size_t y) 48 | { 49 | return x < y ? x : y; 50 | } 51 | 52 | static const unsigned char PADDING_CHAR = '='; 53 | 54 | /** 55 | * Pad the given buffer with len padding characters. 56 | */ 57 | static void pad(unsigned char *buf, int len) 58 | { 59 | for (int i = 0; i < len; i++) 60 | buf[i] = PADDING_CHAR; 61 | } 62 | 63 | /** 64 | * This convert a 5 bits value into a base32 character. 65 | * Only the 5 least significant bits are used. 66 | */ 67 | static unsigned char encode_char(unsigned char c) 68 | { 69 | static unsigned char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 70 | return base32[c & 0x1F]; // 0001 1111 71 | } 72 | 73 | /** 74 | * Decode given character into a 5 bits value. 75 | * Returns -1 iff the argument given was an invalid base32 character 76 | * or a padding character. 77 | */ 78 | static int decode_char(unsigned char c) 79 | { 80 | char retval = -1; 81 | 82 | if (c >= 'A' && c <= 'Z') 83 | retval = c - 'A'; 84 | if (c >= '2' && c <= '7') 85 | retval = c - '2' + 26; 86 | 87 | assert(retval == -1 || ((retval & 0x1F) == retval)); 88 | 89 | return retval; 90 | } 91 | 92 | /** 93 | * Given a block id between 0 and 7 inclusive, this will return the index of 94 | * the octet in which this block starts. For example, given 3 it will return 1 95 | * because block 3 starts in octet 1: 96 | * 97 | * +--------+--------+ 98 | * | ......<|.3 >....| 99 | * +--------+--------+ 100 | * octet 1 | octet 2 101 | */ 102 | static int get_octet(int block) 103 | { 104 | assert(block >= 0 && block < 8); 105 | return (block*5) / 8; 106 | } 107 | 108 | /** 109 | * Given a block id between 0 and 7 inclusive, this will return how many bits 110 | * we can drop at the end of the octet in which this block starts. 111 | * For example, given block 0 it will return 3 because there are 3 bits 112 | * we don't care about at the end: 113 | * 114 | * +--------+- 115 | * |< 0 >...| 116 | * +--------+- 117 | * 118 | * Given block 1, it will return -2 because there 119 | * are actually two bits missing to have a complete block: 120 | * 121 | * +--------+- 122 | * |.....< 1|.. 123 | * +--------+- 124 | **/ 125 | static int get_offset(int block) 126 | { 127 | assert(block >= 0 && block < 8); 128 | return (8 - 5 - (5*block) % 8); 129 | } 130 | 131 | /** 132 | * Like "b >> offset" but it will do the right thing with negative offset. 133 | * We need this as bitwise shifting by a negative offset is undefined 134 | * behavior. 135 | */ 136 | static unsigned char shift_right(unsigned char byte, char offset) 137 | { 138 | if (offset > 0) 139 | return byte >> offset; 140 | else 141 | return byte << -offset; 142 | } 143 | 144 | static unsigned char shift_left(unsigned char byte, char offset) 145 | { 146 | return shift_right(byte, - offset); 147 | } 148 | 149 | /** 150 | * Encode a sequence. A sequence is no longer than 5 octets by definition. 151 | * Thus passing a length greater than 5 to this function is an error. Encoding 152 | * sequences shorter than 5 octets is supported and padding will be added to the 153 | * output as per the specification. 154 | */ 155 | static void encode_sequence(const unsigned char *plain, int len, unsigned char *coded) 156 | { 157 | assert(CHAR_BIT == 8); // not sure this would work otherwise 158 | assert(len >= 0 && len <= 5); 159 | 160 | for (int block = 0; block < 8; block++) { 161 | int octet = get_octet(block); // figure out which octet this block starts in 162 | int junk = get_offset(block); // how many bits do we drop from this octet? 163 | 164 | if (octet >= len) { // we hit the end of the buffer 165 | pad(&coded[block], 8 - block); 166 | return; 167 | } 168 | 169 | unsigned char c = shift_right(plain[octet], junk); // first part 170 | 171 | if (junk < 0 // is there a second part? 172 | && octet < len - 1) // is there still something to read? 173 | { 174 | c |= shift_right(plain[octet+1], 8 + junk); 175 | } 176 | coded[block] = encode_char(c); 177 | } 178 | } 179 | 180 | void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded) 181 | { 182 | // All the hard work is done in encode_sequence(), 183 | // here we just need to feed it the data sequence by sequence. 184 | for (size_t i = 0, j = 0; i < len; i += 5, j += 8) { 185 | encode_sequence(&plain[i], min(len - i, 5), &coded[j]); 186 | } 187 | } 188 | 189 | static int decode_sequence(const unsigned char *coded, unsigned char *plain) 190 | { 191 | assert(CHAR_BIT == 8); 192 | assert(coded && plain); 193 | 194 | plain[0] = 0; 195 | for (int block = 0; block < 8; block++) { 196 | int offset = get_offset(block); 197 | int octet = get_octet(block); 198 | 199 | int c = decode_char(coded[block]); 200 | if (c < 0) // invalid char, stop here 201 | return octet; 202 | 203 | plain[octet] |= shift_left(c, offset); 204 | if (offset < 0) { // does this block overflows to next octet? 205 | assert(octet < 4); 206 | plain[octet+1] = shift_left(c, 8 + offset); 207 | } 208 | } 209 | return 5; 210 | } 211 | 212 | size_t base32_decode(const unsigned char *coded, unsigned char *plain) 213 | { 214 | size_t written = 0; 215 | for (size_t i = 0, j = 0; ; i += 8, j += 5) { 216 | int n = decode_sequence(&coded[i], &plain[j]); 217 | written += n; 218 | if (n < 5) 219 | return written; 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /common/base32.h: -------------------------------------------------------------------------------- 1 | /** 2 | * base32 (de)coder implementation as specified by RFC4648. 3 | * 4 | * Copyright (c) 2010 Adrien Kunysz 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | **/ 24 | 25 | #ifndef __BASE32_H_ 26 | #define __BASE32_H_ 27 | 28 | #include // size_t 29 | 30 | /** 31 | * Returns the length of the output buffer required to encode len bytes of 32 | * data into base32. This is a macro to allow users to define buffer size at 33 | * compilation time. 34 | */ 35 | #define BASE32_LEN(len) (((len)/5)*8 + ((len) % 5 ? 8 : 0)) 36 | 37 | /** 38 | * Returns the length of the output buffer required to decode a base32 string 39 | * of len characters. Please note that len must be a multiple of 8 as per 40 | * definition of a base32 string. This is a macro to allow users to define 41 | * buffer size at compilation time. 42 | */ 43 | #define UNBASE32_LEN(len) (((len)/8)*5) 44 | 45 | /** 46 | * Encode the data pointed to by plain into base32 and store the 47 | * result at the address pointed to by coded. The "coded" argument 48 | * must point to a location that has enough available space 49 | * to store the whole coded string. The resulting string will only 50 | * contain characters from the [A-Z2-7=] set. The "len" arguments 51 | * define how many bytes will be read from the "plain" buffer. 52 | **/ 53 | void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded); 54 | 55 | /** 56 | * Decode the null terminated string pointed to by coded and write 57 | * the decoded data into the location pointed to by plain. The 58 | * "plain" argument must point to a location that has enough available 59 | * space to store the whole decoded string. 60 | * Returns the length of the decoded string. This may be less than 61 | * expected due to padding. If an invalid base32 character is found 62 | * in the coded string, decoding will stop at that point. 63 | **/ 64 | size_t base32_decode(const unsigned char *coded, unsigned char *plain); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /common/build.h: -------------------------------------------------------------------------------- 1 | /* This file is generated by git */ 2 | #define BUILD "698" 3 | -------------------------------------------------------------------------------- /common/challenge.h: -------------------------------------------------------------------------------- 1 | #ifndef DWRANDOMIZER_CHALLENGE_H 2 | #define DWRANDOMIZER_CHALLENGE_H 3 | 4 | #include "dwr_types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void invisible_hero(dw_rom *rom); 11 | void invisible_npcs(dw_rom *rom); 12 | void no_numbers(dw_rom *rom); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif //DWRANDOMIZER_CHALLENGE_H 19 | -------------------------------------------------------------------------------- /common/chaos.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mcgrew on 7/29/17. 3 | // 4 | 5 | #ifndef DWRANDOMIZER_CHAOS_H 6 | #define DWRANDOMIZER_CHAOS_H 7 | 8 | #include "dwr_types.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void chaos_mode(dw_rom *rom); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif //DWRANDOMIZER_CHAOS_H 21 | -------------------------------------------------------------------------------- /common/chests.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _CHESTS_H_ 3 | #define _CHESTS_H_ 4 | 5 | #include "dwr_types.h" 6 | 7 | void do_chest_flags(dw_rom *rom); 8 | void check_quest_items(dw_rom *rom); 9 | BOOL is_quest_item(uint8_t item); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /common/crc64.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _CRC64_H_ 3 | #define _CRC64_H_ 4 | 5 | 6 | uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l); 7 | 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /common/credit_music.h: -------------------------------------------------------------------------------- 1 | /** This file is generated by build_music.py */ 2 | 3 | #ifndef _CREDIT_MUSIC_H 4 | #define _CREDIT_MUSIC_H 5 | 6 | #include 7 | #include 8 | #include "dwr_types.h" 9 | 10 | struct music_data { 11 | const uint8_t *start; 12 | const size_t size; 13 | }; 14 | 15 | void add_music(dw_rom* rom, int track); 16 | const extern size_t track_count; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /common/dungeon_maps.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef _DUNGEON_MAPS_H_ 4 | #define _DUNGEON_MAPS_H_ 5 | 6 | #include "dwr_types.h" 7 | 8 | void rotate_dungeons(dw_rom *rom); 9 | void set_dungeon_tile(dw_rom *rom, dw_map_index town, uint8_t x, 10 | uint8_t y, uint8_t tile); 11 | dw_dungeon_tile get_dungeon_tile(dw_rom *rom, dw_map_index town, uint8_t x, 12 | uint8_t y); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /common/dwr.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _DWR_H_ 3 | #define _DWR_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "build.h" 10 | #include "dwr_types.h" 11 | 12 | #define DWR_VERSION "3.0.3" 13 | 14 | #ifdef DWR_RELEASE 15 | #define VERSION DWR_VERSION 16 | #elif DWR_ALPHA 17 | #define VERSION DWR_VERSION " alpha " BUILD 18 | #else 19 | #define VERSION DWR_VERSION " beta " BUILD 20 | #endif 21 | 22 | #define DEFAULT_FLAGS "IVIAAVCAKACAAAAAAAAAAEAA" 23 | #define CHEST_COUNT 31 24 | 25 | #define SHUFFLE_CHESTS(x) (x->flags[ 0] & 0xc0) 26 | #define RANDOM_CHEST_LOCATIONS(x) (x->flags[ 0] & 0x30) 27 | #define RANDOMIZE_GROWTH(x) (x->flags[ 0] & 0x0c) 28 | #define RANDOM_MAP(x) (x->flags[ 0] & 0x03) 29 | #define RANDOMIZE_SPELLS(x) (x->flags[ 1] & 0xc0) 30 | #define RANDOMIZE_SHOPS(x) (x->flags[ 1] & 0x30) 31 | #define RANDOM_PRICES(x) (x->flags[ 1] & 0x0c) 32 | #define RANDOM_XP_REQS(x) (x->flags[ 1] & 0x03) 33 | #define HEAL_HURT_B4_MORE(x) (x->flags[ 2] & 0xc0) 34 | #define STAIR_SHUFFLE(x) (x->flags[ 2] & 0x0c) 35 | 36 | #define MENU_WRAP(x) (x->flags[ 3] & 0xc0) 37 | #define DEATH_NECKLACE(x) (x->flags[ 3] & 0x30) 38 | #define TORCH_IN_BATTLE(x) (x->flags[ 3] & 0x0c) 39 | #define REPEL_IN_DUNGEONS(x) (x->flags[ 4] & 0xc0) 40 | #define PERMANENT_REPEL(x) (x->flags[ 4] & 0x30) 41 | #define PERMANENT_TORCH(x) (x->flags[ 4] & 0x0c) 42 | #define ALTERNATE_RUNNING(x) (x->flags[ 4] & 0x03) 43 | 44 | #define RANDOMIZE_PATTERNS(x) (x->flags[ 5] & 0xc0) 45 | #define RANDOMIZE_ZONES(x) (x->flags[ 5] & 0x30) 46 | #define RANDOM_ENEMY_STATS(x) (x->flags[ 5] & 0x0c) 47 | #define RANDOM_ENEMY_DROPS(x) (x->flags[ 5] & 0x03) 48 | #define CONSISTENT_STATS(x) (x->flags[ 6] & 0xc0) 49 | #define SCARED_SLIMES(x) (x->flags[ 6] & 0x30) 50 | #define SCALED_SLIMES(x) (x->flags[ 6] & 0x0c) 51 | 52 | #define FAST_TEXT(x) (x->flags[ 7] & 0xc0) 53 | #define SPEED_HACKS(x) (x->flags[ 7] & 0x30) 54 | #define OPEN_CHARLOCK(x) (x->flags[ 7] & 0x0c) 55 | #define SHORT_CHARLOCK(x) (x->flags[ 7] & 0x03) 56 | #define NO_KEYS(x) (x->flags[ 8] & 0xc0) 57 | #define SUMMER_SALE(x) (x->flags[13] & 0x0c) 58 | #define FAST_XP(x) (x->flags[13] & 0x10) 59 | #define VERY_FAST_XP(x) (x->flags[13] & 0x20) 60 | #define SMALL_MAP(x) (x->flags[13] & 0x40) 61 | #define VERY_SMALL_MAP(x) (x->flags[13] & 0x80) 62 | #define RANDOM_MAP_SIZE(x) (x->flags[13] & 0xc0) 63 | 64 | #define NO_HURTMORE(x) (x->flags[ 9] & 0xc0) 65 | #define NO_NUMBERS(x) (x->flags[ 9] & 0x30) 66 | #define INVISIBLE_HERO(x) (x->flags[ 9] & 0x0c) 67 | #define INVISIBLE_NPCS(x) (x->flags[ 9] & 0x03) 68 | #define TREASURE_GUARDS(x) (x->flags[13] & 0x03) 69 | #define BIG_SWAMP(x) (x->flags[10] & 0x03) 70 | #define ROTATE_DUNGEONS(x) (x->flags[10] & 0x0c) 71 | #define NO_ARMOR_IN_CHARLOCK(x) (x->flags[10] & 0x30) 72 | #define EASY_CHARLOCK(x) (x->flags[10] & 0xc0) 73 | 74 | #define CURSED_PRINCESS(x) (x->flags[ 8] & 0x0c) 75 | #define THREES_COMPANY(x) (x->flags[ 8] & 0x03) 76 | 77 | #define MODERN_SPELLS(x) (x->flags[11] & 0xc0) 78 | #define NOIR_MODE(x) (x->flags[11] & 0x30) 79 | #define RANDOMIZE_MUSIC(x) (x->flags[14] & 0x80) 80 | #define DISABLE_MUSIC(x) (x->flags[14] & 0x40) 81 | #define NO_SCREEN_FLASH(x) (x->flags[14] & 0x20) 82 | #define DEATH_COUNTER(x) (x->flags[14] & 0x10) 83 | #define CUSTOM_SPELLS(x) (x->flags[14] & 0x08) 84 | #define SKIP_VANILLA_CREDITS(x) (x->flags[14] & 0x04) 85 | 86 | #ifdef __cplusplus 87 | extern "C" { 88 | #endif 89 | 90 | /** 91 | * Randomizes a Dragon Warrior rom file 92 | * 93 | * @param input_file The name of the input file 94 | * @param seed The seed number to use for the random number generator 95 | * @param flags The flags to use for randomization options 96 | * @param output_dir The directory to write the new file to 97 | * @return A checksum for the new rom. This checksum is taken before certain 98 | * options which don't affect gameplay. 99 | */ 100 | uint64_t dwr_randomize(const char* input_file, uint64_t seed, char *flags, 101 | const char *sprite_name, const char* output_dir); 102 | uint16_t set_text(dw_rom *rom, const size_t address, char *text); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | #endif 108 | 109 | -------------------------------------------------------------------------------- /common/dwr_types.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _DWR_TYPES_H_ 3 | #define _DWR_TYPES_H_ 4 | 5 | #include 6 | 7 | #define ROM_SIZE 81936 8 | 9 | #define ABS(x) ((x < 0) ? -x : x) 10 | #define MAX(x,y) ((x > y) ? x : y) 11 | #define MIN(x,y) ((x < y) ? x : y) 12 | 13 | typedef enum { 14 | FALSE, 15 | TRUE, 16 | } BOOL; 17 | 18 | /** In-game indexes for various maps. */ 19 | typedef enum { 20 | NO_MAP, 21 | OVERWORLD, 22 | CHARLOCK, 23 | HAUKSNESS, 24 | TANTEGEL, 25 | TANTEGEL_THRONE_ROOM, /* 5 */ 26 | CHARLOCK_THRONE_ROOM, 27 | KOL, 28 | BRECCONARY, 29 | GARINHAM, 30 | CANTLIN, /* 10 */ 31 | RIMULDAR, 32 | TANTEGEL_BASEMENT, 33 | NORTHERN_SHRINE, 34 | SOUTHERN_SHRINE, 35 | CHARLOCK_CAVE_1, /* 15 */ 36 | CHARLOCK_CAVE_2, 37 | CHARLOCK_CAVE_3, 38 | CHARLOCK_CAVE_4, 39 | CHARLOCK_CAVE_5, 40 | CHARLOCK_CAVE_6, /* 20 */ 41 | SWAMP_CAVE, 42 | MOUNTAIN_CAVE, 43 | MOUNTAIN_CAVE_2, 44 | GARINS_GRAVE_1, 45 | GARINS_GRAVE_2, /* 25 */ 46 | GARINS_GRAVE_3, 47 | GARINS_GRAVE_4, 48 | ERDRICKS_CAVE, 49 | ERDRICKS_CAVE_2 50 | } dw_map_index; 51 | 52 | typedef enum { 53 | TOWN_TILE_GRASS, /* 0 */ 54 | TOWN_TILE_DESERT, 55 | TOWN_TILE_WATER, 56 | TOWN_TILE_CHEST, 57 | TOWN_TILE_BLOCK, 58 | TOWN_TILE_STAIRS_UP, /* 5 */ 59 | TOWN_TILE_BRICK, 60 | TOWN_TILE_STAIRS_DOWN, 61 | TOWN_TILE_TREES, 62 | TOWN_TILE_SWAMP, 63 | TOWN_TILE_BARRIER, /* 10 */ 64 | TOWN_TILE_DOOR, 65 | TOWN_TILE_WPN_SIGN, 66 | TOWN_TILE_INN_SIGN, 67 | TOWN_TILE_BRIDGE, 68 | TOWN_TILE_COUNTER, /* 15 */ 69 | } dw_town_tile; 70 | 71 | typedef enum { 72 | DUNGEON_TILE_BLOCK, /* 0 */ 73 | DUNGEON_TILE_STAIRS_UP, 74 | DUNGEON_TILE_BRICK, 75 | DUNGEON_TILE_STAIRS_DOWN, 76 | DUNGEON_TILE_CHEST, 77 | DUNGEON_TILE_DOOR, /* 5 */ 78 | DUNGEON_TILE_GWAELIN, 79 | DUNGEON_TILE_BLACK, 80 | } dw_dungeon_tile; 81 | 82 | typedef enum { 83 | HEAL, 84 | HURT, 85 | SLEEP, 86 | RADIANT, 87 | STOPSPELL, 88 | OUTSIDE, 89 | RETURN, 90 | REPEL, 91 | HEALMORE, 92 | HURTMORE 93 | } dw_spells; 94 | 95 | /** In-game enemy indexes */ 96 | typedef enum { 97 | SLIME, /* 0 */ 98 | RED_SLIME, 99 | DRAKEE, 100 | GHOST, 101 | MAGICIAN, 102 | MAGIDRAKEE, /* 5 */ 103 | SCORPION, 104 | DRUIN, 105 | POLTERGEIST, 106 | DROLL, 107 | DRAKEEMA, /* 10 */ 108 | SKELETON, 109 | WARLOCK, 110 | METAL_SCORPION, 111 | WOLF, 112 | WRAITH, /* 15 */ 113 | METAL_SLIME, 114 | SPECTER, 115 | WOLFLORD, 116 | DRUINLORD, 117 | DROLLMAGI, /* 20 */ 118 | WYVERN, 119 | ROGUE_SCORPION, 120 | WRAITH_KNIGHT, 121 | GOLEM, 122 | GOLDMAN, /* 25 */ 123 | KNIGHT, 124 | MAGIWYVERN, 125 | DEMON_KNIGHT, 126 | WEREWOLF, 127 | GREEN_DRAGON,/* 30 */ 128 | STARWYVERN, 129 | WIZARD, 130 | AXE_KNIGHT, 131 | BLUE_DRAGON, 132 | STONEMAN, /* 35 */ 133 | ARMORED_KNIGHT, 134 | RED_DRAGON, 135 | DRAGONLORD_1, 136 | DRAGONLORD_2 137 | } dw_enemies; 138 | 139 | typedef enum { 140 | MOVE2_00_PERCENT = 0x00, 141 | MOVE2_25_PERCENT = 0x01, 142 | MOVE2_50_PERCENT = 0x02, 143 | MOVE2_75_PERCENT = 0x03, 144 | MOVE2_HURT = 0x00, 145 | MOVE2_HURTMORE = 0x04, 146 | MOVE2_FIRE = 0x08, 147 | MOVE2_FIRE2 = 0x0c, 148 | MOVE1_00_PERCENT = 0x00, 149 | MOVE1_25_PERCENT = 0x10, 150 | MOVE1_50_PERCENT = 0x20, 151 | MOVE1_75_PERCENT = 0x30, 152 | MOVE1_SLEEP = 0x00, 153 | MOVE1_STOPSPELL = 0x40, 154 | MOVE1_HEAL = 0x80, 155 | MOVE1_HEALMORE = 0xc0, 156 | } dw_enemy_pattern; 157 | 158 | /** In-game indexes for chest content items */ 159 | typedef enum { 160 | ARMOR = 1, 161 | HERB, 162 | KEY, 163 | TORCH, 164 | FAIRY_WATER, /* 5 */ 165 | WINGS, 166 | DRAGON_SCALE, 167 | FLUTE, 168 | RING, 169 | TOKEN, /* 10 */ 170 | GWAELINS_LOVE, 171 | CURSED_BELT, 172 | HARP, 173 | NECKLACE, 174 | STONES, /* 15 */ 175 | STAFF, 176 | SWORD, 177 | GOLD 178 | } dw_chest_content; 179 | 180 | /** In-game indexes for weapon shop items */ 181 | typedef enum { 182 | BAMBOO_POLE, 183 | CLUB, 184 | COPPER_SWORD, 185 | HAND_AXE, 186 | BROAD_SWORD, 187 | FLAME_SWORD, 188 | ERDRICKS_SWORD, 189 | CLOTHES, 190 | LEATHER_ARMOR, 191 | CHAIN_MAIL, 192 | HALF_PLATE, 193 | FULL_PLATE, 194 | MAGIC_ARMOR, 195 | ERDRICKS_ARMOR, 196 | SMALL_SHIELD, 197 | LARGE_SHIELD, 198 | SILVER_SHIELD, 199 | SHOP_HERB, 200 | SHOP_TORCH = 0x13, 201 | SHOP_WINGS = 0x15, 202 | SHOP_DRAGON_SCALE, 203 | SHOP_END = 0xfd, 204 | } dw_shop_item; 205 | 206 | /** Calculation code for Gwaelin's Love */ 207 | typedef struct { 208 | uint8_t y; 209 | uint8_t code[27]; 210 | uint8_t x; 211 | } dw_love_calc; 212 | 213 | /** Table for the 3 "search" items in the game (not including the trap door) */ 214 | typedef struct { 215 | uint8_t map[3]; 216 | uint8_t x[3]; 217 | uint8_t y[3]; 218 | uint8_t item[3]; 219 | } dwr_search_table; 220 | 221 | /** A single in-game chest */ 222 | typedef struct { 223 | uint8_t map; 224 | uint8_t x; 225 | uint8_t y; 226 | uint8_t item; 227 | } dw_chest; 228 | 229 | /** Statistics for an in-game enemy */ 230 | typedef struct __attribute__((packed)) { 231 | uint8_t str; 232 | uint8_t agi; 233 | uint8_t hp; 234 | uint8_t pattern; 235 | uint8_t s_ss_resist; /* sleep/stopspell resist */ 236 | uint8_t hr_dodge; /* hurt resist/dodge */ 237 | uint16_t xp; /* These are 1 byte in the original game, but there is */ 238 | uint16_t gold; /* Unused space so we're supporting 2 bytes */ 239 | /* The rest of this is 6 bytes of unused space in the original game. */ 240 | float rank; 241 | uint16_t index; 242 | } dw_enemy; 243 | 244 | /** Statistics for a single player level */ 245 | typedef struct { 246 | uint8_t str; 247 | uint8_t agi; 248 | uint8_t hp; 249 | uint8_t mp; 250 | uint16_t spells; 251 | } dw_stats; 252 | 253 | /** In-game map metadata */ 254 | typedef struct { 255 | uint8_t pointer[2]; /* if we use uint16_t here it causes memalign issues */ 256 | uint8_t width; /* This causes the struct to be size 6 instead of 5, */ 257 | uint8_t height; /* which breaks things */ 258 | uint8_t border; 259 | } dw_map_meta; 260 | 261 | /** In-game warps for stairs and towns */ 262 | typedef struct { 263 | uint8_t map; 264 | uint8_t x; 265 | uint8_t y; 266 | } dw_warp; 267 | 268 | /** Code for the return spell and wings */ 269 | typedef struct { 270 | uint8_t map; 271 | uint8_t code1[3]; 272 | uint8_t x; 273 | uint8_t code2[7]; 274 | uint8_t y; 275 | 276 | } dw_return_point; 277 | 278 | /** Code for usage of the rainbow drop */ 279 | typedef struct { 280 | uint8_t code1[3]; 281 | uint8_t map; 282 | uint8_t code2[5]; 283 | uint8_t x; 284 | uint8_t code3[5]; 285 | uint8_t y; 286 | } dw_rainbow_drop; 287 | 288 | typedef struct { 289 | uint8_t map[8]; 290 | uint8_t x[8]; 291 | uint8_t y[8]; 292 | uint8_t flags[8]; 293 | uint8_t monster[8]; 294 | } dwr_spike_table; 295 | 296 | 297 | /** A struct for the in-game map */ 298 | typedef struct { 299 | uint16_t *pointers; 300 | uint8_t *encoded; 301 | uint8_t *flags; 302 | int size; 303 | dw_map_meta *meta; 304 | dw_warp *warps_from; 305 | dw_warp *warps_to; 306 | dw_love_calc *love_calc; 307 | dw_return_point *return_point; 308 | dw_rainbow_drop *rainbow_drop; 309 | dw_rainbow_drop *rainbow_bridge; 310 | uint8_t tiles[120][120]; 311 | uint8_t walkable[120][120]; 312 | uint8_t *chest_access; 313 | uint8_t key_access; 314 | } dw_map; 315 | 316 | /** A struct for the rom data */ 317 | typedef struct { 318 | uint8_t *header; 319 | uint8_t *content; 320 | uint8_t *expansion; 321 | unsigned char flags_encoded[25]; 322 | uint8_t flags[15]; 323 | uint8_t chest_access[31]; 324 | uint64_t seed; 325 | dw_map map; 326 | dw_stats *stats; 327 | uint8_t *mp_reqs; 328 | uint16_t *xp_reqs; 329 | dw_enemy *enemies; 330 | uint8_t *zones; 331 | uint8_t *zone_layout; 332 | dw_chest *chests; 333 | dwr_spike_table *spike_table; 334 | dwr_search_table *search_table; 335 | uint8_t *repel_table; 336 | uint8_t *weapon_shops; 337 | uint16_t *weapon_prices; 338 | uint16_t *weapon_price_display; 339 | uint8_t *music; 340 | uint8_t *title_text; 341 | } dw_rom; 342 | 343 | #endif 344 | 345 | -------------------------------------------------------------------------------- /common/expansion.h: -------------------------------------------------------------------------------- 1 | /** This file is generated by build_expansion.py */ 2 | #ifndef _EXPANSION_H_ 3 | #define _EXPANSION_H_ 4 | 5 | #include "dwr_types.h" 6 | 7 | enum hooktype { 8 | DIALOGUE, 9 | JSR = 0x20, 10 | JMP = 0x4c, 11 | }; 12 | 13 | enum subroutine { 14 | BLOCKED_IN_FRONT = 0xC2D5, 15 | COUNT_ENCOUNTER = 0xC30A, 16 | COUNT_FRAME = 0xC3DD, 17 | COUNT_SPELL_USE = 0xC31D, 18 | COUNT_WIN = 0xC315, 19 | CURSED_PRINCESS_CHECK = 0xC390, 20 | DISPLAY_DEATHS = 0xC3BC, 21 | EXEC_EXPANSION_SUB = 0xC2E7, 22 | INC_ATTACK_CTR = 0xC29E, 23 | INC_BONK_CTR = 0xC2C3, 24 | INC_CRIT_CTR = 0xC2A8, 25 | INC_DEATH_CTR = 0xC2CC, 26 | INC_DODGE_CTR = 0xC2BA, 27 | INC_ENEMY_DEATH_CTR = 0xC303, 28 | INC_MISS_CTR = 0xC2B1, 29 | INIT_SAVE_RAM = 0xC3B2, 30 | MODIFY_RUN_RATE = 0xC412, 31 | PLAYER_AMBUSHED = 0xC2DF, 32 | SCARED_SLIMES = 0xC3A5, 33 | SNAPSHOT_TIMER = 0xC404, 34 | SORT_INVENTORY = 0xC325, 35 | START_DWR_CREDITS = 0xC29A, 36 | STORE_PRINCESS_ITEM = 0xC38B, 37 | THREES_COMPANY_CHECK = 0xC379, 38 | TORCH_IN_BATTLE = 0xC331, 39 | }; 40 | 41 | void add_hook(dw_rom *rom, enum hooktype type, uint16_t address, 42 | enum subroutine to_addr); 43 | void bank_3_patch(dw_rom *rom); 44 | void fill_expansion(dw_rom *rom); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /common/map.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef _MAP_H_ 4 | #define _MAP_H_ 5 | 6 | #include 7 | 8 | #include "dwr_types.h" 9 | #include "dwr.h" 10 | 11 | /** Map tile indexes */ 12 | typedef enum { 13 | TILE_NOTSWAMP = -2, 14 | TILE_NONE = -1, 15 | TILE_GRASS = 0x0, 16 | TILE_DESERT = 0x1, 17 | TILE_HILL = 0x2, 18 | TILE_MOUNTAIN = 0x3, 19 | TILE_WATER = 0x4, 20 | TILE_BLOCK = 0x5, 21 | TILE_TREES = 0x6, 22 | TILE_SWAMP = 0x7, 23 | TILE_TOWN = 0x8, 24 | TILE_CAVE = 0x9, 25 | TILE_CASTLE = 0xa, 26 | TILE_BRIDGE = 0xb, 27 | TILE_STAIRS = 0xc 28 | } dw_tile; 29 | 30 | /** Town border tile indexes */ 31 | typedef enum { 32 | BORDER_GRASS = 0x0, 33 | BORDER_DESERT = 0x1, 34 | BORDER_HILL = 0x2, 35 | BORDER_BRICK = 0x4, 36 | BORDER_SWAMP = 0x6, 37 | BORDER_TREES = 0xb, 38 | BORDER_WATER = 0xf, 39 | BORDER_BLOCK = 0x10, 40 | BORDER_MOUNTAIN = 0x12, 41 | } dw_border_tile; 42 | 43 | /** Warp indices */ 44 | typedef enum { 45 | WARP_GARINHAM, 46 | WARP_STAFF_SHRINE, 47 | WARP_KOL, 48 | WARP_BRECCONARY, 49 | WARP_TANTEGEL, 50 | WARP_SWAMP_NORTH, /* 5 */ 51 | WARP_CHARLOCK, 52 | WARP_SWAMP_SOUTH, 53 | WARP_MOUNTAIN_CAVE, 54 | WARP_RIMULDAR, 55 | WARP_HAUKSNESS, /* 10 */ 56 | WARP_CANTLIN, 57 | WARP_JERK_CAVE, 58 | WARP_ERDRICKS_CAVE, 59 | WARP_CHARLOCK_SURFACE_1, 60 | WARP_CHARLOCK_SURFACE_2, /* 15 */ 61 | WARP_CHARLOCK_SURFACE_3, 62 | WARP_TANTEGEL_BASEMENT, 63 | WARP_GARINS_GRAVE = 19, 64 | WARP_CHARLOCK_CHEST = 21, 65 | WARP_CHARLOCK_POINTLESS_1 = 24, 66 | WARP_CHARLOCK_POINTLESS_2 = 25, 67 | WARP_CHARLOCK_THRONE = 38, 68 | WARP_MOUNTAIN_CAVE_POINTLESS = 39, 69 | WARP_GARINS_GRAVE_POINTLESS = 45 70 | } dw_warp_index; 71 | 72 | enum { 73 | KEY_IN_TABLET = 0x01, 74 | KEY_IN_MOUNTAIN = 0x02, 75 | KEY_IN_GRAVE = 0x04, 76 | KEY_IN_BASEMENT = 0x10, 77 | }; 78 | 79 | #ifdef __cplusplus 80 | extern "C" { 81 | #endif 82 | 83 | /** 84 | * Decodes the in-game map into a 2 dimentional array of tiles 85 | * 86 | * @param map The map struct 87 | */ 88 | void map_decode(dw_map *map); 89 | 90 | /** 91 | * Generates a new in-game map. 92 | * 93 | * @param rom The rom struct 94 | * @return A boolean indicating whether terrain generation was successful or not 95 | */ 96 | void map_generate_terrain(dw_rom *rom); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | #endif 102 | 103 | 104 | -------------------------------------------------------------------------------- /common/mt19937-64.c: -------------------------------------------------------------------------------- 1 | /* 2 | A C-program for MT19937-64 (2014/2/23 version). 3 | Coded by Takuji Nishimura and Makoto Matsumoto. 4 | 5 | Modified for use here by mcgrew. 6 | 7 | This is a 64-bit version of Mersenne Twister pseudorandom number 8 | generator. 9 | 10 | Before using, initialize the state by using mt_init(seed) 11 | or init_by_array64(init_key, key_length). 12 | 13 | Copyright (C) 2004, 2014, Makoto Matsumoto and Takuji Nishimura, 14 | All rights reserved. 15 | 16 | Redistribution and use in source and binary forms, with or without 17 | modification, are permitted provided that the following conditions 18 | are met: 19 | 20 | 1. Redistributions of source code must retain the above copyright 21 | notice, this list of conditions and the following disclaimer. 22 | 23 | 2. Redistributions in binary form must reproduce the above copyright 24 | notice, this list of conditions and the following disclaimer in the 25 | documentation and/or other materials provided with the distribution. 26 | 27 | 3. The names of its contributors may not be used to endorse or promote 28 | products derived from this software without specific prior written 29 | permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 35 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 36 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 37 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 38 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 39 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | 43 | References: 44 | T. Nishimura, ``Tables of 64-bit Mersenne Twisters'' 45 | ACM Transactions on Modeling and 46 | Computer Simulation 10. (2000) 348--357. 47 | M. Matsumoto and T. Nishimura, 48 | ``Mersenne Twister: a 623-dimensionally equidistributed 49 | uniform pseudorandom number generator'' 50 | ACM Transactions on Modeling and 51 | Computer Simulation 8. (Jan. 1998) 3--30. 52 | 53 | Any feedback is very welcome. 54 | http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html 55 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces) 56 | */ 57 | 58 | 59 | #include 60 | #include 61 | 62 | #include "mt64.h" 63 | 64 | #define NN 312 65 | #define MM 156 66 | #define MATRIX_A UINT64_C(0xB5026F5AA96619E9) 67 | #define UM UINT64_C(0xFFFFFFFF80000000) /* Most significant 33 bits */ 68 | #define LM UINT64_C(0x7FFFFFFF) /* Least significant 31 bits */ 69 | 70 | 71 | /* The array for the state vector */ 72 | static uint64_t mt[NN]; 73 | /* mti==NN+1 means mt[NN] is not initialized */ 74 | static int mti=NN+1; 75 | 76 | /* initializes mt[NN] with a seed */ 77 | void mt_init(uint64_t seed) 78 | { 79 | mt[0] = seed; 80 | for (mti=1; mti> 62)) + mti); 83 | } 84 | } 85 | 86 | 87 | /* generates a random number on [0, 2^64-1]-interval */ 88 | static uint64_t genrand64_int64() 89 | { 90 | int i; 91 | uint64_t x; 92 | static uint64_t mag01[2]={UINT64_C(0), MATRIX_A}; 93 | 94 | if (mti >= NN) { /* generate NN words at one time */ 95 | 96 | /* if mt_init() has not been called, */ 97 | /* a default initial seed is used */ 98 | if (mti == NN+1) 99 | mt_init(UINT64_C(5489)); 100 | 101 | for (i=0;i>1) ^ mag01[(int)(x&UINT64_C(1))]; 104 | } 105 | for (;i>1) ^ mag01[(int)(x&UINT64_C(1))]; 108 | } 109 | x = (mt[NN-1]&UM)|(mt[0]&LM); 110 | mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))]; 111 | 112 | mti = 0; 113 | } 114 | 115 | x = mt[mti++]; 116 | 117 | x ^= (x >> 29) & UINT64_C(0x5555555555555555); 118 | x ^= (x << 17) & UINT64_C(0x71D67FFFEDA60000); 119 | x ^= (x << 37) & UINT64_C(0xFFF7EEE000000000); 120 | x ^= (x >> 43); 121 | 122 | return x; 123 | } 124 | 125 | uint64_t mt_rand(uint64_t min, uint64_t max) 126 | { 127 | if (min >= max) return min; 128 | 129 | return min + (genrand64_int64() % (max - min + 1)); 130 | } 131 | 132 | uint64_t mt_rand64() 133 | { 134 | return genrand64_int64(); 135 | } 136 | 137 | double mt_rand_double() 138 | { 139 | return (genrand64_int64() >> 11) * (1.0/9007199254740992.0); 140 | } 141 | 142 | double mt_rand_double_ranged(double min, double max) 143 | { 144 | return (genrand64_int64() >> 11) * (1.0/9007199254740992.0) * 145 | (max - min) + min; 146 | } 147 | 148 | 149 | int mt_rand_bool() 150 | { 151 | return genrand64_int64() & 0x1; 152 | } 153 | 154 | void mt_shuffle(void *array, size_t n, size_t size) 155 | { 156 | char tmp[size]; 157 | char *arr = array; 158 | size_t i,j, stride = size * sizeof(char); 159 | 160 | if (n > 1) { 161 | for (i = 0; i < n - 1; ++i) { 162 | j = mt_rand(i, n-1); 163 | 164 | memcpy(tmp, arr + j * stride, size); 165 | memcpy(arr + j * stride, arr + i * stride, size); 166 | memcpy(arr + i * stride, tmp, size); 167 | } 168 | } 169 | } 170 | 171 | -------------------------------------------------------------------------------- /common/mt64.h: -------------------------------------------------------------------------------- 1 | /* 2 | A C-program for MT19937-64 (2014/2/23 version). 3 | Coded by Takuji Nishimura and Makoto Matsumoto. 4 | 5 | This is a 64-bit version of Mersenne Twister pseudorandom number 6 | generator. 7 | 8 | Before using, initialize the state by using init_genrand64(seed) 9 | or init_by_array64(init_key, key_length). 10 | 11 | Copyright (C) 2004, 2014, Makoto Matsumoto and Takuji Nishimura, 12 | All rights reserved. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions 16 | are met: 17 | 18 | 1. Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 21 | 2. Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in the 23 | documentation and/or other materials provided with the distribution. 24 | 25 | 3. The names of its contributors may not be used to endorse or promote 26 | products derived from this software without specific prior written 27 | permission. 28 | 29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 33 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 34 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 35 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 36 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 37 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 38 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 39 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 | 41 | References: 42 | T. Nishimura, ``Tables of 64-bit Mersenne Twisters'' 43 | ACM Transactions on Modeling and 44 | Computer Simulation 10. (2000) 348--357. 45 | M. Matsumoto and T. Nishimura, 46 | ``Mersenne Twister: a 623-dimensionally equidistributed 47 | uniform pseudorandom number generator'' 48 | ACM Transactions on Modeling and 49 | Computer Simulation 8. (Jan. 1998) 3--30. 50 | 51 | Any feedback is very welcome. 52 | http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html 53 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces) 54 | */ 55 | 56 | #ifndef _MT64_H_ 57 | #define _MT64_H_ 58 | 59 | #include 60 | #include 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | void mt_init(uint64_t seed); 67 | 68 | uint64_t mt_rand(uint64_t min, uint64_t max); 69 | 70 | uint64_t mt_rand64(); 71 | 72 | int mt_rand_bool(); 73 | 74 | double mt_rand_double(); 75 | 76 | double mt_rand_double_ranged(double min, double max); 77 | 78 | void mt_shuffle(void *array, size_t n, size_t size); 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /common/patch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "dwr_types.h" 5 | 6 | /** 7 | * Patches the rom at the specified address with the specified bytes. 8 | * 9 | * @param rom The rom struct to be patched 10 | * @param address The address inside the rom to apply the patch. 11 | * @param size The size of the patch 12 | * @param ... A series of uint8_t bytes, the patch data 13 | * @return The address of the end of the patch 14 | */ 15 | uint16_t vpatch(const dw_rom *rom, const uint32_t address, const uint32_t size, 16 | ...) 17 | { 18 | uint32_t i; 19 | va_list arg; 20 | uint8_t *p; 21 | 22 | p = &rom->content[address]; 23 | va_start(arg, size); 24 | 25 | for (i=0; i < size; i++) { 26 | *(p++) = va_arg(arg, int); 27 | } 28 | va_end(arg); 29 | return p - rom->content; 30 | } 31 | 32 | /** 33 | * Patches the rom at the specified address with the specified bytes. 34 | * 35 | * @param rom The rom struct to be patched 36 | * @param address The address inside the rom to apply the patch 37 | * @param size The size of the patch 38 | * @param data An array of bytes to use for the patch. 39 | * @return The address of the end of the patch 40 | */ 41 | uint16_t patch(const dw_rom *rom, uint32_t address, const uint32_t size, 42 | const uint8_t *data) 43 | { 44 | uint32_t i; 45 | uint8_t *p; 46 | 47 | p = &rom->content[address]; 48 | 49 | for (i=0; i < size; i++) { 50 | *(p++) = data[i]; 51 | } 52 | return p - rom->content; 53 | } 54 | 55 | /** 56 | * Patches the data at the specified pointer 57 | * 58 | * @param p A pointer to the rom data to be patched 59 | * @param size The size of the patch 60 | * @param data An array of bytes to use for the patch. 61 | * @return A pointer to the end of the patch 62 | */ 63 | uint8_t *ppatch(uint8_t *p, const uint32_t size, const uint8_t *data) 64 | { 65 | uint32_t i; 66 | 67 | for (i=0; i < size; i++) { 68 | *(p++) = data[i]; 69 | } 70 | return p; 71 | } 72 | 73 | /** 74 | * Patches the data at the specified pointer 75 | * 76 | * @param p A pointer to the rom data to be patched 77 | * @param size The size of the patch. 78 | * @param ... A series of uint8_t bytes to be used for the patchj 79 | * @return A pointer to the end of the patch 80 | */ 81 | uint8_t *pvpatch(uint8_t *p, const uint32_t size, ...) 82 | { 83 | uint32_t i; 84 | va_list arg; 85 | 86 | va_start(arg, size); 87 | 88 | for (i=0; i < size; i++) { 89 | *(p++) = va_arg(arg, int); 90 | } 91 | va_end(arg); 92 | return p; 93 | 94 | } 95 | -------------------------------------------------------------------------------- /common/patch.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DWRANDOMIZER_PATCH_H 3 | #define DWRANDOMIZER_PATCH_H 4 | 5 | #include 6 | 7 | #include "dwr_types.h" 8 | 9 | /** 10 | * Patches the rom at the specified address with the specified bytes. 11 | * 12 | * @param rom The rom struct to be patched 13 | * @param address The address inside the rom to apply the patch. 14 | * @param size The size of the patch 15 | * @param ... A series of uint8_t bytes, the patch data 16 | * @return The address of the end of the patch 17 | */ 18 | uint16_t vpatch(const dw_rom *rom, const uint32_t address, const uint32_t size, 19 | ...); 20 | /** 21 | * Patches the rom at the specified address with the specified bytes. 22 | * 23 | * @param rom The rom struct to be patched 24 | * @param address The address inside the rom to apply the patch 25 | * @param size The size of the patch 26 | * @param data An array of bytes to use for the patch. 27 | * @return The address of the end of the patch 28 | */ 29 | uint16_t patch(const dw_rom *rom, const uint32_t address, const uint32_t size, 30 | const uint8_t *data); 31 | 32 | /** 33 | * Patches the data at the specified pointer 34 | * 35 | * @param p A pointer to the rom data to be patched 36 | * @param size The size of the patch 37 | * @param data An array of bytes to use for the patch. 38 | * @return A pointer to the end of the patch 39 | */ 40 | uint8_t *ppatch(uint8_t *p, const uint32_t size, const uint8_t *data); 41 | 42 | /** 43 | * Patches the data at the specified pointer 44 | * 45 | * @param p A pointer to the rom data to be patched 46 | * @param size The size of the patch. 47 | * @param ... A series of uint8_t bytes to be used for the patchj 48 | * @return A pointer to the end of the patch 49 | */ 50 | uint8_t *pvpatch(uint8_t *p, const uint32_t size, ...); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /common/polyfit.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "dwr_types.h" 7 | #include "polyfit.h" 8 | 9 | const polyfactors mon_hp_fac = { /* monster HP */ 10 | 3, 11 | 255, 12 | -9.963841777001374, 13 | 8.454464882934817, 14 | -1.3030567173494914, 15 | 0.10287367249259728, 16 | -0.0035005800831845774, 17 | 4.2935341320271974e-05, 18 | 0.0, 19 | 0.0, 20 | 0.0, 21 | 0.0, 22 | 0.0, 23 | 0.0, 24 | 0.0, 25 | 0.0, 26 | }; 27 | 28 | const polyfactors mon_str_fac = { /* monster strength */ 29 | 5, 30 | 255, 31 | -17.122064777331587, 32 | 16.827828360192285, 33 | -2.967672859575701, 34 | 0.225529906099072, 35 | -0.00709399951981401, 36 | 7.884633642164365e-05, 37 | 0.0, 38 | 0.0, 39 | 0.0, 40 | 0.0, 41 | 0.0, 42 | 0.0, 43 | 0.0, 44 | 0.0, 45 | }; 46 | 47 | const polyfactors mon_agi_fac = { /* monster agility */ 48 | 3, 49 | 255, 50 | -18.781392931397956, 51 | 16.16038494431541, 52 | -2.7182226936743086, 53 | 0.20523737020030292, 54 | -0.0065653285676726975, 55 | 7.495944393279058e-05, 56 | 0.0, 57 | 0.0, 58 | 0.0, 59 | 0.0, 60 | 0.0, 61 | 0.0, 62 | 0.0, 63 | 0.0, 64 | }; 65 | 66 | 67 | const polyfactors mon_xp_fac = { /* xp drop */ 68 | 1, 69 | 65535, 70 | -20.841100680021054, 71 | 26.84734630013967, 72 | -9.825840742202868, 73 | 1.6959832502784307, 74 | -0.15254999072108652, 75 | 0.0076971508758765135, 76 | -0.00021823995314218197, 77 | 3.2334332823059712e-06, 78 | -1.9381476733584117e-08, 79 | 0.0, 80 | 0.0, 81 | 0.0, 82 | 0.0, 83 | 0.0, 84 | }; 85 | 86 | const polyfactors mon_gold_fac = { /* gold drop */ 87 | 1, 88 | 65535, 89 | -181.6771668982451, 90 | 386.8666504544928, 91 | -301.04838303113064, 92 | 120.0121318216478, 93 | -28.239066882044998, 94 | 4.255536278310077, 95 | -0.4310644096683368, 96 | 0.030169784104046294, 97 | -0.0014761042847631243, 98 | 5.032651290264322e-05, 99 | -1.170908028733686e-06, 100 | 1.7713237145736675e-08, 101 | -1.5696278657423732e-10, 102 | 6.179904820229751e-13, 103 | }; 104 | 105 | 106 | const polyfactors mon_sr_fac = { /* sleep resist */ 107 | 0, 108 | 15, 109 | -2.1969437076317404, 110 | 3.483961128823471, 111 | -1.8204222230467941, 112 | 0.4520755754949881, 113 | -0.06254050232250673, 114 | 0.0052010391351393, 115 | -0.0002681807562045997, 116 | 8.596519147477848e-06, 117 | -1.6601627035508357e-07, 118 | 1.7617581896745132e-09, 119 | -7.862108379050638e-12, 120 | 0.0, 121 | 0.0, 122 | 0.0, 123 | }; 124 | 125 | const polyfactors mon_ssr_fac = { /* stopspell resist */ 126 | 0, 127 | 15, 128 | -1.3975554576022768, 129 | 1.1092073308967485, 130 | -0.34011588034318774, 131 | 0.05251897032361768, 132 | -0.003980681424706965, 133 | 0.00015503321304148872, 134 | -2.9829159588564997e-06, 135 | 2.24678806115065e-08, 136 | 0.0, 137 | 0.0, 138 | 0.0, 139 | 0.0, 140 | 0.0, 141 | 0.0, 142 | }; 143 | 144 | const polyfactors mon_hr_fac = { /* hurt resist */ 145 | 0, 146 | 15, 147 | 3.239518498565487, 148 | -4.208288329186024, 149 | 1.671124663419926, 150 | -0.29681665124095485, 151 | 0.027534617270887022, 152 | -0.0014224210043402236, 153 | 4.1036011631450263e-05, 154 | -6.158661983444021e-07, 155 | 3.73676230182728e-09, 156 | 0.0, 157 | 0.0, 158 | 0.0, 159 | 0.0, 160 | 0.0, 161 | }; 162 | 163 | const polyfactors mon_dodge_fac = { /* dodge rate */ 164 | 0, 165 | 15, 166 | 0.5368685340509266, 167 | -1.19322450637194, 168 | 1.135749874694354, 169 | -0.3569654344660422, 170 | 0.0558650996237906, 171 | -0.005026490880983962, 172 | 0.0002775653042091582, 173 | -9.586780557000136e-06, 174 | 2.022816058385553e-07, 175 | -2.3870467816279395e-09, 176 | 1.2078878215282233e-11, 177 | 0.0, 178 | 0.0, 179 | 0.0, 180 | }; 181 | 182 | const polyfactors hero_hp_fac = { /* hero hp */ 183 | 10, 184 | 254, 185 | 10.769305218816912, 186 | 10.38282954566378, 187 | -2.1766062394137147, 188 | 0.291310320096156, 189 | -0.014950948297038679, 190 | 0.0003205574441787177, 191 | -2.327262068436651e-06, 192 | 0.0, 193 | 0.0, 194 | 0.0, 195 | 0.0, 196 | 0.0, 197 | 0.0, 198 | 0.0, 199 | }; 200 | 201 | const polyfactors hero_mp_fac = { /* hero mp */ 202 | 0, 203 | 254, 204 | 0.13093148808975483, 205 | 8.695665405039039, 206 | -22.78588836769728, 207 | 19.084988390583433, 208 | -7.261082550213018, 209 | 1.5887604731251848, 210 | -0.22145864502085602, 211 | 0.020731125770043393, 212 | -0.001335795175925303, 213 | 5.9460470002518895e-05, 214 | -1.797127696880616e-06, 215 | 3.5208151060336736e-08, 216 | -4.032368075387321e-10, 217 | 2.0490726714779504e-12, 218 | }; 219 | 220 | const polyfactors hero_str_fac = { /* hero str */ 221 | 4, 222 | 255, 223 | 1.9855036334052616, 224 | 0.34832358784053047, 225 | 1.5428483226313243, 226 | 0.3239461083788206, 227 | -0.21645012688898962, 228 | 0.04302723862647274, 229 | -0.004579815435313073, 230 | 0.00029461668659935543, 231 | -1.1834359468455204e-05, 232 | 2.9112490218662203e-07, 233 | -4.019939224312338e-09, 234 | 2.3890912704510155e-11, 235 | 0.0, 236 | 0.0, 237 | }; 238 | 239 | const polyfactors hero_agi_fac = { /* hero agility */ 240 | 4, 241 | 255, 242 | 4.042393433680315, 243 | 1.4391285141452397, 244 | 3.872740592255078, 245 | -2.24526590826916, 246 | 0.7134255669128887, 247 | -0.13361532225642578, 248 | 0.015301508217809944, 249 | -0.001060052044776044, 250 | 3.998825862775953e-05, 251 | -3.6196885559985426e-07, 252 | -3.514428765810476e-08, 253 | 1.6259569090787755e-09, 254 | -2.9493035830245705e-11, 255 | 2.0484508811893367e-13, 256 | }; 257 | 258 | 259 | const polyfactors hero_xp_fac = { /* random level xp */ 260 | 1, 261 | 65535, 262 | -203.9930248427263, 263 | 355.710547735673, 264 | -123.22889565409092, 265 | 13.309885476933784, 266 | -0.23922916799801897, 267 | 0.0, 268 | 0.0, 269 | 0.0, 270 | 0.0, 271 | 0.0, 272 | 0.0, 273 | 0.0, 274 | 0.0, 275 | 0.0, 276 | }; 277 | 278 | const polyfactors wpn_price_fac = { /* weapon prices */ 279 | 5, 280 | 65535, 281 | 18.145188145239064, 282 | -142.37844514164718, 283 | 106.63369825909453, 284 | -20.403062136809016, 285 | 1.2241551018641001, 286 | 0.0, 287 | 0.0, 288 | 0.0, 289 | 0.0, 290 | 0.0, 291 | 0.0, 292 | 0.0, 293 | 0.0, 294 | 0.0, 295 | }; 296 | 297 | /** 298 | * Solves a polynomial function for the given x value. 299 | * 300 | * @param x The x value 301 | * @param fac The factors for the polynomial 302 | * 303 | * @return The solution to the equation 304 | */ 305 | double polyfit(double x, const polyfactors *fac) 306 | { 307 | size_t i; 308 | double result = 0.0; 309 | const double *factors = &fac->x0; 310 | 311 | for (i = 0; i <= 13; i++) { 312 | if (factors[i]) { 313 | result += factors[i] * pow(x, (double)i); 314 | } 315 | } 316 | result = MAX(result, fac->y_min); 317 | result = MIN(result, fac->y_max); 318 | return roundl(result); 319 | } 320 | 321 | -------------------------------------------------------------------------------- /common/polyfit.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _DWR_POLYFIT_H_ 3 | #define _DWR_POLYFIT_H_ 4 | 5 | typedef struct { 6 | double y_min; 7 | double y_max; 8 | double x0; 9 | double x1; 10 | double x2; 11 | double x3; 12 | double x4; 13 | double x5; 14 | double x6; 15 | double x7; 16 | double x8; 17 | double x9; 18 | double x10; 19 | double x11; 20 | double x12; 21 | double x13; 22 | } polyfactors; 23 | 24 | extern const polyfactors mon_hp_fac; /* monster HP */ 25 | extern const polyfactors mon_str_fac; /* monster strength */ 26 | extern const polyfactors mon_agi_fac; /* monster agility */ 27 | extern const polyfactors mon_xp_fac; /* xp drop */ 28 | extern const polyfactors mon_xp_fac; /* xp drop */ 29 | extern const polyfactors mon_gold_fac; /* gold drop */ 30 | extern const polyfactors mon_sr_fac; /* sleep resist */ 31 | extern const polyfactors mon_ssr_fac; /* stopspell resist */ 32 | extern const polyfactors mon_hr_fac; /* hurt resist */ 33 | extern const polyfactors mon_dodge_fac; /* dodge rate */ 34 | extern const polyfactors hero_hp_fac; /* hero hp */ 35 | extern const polyfactors hero_mp_fac; /* hero mp */ 36 | extern const polyfactors hero_str_fac; /* hero mp */ 37 | extern const polyfactors hero_agi_fac; /* hero agility */ 38 | extern const polyfactors hero_xp_fac; /* random level xp */ 39 | extern const polyfactors wpn_price_fac; /* weapon prices */ 40 | 41 | double polyfit(double x, const polyfactors *fac); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /common/sprites.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DWRANDOMIZER_SPRITES_H 3 | #define DWRANDOMIZER_SPRITES_H 4 | 5 | #include 6 | 7 | #include "dwr_types.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | extern const char * const dwr_sprite_names[]; 14 | 15 | void sprite(dw_rom *rom, const char *sprite_name); 16 | size_t sprite_count(); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif //DWRANDOMIZER_SPRITES_H 23 | -------------------------------------------------------------------------------- /common/stair_shuffle.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _STAIR_SHUFFLE_H_ 3 | #define _STAIR_SHUFFLE_H_ 4 | 5 | #include "dwr_types.h" 6 | 7 | void stair_shuffle(dw_rom *rom); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /compile_commands.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "directory": "/home/mcgrew/projects/dwrandomizer", 4 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/cli/main.c.o -c /home/mcgrew/projects/dwrandomizer/cli/main.c", 5 | "file": "/home/mcgrew/projects/dwrandomizer/cli/main.c" 6 | }, 7 | { 8 | "directory": "/home/mcgrew/projects/dwrandomizer", 9 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/crc64.c.o -c /home/mcgrew/projects/dwrandomizer/common/crc64.c", 10 | "file": "/home/mcgrew/projects/dwrandomizer/common/crc64.c" 11 | }, 12 | { 13 | "directory": "/home/mcgrew/projects/dwrandomizer", 14 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/sprites.c.o -c /home/mcgrew/projects/dwrandomizer/common/sprites.c", 15 | "file": "/home/mcgrew/projects/dwrandomizer/common/sprites.c" 16 | }, 17 | { 18 | "directory": "/home/mcgrew/projects/dwrandomizer", 19 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/dwr.c.o -c /home/mcgrew/projects/dwrandomizer/common/dwr.c", 20 | "file": "/home/mcgrew/projects/dwrandomizer/common/dwr.c" 21 | }, 22 | { 23 | "directory": "/home/mcgrew/projects/dwrandomizer", 24 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/map.c.o -c /home/mcgrew/projects/dwrandomizer/common/map.c", 25 | "file": "/home/mcgrew/projects/dwrandomizer/common/map.c" 26 | }, 27 | { 28 | "directory": "/home/mcgrew/projects/dwrandomizer", 29 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/dungeon_maps.c.o -c /home/mcgrew/projects/dwrandomizer/common/dungeon_maps.c", 30 | "file": "/home/mcgrew/projects/dwrandomizer/common/dungeon_maps.c" 31 | }, 32 | { 33 | "directory": "/home/mcgrew/projects/dwrandomizer", 34 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/stair_shuffle.c.o -c /home/mcgrew/projects/dwrandomizer/common/stair_shuffle.c", 35 | "file": "/home/mcgrew/projects/dwrandomizer/common/stair_shuffle.c" 36 | }, 37 | { 38 | "directory": "/home/mcgrew/projects/dwrandomizer", 39 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/chests.c.o -c /home/mcgrew/projects/dwrandomizer/common/chests.c", 40 | "file": "/home/mcgrew/projects/dwrandomizer/common/chests.c" 41 | }, 42 | { 43 | "directory": "/home/mcgrew/projects/dwrandomizer", 44 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/expansion.c.o -c /home/mcgrew/projects/dwrandomizer/common/expansion.c", 45 | "file": "/home/mcgrew/projects/dwrandomizer/common/expansion.c" 46 | }, 47 | { 48 | "directory": "/home/mcgrew/projects/dwrandomizer", 49 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/mt19937-64.c.o -c /home/mcgrew/projects/dwrandomizer/common/mt19937-64.c", 50 | "file": "/home/mcgrew/projects/dwrandomizer/common/mt19937-64.c" 51 | }, 52 | { 53 | "directory": "/home/mcgrew/projects/dwrandomizer", 54 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/chaos.c.o -c /home/mcgrew/projects/dwrandomizer/common/chaos.c", 55 | "file": "/home/mcgrew/projects/dwrandomizer/common/chaos.c" 56 | }, 57 | { 58 | "directory": "/home/mcgrew/projects/dwrandomizer", 59 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/patch.c.o -c /home/mcgrew/projects/dwrandomizer/common/patch.c", 60 | "file": "/home/mcgrew/projects/dwrandomizer/common/patch.c" 61 | }, 62 | { 63 | "directory": "/home/mcgrew/projects/dwrandomizer", 64 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/challenge.c.o -c /home/mcgrew/projects/dwrandomizer/common/challenge.c", 65 | "file": "/home/mcgrew/projects/dwrandomizer/common/challenge.c" 66 | }, 67 | { 68 | "directory": "/home/mcgrew/projects/dwrandomizer", 69 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/polyfit.c.o -c /home/mcgrew/projects/dwrandomizer/common/polyfit.c", 70 | "file": "/home/mcgrew/projects/dwrandomizer/common/polyfit.c" 71 | }, 72 | { 73 | "directory": "/home/mcgrew/projects/dwrandomizer", 74 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/base32.c.o -c /home/mcgrew/projects/dwrandomizer/common/base32.c", 75 | "file": "/home/mcgrew/projects/dwrandomizer/common/base32.c" 76 | }, 77 | { 78 | "directory": "/home/mcgrew/projects/dwrandomizer", 79 | "command": "/usr/bin/cc -I/home/mcgrew/projects/dwrandomizer/common -o CMakeFiles/dwrandomizer.dir/common/credit_music.c.o -c /home/mcgrew/projects/dwrandomizer/common/credit_music.c", 80 | "file": "/home/mcgrew/projects/dwrandomizer/common/credit_music.c" 81 | } 82 | ] -------------------------------------------------------------------------------- /electron/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | yarn.lock 4 | -------------------------------------------------------------------------------- /electron/base32.js: -------------------------------------------------------------------------------- 1 | ../build/release/base32.js -------------------------------------------------------------------------------- /electron/build/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icon.ico -------------------------------------------------------------------------------- /electron/build/icons/icon_1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_1024x1024.png -------------------------------------------------------------------------------- /electron/build/icons/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_128x128.png -------------------------------------------------------------------------------- /electron/build/icons/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_16x16.png -------------------------------------------------------------------------------- /electron/build/icons/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_256x256.png -------------------------------------------------------------------------------- /electron/build/icons/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_32x32.png -------------------------------------------------------------------------------- /electron/build/icons/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_512x512.png -------------------------------------------------------------------------------- /electron/build/icons/icon_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/electron/build/icons/icon_64x64.png -------------------------------------------------------------------------------- /electron/dwrandomizer.js: -------------------------------------------------------------------------------- 1 | ../build/release/dwrandomizer.js -------------------------------------------------------------------------------- /electron/dwrandomizer.wasm: -------------------------------------------------------------------------------- 1 | ../build/release/dwrandomizer.wasm -------------------------------------------------------------------------------- /electron/index.css: -------------------------------------------------------------------------------- 1 | ../build/release/index.css -------------------------------------------------------------------------------- /electron/index.html: -------------------------------------------------------------------------------- 1 | ../build/release/index.html -------------------------------------------------------------------------------- /electron/index.js: -------------------------------------------------------------------------------- 1 | ../build/release/index.js -------------------------------------------------------------------------------- /electron/interface.js: -------------------------------------------------------------------------------- 1 | ../build/release/interface.js -------------------------------------------------------------------------------- /electron/logo.png: -------------------------------------------------------------------------------- 1 | ../build/release/logo.png -------------------------------------------------------------------------------- /electron/main.js: -------------------------------------------------------------------------------- 1 | // Modules to control application life and create native browser window 2 | const {app, BrowserWindow, Menu} = require('electron') 3 | const path = require('path') 4 | 5 | function createWindow () { 6 | // Create the browser window. 7 | const mainWindow = new BrowserWindow({ 8 | width: 800, 9 | height: 700, 10 | autoHideMenuBar: true, 11 | resizable: false, 12 | // frame: false, 13 | webPreferences: { 14 | preload: path.join(__dirname, 'preload.js'), 15 | enableRemoteModule: true 16 | } 17 | }) 18 | // mainWindow.openDevTools(); 19 | Menu.setApplicationMenu(null); 20 | 21 | // and load the index.html of the app. 22 | mainWindow.loadFile('index.html') 23 | 24 | // Open the DevTools. 25 | // mainWindow.webContents.openDevTools() 26 | } 27 | 28 | // This method will be called when Electron has finished 29 | // initialization and is ready to create browser windows. 30 | // Some APIs can only be used after this event occurs. 31 | app.whenReady().then(() => { 32 | createWindow() 33 | 34 | app.on('activate', function () { 35 | // On macOS it's common to re-create a window in the app when the 36 | // dock icon is clicked and there are no other windows open. 37 | if (BrowserWindow.getAllWindows().length === 0) createWindow() 38 | }) 39 | }) 40 | 41 | // Quit when all windows are closed, except on macOS. There, it's common 42 | // for applications and their menu bar to stay active until the user quits 43 | // explicitly with Cmd + Q. 44 | app.on('window-all-closed', function () { 45 | if (process.platform !== 'darwin') app.quit() 46 | }) 47 | 48 | // In this file you can include the rest of your app's specific main process 49 | // code. You can also put them in separate files and require them here. 50 | -------------------------------------------------------------------------------- /electron/modal.js: -------------------------------------------------------------------------------- 1 | ../build/release/modal.js -------------------------------------------------------------------------------- /electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dwrandomizer", 3 | "version": "3.0.3", 4 | "description": "Dragon Warrior Randomizer", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "electron .", 8 | "dist": "electron-builder -wl", 9 | "dist-linux": "electron-builder -l", 10 | "dist-win": "electron-builder -w", 11 | "dist-mac": "electron-builder -m" 12 | }, 13 | "build": { 14 | "appId": "com.dwrandomizer", 15 | "linux": { 16 | "category": "Gaming", 17 | "target": [ 18 | "snap", 19 | "AppImage", 20 | "deb" 21 | ] 22 | }, 23 | "mac": { 24 | "category": "Gaming", 25 | "target": [ 26 | "dmg" 27 | ] 28 | }, 29 | "win": { 30 | "target": [ 31 | "portable" 32 | ] 33 | } 34 | }, 35 | "repository": "https://github.com/mcgrew/dwrandomizer", 36 | "keywords": [ 37 | "Dragon", 38 | "Warrior", 39 | "Randomizer" 40 | ], 41 | "author": { 42 | "name": "mcgrew", 43 | "email": "tjmcgrew@gmail.com" 44 | }, 45 | "license": "MIT", 46 | "devDependencies": { 47 | "electron": "^19.0.7", 48 | "electron-builder": "^23.1.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /electron/preload.js: -------------------------------------------------------------------------------- 1 | 2 | // All of the Node.js APIs are available in the preload process. 3 | // It has the same sandbox as a Chrome extension. 4 | window.addEventListener('DOMContentLoaded', () => { 5 | const replaceText = (selector, text) => { 6 | const element = document.getElementById(selector) 7 | if (element) element.innerText = text 8 | } 9 | 10 | for (const type of ['chrome', 'node', 'electron']) { 11 | replaceText(`${type}-version`, process.versions[type]) 12 | } 13 | 14 | document.body.style.backgroundColor = '#fff'; 15 | if (window.matchMedia("(prefers-color-scheme: dark)").matches) { 16 | document.body.style.backgroundColor = '#333'; 17 | } 18 | }) 19 | 20 | function createElement(element, text, style) { 21 | let el = document.createElement(element); 22 | if (text) 23 | el.innerText = text 24 | if (style) { 25 | for (key in style) 26 | el.style.setProperty(key, style[key]); 27 | } 28 | return el; 29 | } 30 | -------------------------------------------------------------------------------- /electron/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 | // No Node.js APIs are available in this process because 4 | // `nodeIntegration` is turned off. Use `preload.js` to 5 | // selectively enable features needed in the rendering 6 | // process. 7 | -------------------------------------------------------------------------------- /electron/sprites: -------------------------------------------------------------------------------- 1 | ../build/release/sprites -------------------------------------------------------------------------------- /expansion/bank_0.asm: -------------------------------------------------------------------------------- 1 | 2 | FILLVALUE $ff 3 | 4 | CURRENT_TILE EQU $E0 5 | SELECTED_ITEM EQU $D7 6 | ITEMS EQU $C1 7 | 8 | .db "NES", $1a 9 | .db 8 ; PRG ROM banks 10 | .db 2 ; CHR ROM banks 11 | .db $12 12 | .db $00 13 | .db $00 14 | .db $00 15 | .db $00 16 | .db 0,0,0,0,0 17 | 18 | PPUCTRL EQU $2000 19 | PPUMASK EQU $2001 20 | PPUSTATUS EQU $2002 21 | PPUSCROLL EQU $2005 22 | PPUADDR EQU $2006 23 | PPUDATA EQU $2007 24 | DMC_FREQ EQU $4010 25 | OAMDMA EQU $4014 26 | 27 | .base $8000 28 | 29 | ; DW labels 30 | 31 | b3_e01b EQU $e01b 32 | 33 | X_POS EQU $3A 34 | X_POS_2 EQU $8E 35 | Y_POS EQU $3B 36 | Y_POS_2 EQU $8F 37 | MAP_INDEX EQU $45 38 | RANDOM_H EQU $95 39 | RANDOM_L EQU $94 40 | ; _UNUSED_D5 EQU $00D5 41 | ; _UNUSED_DC EQU $00DC 42 | ; _UNUSED_DD EQU $00DD 43 | ; 44 | ; b3_hero_used_harp EQU $DE18 45 | ; b3_hero_used_herb EQU $DCFE 46 | ; b3_hero_used_take EQU $E200 47 | ; b3_irq EQU $FD3A 48 | ; b3_nmi EQU $FE67 49 | ; b3_reset EQU $FFD8 50 | ; buy_sell_win EQU $B0FB 51 | ; calc_stats EQU $F050 52 | ; cave_zones EQU $F542 53 | ; combat_cmd_win EQU $B095 54 | ; command_win EQU $B054 55 | ; cont_chg_win EQU $B20B 56 | ; credit_data EQU $948D 57 | ; cycle_rng EQU $C55B 58 | ; d3_d1b2 EQU $D1B2 59 | ; dec_radiant_counter EQU $CA56 60 | ; desc_ptr_table EQU $A830 61 | ; detect_vowel EQU $BA3C 62 | ; dialog_win EQU $B04B 63 | ; do_dialog_hi EQU $C7BD 64 | do_dialog_hi EQU $C7C5 65 | do_dialog_lo EQU $C7CB 66 | ; do_item EQU $B757 67 | ; do_spell EQU $B7D8 68 | ; 69 | ; end_credit_ptr EQU $948B 70 | ; enemy_names_1 EQU $BC70 71 | ; enemy_names_2 EQU $BDA2 72 | ; finish_text EQU $D242 73 | ; full_menu_win EQU $B249 74 | ; heal_spell EQU $DA47 75 | ; healmore_spell EQU $DAE3 76 | ; hero_used_heal EQU $DBB8 77 | ; hero_used_healmore EQU $DBD7 78 | ; hurt_spell EQU $DA51 79 | ; input_name_win EQU $B1E0 80 | ; inv_add_item EQU $E01B 81 | ; inv_check EQU $E055 82 | ; inv_del_item EQU $E04B 83 | ; item_names_1_1 EQU $BAB7 84 | ; item_names_1_2 EQU $BBB7 85 | ; item_names_2_1 EQU $BB8F 86 | ; item_names_2_2 EQU $BC4F 87 | ; item_prices EQU $BE10 88 | ; item_prices_ptr EQU $BE0E 89 | ; items_win EQU $B0CC 90 | ; jmp_amt EQU $B6CD 91 | ; jmp_amt_pts EQU $B6CA 92 | ; jmp_copy EQU $B6B2 93 | ; jmp_desc EQU $B6BE 94 | ; jmp_enemy EQU $B6B8 95 | ; jmp_enemy_2 EQU $B6C1 96 | ; jmp_item EQU $B6C4 97 | ; jmp_name EQU $B6B5 98 | ; jmp_points EQU $B6C7 99 | ; jmp_spell EQU $B6BB 100 | ; ken_masuta EQU $FC76 101 | ; load_chr_bank EQU $FE09 102 | ; store_and_load_prg_bank EQU $FF91 103 | ; load_prg_bank EQU $FF96 104 | ; monster_stats EQU $9E4B 105 | ; monster_stats_ptr EQU $9E49 106 | ; msg_speed_win EQU $B194 107 | ; music_notes EQU $8205 108 | ; name_entry_win EQU $B1F7 109 | ; new_quest_win EQU $B2A8 110 | ; outside_spell EQU $DA9F 111 | ; player_stats EQU $A0CD 112 | ; radiant_spell EQU $DA84 113 | ; read_joy_1 EQU $C608 114 | ; repel_spell EQU $DA94 115 | ; repel_table EQU $F4FA 116 | ; reset EQU $FD86 117 | ; return_spell EQU $DAED 118 | ; save_game EQU $F6F4 119 | ; shop_inv_win EQU $B0DA 120 | ; show_window EQU $C6F0 121 | ; sleep_spell EQU $DA5C 122 | ; spell_names EQU $BE56 123 | ; spell_win EQU $B0BA 124 | ; start_combat EQU $E4DF 125 | ; stats_win EQU $AFB0 126 | ; status_win EQU $AFC7 127 | ; 128 | ; tab_brecconary_map EQU $8716 129 | ; tab_cantlin_map EQU $88D8 130 | ; tab_charlock1_map EQU $80B0 131 | ; tab_charlock_b1_map EQU $8DBA 132 | ; tab_charlock_b2_map EQU $8E82 133 | ; tab_charlock_b3_map EQU $8EB4 134 | ; tab_charlock_b4_map EQU $8EE6 135 | ; tab_charlock_b5_map EQU $8F18 136 | ; tab_charlock_b6_map EQU $8F4A 137 | ; tab_charlock_throne_map EQU $8434 138 | ; tab_chest_contents EQU $9DCD 139 | ; tab_erdrick_cave_b1_map EQU $92B0 140 | ; tab_erdrick_cave_b2_map EQU $92E2 141 | ; tab_garinham_map EQU $8A9A 142 | ; tab_garins_grave_b1_map EQU $909A 143 | ; tab_garins_grave_b2_map EQU $925C 144 | ; tab_garins_grave_b3_map EQU $9162 145 | ; tab_garins_grave_b4_map EQU $922A 146 | ; tab_hauksness_map EQU $8178 147 | ; tab_item_shop_inv EQU $99BC 148 | ; tab_kol_map EQU $85F6 149 | ; tab_map_data EQU $801A 150 | ; tab_mt_cave_b1_map EQU $8FD6 151 | ; tab_mt_cave_b2_map EQU $9038 152 | ; tab_north_shrine_map EQU $8D56 153 | ; tab_point EQU $B751 154 | ; tab_rimuldar_map EQU $8B62 155 | ; tab_south_shrine_map EQU $8D88 156 | ; tab_stones_shrine_map EQU $8D24 157 | ; tab_swamp_cave_map EQU $8F7C 158 | ; tab_tant_throne_map EQU $8402 159 | ; tab_tantegel_map EQU $8240 160 | ; tab_warp_from EQU $F3C8 161 | ; tab_warp_to EQU $F461 162 | ; tab_weapon_prices EQU $9947 163 | ; tab_weapon_shop_inv EQU $9991 164 | ; tab_world_map EQU $9D5D 165 | ; tab_world_map_pointers EQU $A653 166 | ; take_content EQU $E39A 167 | ; text_block_1 EQU $8028 168 | ; text_block_2 EQU $8286 169 | ; text_block_3 EQU $8519 170 | ; text_block_4 EQU $8713 171 | ; text_block_5 EQU $894C 172 | ; text_block_6 EQU $8D12 173 | ; text_block_7 EQU $906E 174 | ; text_block_8 EQU $9442 175 | ; text_block_9 EQU $981E 176 | ; text_block_10 EQU $9C88 177 | ; text_block_11 EQU $9F3F 178 | ; text_block_12 EQU $A28A 179 | ; text_block_13 EQU $A6DC 180 | ; text_block_14 EQU $AA2E 181 | ; text_block_15 EQU $AC61 182 | ; text_block_16 EQU $AE28 183 | ; text_block_17 EQU $AFEE 184 | ; text_block_18 EQU $B68B 185 | ; text_block_19 EQU $BA65 186 | ; title_routine EQU $BCB0 187 | ; update_sound EQU $8028 188 | ; xp_requirements EQU $F35B 189 | ; yes_no_win_1 EQU $B0EB 190 | ; zone_enemies EQU $F54F 191 | ; zone_layout EQU $F522 192 | 193 | .org $c000 194 | -------------------------------------------------------------------------------- /expansion/bank_3_patch.asm: -------------------------------------------------------------------------------- 1 | 2 | .org $c288 3 | 4 | .word exp_start_dwr_credits ; 0 5 | .word exp_inc_counter ; 2 6 | .word exp_inc_enemy_death_ctr ; 4 7 | .word exp_count_win ; 6 8 | .word exp_count_encounter ; 8 9 | .word exp_inc_mon_counter ; 10 10 | .word exp_count_spell_use ; 12 11 | .word exp_load_last_bank ; 14 12 | .word exp_sort_inventory ; 16 13 | ; .word exp_torch_in_battle ; 18 14 | 15 | start_dwr_credits: 16 | ldy #0 17 | beq exec_expansion_sub 18 | 19 | inc_attack_ctr: 20 | brk 21 | hex 04 17 22 | lda #2 23 | tay 24 | jsr exec_expansion_sub 25 | rts 26 | 27 | inc_crit_ctr: 28 | brk 29 | hex 04 17 30 | lda #4 31 | ldy #2 32 | bne exec_expansion_sub 33 | 34 | inc_miss_ctr: 35 | brk 36 | hex 04 17 37 | lda #6 38 | ldy #2 39 | bne exec_expansion_sub 40 | 41 | inc_dodge_ctr: 42 | brk 43 | hex 04 17 44 | lda #8 45 | ldy #2 46 | bne exec_expansion_sub 47 | 48 | inc_bonk_ctr: 49 | brk 50 | hex 04 17 51 | lda #10 52 | ldy #2 53 | bne exec_expansion_sub 54 | 55 | inc_death_ctr: 56 | brk 57 | hex 04 17 58 | lda #0 59 | ldy #2 60 | bne exec_expansion_sub 61 | 62 | blocked_in_front: 63 | jsr do_dialog_lo ; but was blocked in front 64 | hex f6 65 | ldy #2 66 | lda #12 67 | bne exec_expansion_sub 68 | 69 | player_ambushed: 70 | jsr do_dialog_lo ; attacked before ready 71 | hex e4 72 | lda #14 73 | ldy #2 74 | ; bne exec_expansion_sub 75 | 76 | exec_expansion_sub: 77 | pha 78 | ; lda #$4c 79 | ; sta $7f00 80 | lda $c288,y 81 | sta $7f01 82 | lda $c289,y 83 | sta $7f02 84 | lda $6004 85 | sta $7004 86 | lda #3 87 | jsr store_and_load_prg_bank 88 | pla 89 | jmp ($7f01) 90 | 91 | inc_enemy_death_ctr: 92 | brk 93 | hex 04 17 94 | ldy #4 95 | bne exec_expansion_sub 96 | 97 | count_encounter: 98 | brk 99 | hex 04 17 100 | ldy #8 101 | jsr exec_expansion_sub 102 | jmp exp_load_last_bank 103 | 104 | count_win: 105 | ldy #6 106 | jsr exec_expansion_sub 107 | jmp exp_load_last_bank 108 | 109 | count_spell_use: 110 | ldy #12 111 | jsr exec_expansion_sub 112 | jmp $c6f0 ; show window 113 | 114 | sort_inventory: 115 | jsr b3_e01b ; add the new item 116 | cpx #$04 117 | bne + 118 | rts 119 | + ldy #16 120 | bne exec_expansion_sub 121 | 122 | torch_in_battle: 123 | ; ldy #18 124 | ; bne exec_expansion_sub 125 | cmp #$04 ; is this a torch? 126 | bne +++ ; no, go to next check 127 | lda #$01 128 | jsr $e04b ; remove the item from inventory 129 | jsr $c7c5 ; show the "hurled a torch" message 130 | hex 29 131 | lda $e0 132 | cmp #$10 ; are we fighting a metal slime? 133 | bne ++ ; no, go to higher damage 134 | - jsr $c55b ; run the rng cycle routine 135 | lda $95 ; load a random number 136 | and #$01 ; limit to 0-1 137 | bne + ; did we hit it? 138 | jmp $e658 ; A miss! 139 | + jmp $e694 ; yes, go to damage routine 140 | ++ jsr $c55b ; run the rng cycle routine 141 | lda $95 ; load a random number 142 | and #$03 ; limit to 0-3 143 | clc 144 | adc #$06 ; add 6 145 | jmp $e694 ; jump to damage routine 146 | +++ cmp #$05 ; c9 04 ; Fairy Water 147 | bne + 148 | lda #$02 149 | jsr $e04b ; remove the item from inventory 150 | jsr $c7c5 ; show the "sprinked fairy water" message 151 | hex 2a 152 | lda $e0 153 | cmp #$10 ; metal slime 154 | beq - 155 | jmp $e744 156 | + jmp $e6fd ; 4c fd e6 157 | 158 | threes_company_check: 159 | lda $df ; Load the status bits 160 | and #$01 ; Are we carrying Gwaelin? 161 | beq + ; No, back to original code 162 | jsr $c7cb ; Show dialogue 163 | .db $a1 ; I have some great ideas 164 | jmp $ccb8 ; Jump to the ending credits 165 | 166 | + jsr $c7cb ; Show dialoge 167 | .db $a1 ; Now take a long rest 168 | rts 169 | 170 | store_princess_item: 171 | sta $0e ; Store the item Gwaelin took 172 | jmp $e04b ; Continue on 173 | cursed_princess_check: 174 | pha ; Store register 175 | lda $0e ; Load the item Gwaelin took 176 | cmp #$09 ; It is a cursed belt? 177 | bne + ; No, keep playing 178 | jsr $c7cb ; Yes, Display dialogue 179 | .db $a0 ; What a lovely corset 180 | jsr $dffa ; Play the curse music 181 | jmp $ccb8 ; Jump to the ending 182 | + pla ; Restore register and continue 183 | jmp $d433 184 | 185 | scared_slimes: 186 | cmp $0100 ; Replace the code from $efba 187 | bcs + ; Return, everything is fine 188 | lda $e0 ; Load the enemy type 189 | cmp #$10 ; Is it a metal slime? 190 | beq + 191 | clc ; It's not, enemy doesn't run 192 | + rts 193 | 194 | init_save_ram: 195 | sta $62e8,x 196 | sta $662c,x 197 | sta $672c,x 198 | rts 199 | 200 | display_deaths: 201 | lda $64df 202 | bne + 203 | jmp $a8ba 204 | + lda #05 205 | sta $64e2 206 | lda $6630 207 | sta $1a 208 | lda $6631 209 | sta $1b 210 | lda #00 211 | sta $1c 212 | jsr $a753 213 | jmp $a764 214 | 215 | count_frame: 216 | ldx MAP_INDEX ; Start the timer once the map is no longer zero 217 | bne + 218 | lda $662c ; continue counting if the timer is greater than zero. 219 | ora $662d 220 | ora $662e 221 | beq ++ 222 | + ldx $662c ; increment the timer 223 | inx 224 | stx $662c 225 | bne ++ 226 | ldx $662d 227 | inx 228 | stx $662d 229 | bne ++ 230 | inc $662e 231 | ++ jmp $fdf4 232 | 233 | snapshot_timer: 234 | ldx #2 235 | - lda $662c,x 236 | sta $6f00,x 237 | dex 238 | bpl - 239 | jmp do_dialog_hi 240 | 241 | modify_run_rate: 242 | and #$7f ; limit the value in reg A to 0-127 243 | sta $3e ; save to $3E 244 | jsr cycle_rng ; generate a new random number 245 | lda RANDOM_H ; load the random number 246 | and #$3f ; limit to 0-63 247 | adc $3e ; add to the previous number 248 | jmp $eec7 249 | 250 | .org $c4f5 251 | 252 | .org $c4f5 253 | ; potentially unused data 254 | .org $c529 255 | 256 | .org $c6c9 257 | ; potentially unused data 258 | .org $c6f0 259 | 260 | .org $c7ec 261 | ; potentially unused data 262 | .org $c9b5 263 | 264 | .org $f232 265 | ; potentially unused data 266 | .org $f35b 267 | 268 | -------------------------------------------------------------------------------- /expansion/bank_7.asm: -------------------------------------------------------------------------------- 1 | 2 | .base $c000 3 | 4 | set_first_bank: 5 | sta $dfff 6 | lsr a 7 | sta $dfff 8 | lsr a 9 | sta $dfff 10 | lsr a 11 | sta $dfff 12 | lsr a 13 | sta $dfff 14 | nop 15 | nop 16 | rts 17 | 18 | first_vblank: 19 | jsr load_pal 20 | 21 | lda #$20 22 | sta PPUADDR 23 | lda #$00 24 | sta PPUADDR 25 | jsr load_bg 26 | lda #$24 27 | sta PPUADDR 28 | lda #$00 29 | sta PPUADDR 30 | jsr load_bg 31 | 32 | lda #$00 33 | ; sta SCROLLX 34 | sta PPUSCROLL 35 | ; lda SCROLLY 36 | sta PPUSCROLL 37 | rts 38 | 39 | load_pal: 40 | lda #$3f 41 | sta PPUADDR 42 | lda #$00 43 | sta PPUADDR 44 | ldx #$00 45 | - lda bg_palette, x 46 | sta PPUDATA 47 | inx 48 | cpx #$10 49 | bne - 50 | rts 51 | 52 | load_bg: 53 | ldy #$04 54 | -- ldx #$f0 55 | - lda #$5f 56 | ++ sta PPUDATA 57 | dex 58 | bne - 59 | dey 60 | bmi + ; this will trigger on our final write loop 61 | bne -- 62 | ; ldx #$c0 ; start the final write loop 63 | ; - sta PPUDATA 64 | ; dex 65 | ; bne - 66 | ldx #0 67 | -- lda the_end,x 68 | inx 69 | cmp #$fd 70 | beq + 71 | pha 72 | lda the_end,x 73 | inx 74 | sta PPUADDR 75 | pla 76 | sta PPUADDR 77 | - lda the_end,x 78 | inx 79 | cmp #$fc 80 | beq -- 81 | sta PPUDATA 82 | bne - 83 | + rts 84 | 85 | game_init: 86 | 87 | + rts 88 | 89 | bg_palette: 90 | .hex 0f 0f 30 30 91 | .hex 0f 0f 24 24 92 | .hex 0f 0f 27 27 93 | .hex 0f 0f 2a 2a 94 | 95 | the_end: 96 | ; The follwing is for "THE END" text 97 | .word $21aa ; PPU address 98 | .hex 3e 3f 40 41 42 43 44 45 46 47 48 49 fc 99 | .word $21ca ; PPU address 100 | .hex 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 fc 101 | .hex fd 102 | 103 | .include base.asm 104 | 105 | game_start: 106 | jmp start_dwr_credits 107 | .include bank_3_patch.asm 108 | 109 | 110 | .org $fe09 111 | b3_fe09: 112 | sta $6001 113 | sta $9fff 114 | lsr a 115 | sta $9fff 116 | lsr a 117 | sta $9fff 118 | lsr a 119 | sta $9fff 120 | lsr a 121 | sta $9fff 122 | rts 123 | 124 | .org $ff91 125 | 126 | store_and_load_prg_bank: 127 | b3_ff91: 128 | sta $6004 129 | nop 130 | nop 131 | load_prg_bank: 132 | b3_ff96: 133 | sta $ffff 134 | lsr a 135 | sta $ffff 136 | lsr a 137 | sta $ffff 138 | lsr a 139 | sta $ffff 140 | lsr a 141 | sta $ffff 142 | nop 143 | nop 144 | rts 145 | 146 | .org $ffd8 147 | ; sei 148 | ; inc $ffdf 149 | lda #0 150 | jsr set_first_bank 151 | jmp reset 152 | 153 | .org $fffa 154 | 155 | .word nmi 156 | .word reset 157 | .word irq 158 | 159 | -------------------------------------------------------------------------------- /expansion/base.asm: -------------------------------------------------------------------------------- 1 | 2 | .enum $e0 3 | TMP .dsb 1 4 | TMP2 .dsb 1 5 | RANDOM .dsb 2 6 | BUTTONS .dsb 2 7 | NEW_BTNS .dsb 2 8 | RELEASED_BTNS .dsb 2 9 | ; VBLANK .dsb 1 10 | .ende 11 | 12 | reset: 13 | sei 14 | cld 15 | ldx #$40 16 | stx $4017 17 | ldx #$ff 18 | txs ; set up the stack 19 | inx 20 | stx PPUCTRL ; disable NMI 21 | stx DMC_FREQ ; disable DMC IRQs 22 | lda #$06 23 | sta PPUMASK ; disable rendering 24 | 25 | ; Optional (omitted): 26 | ; Set up mapper and jmp to further init code here. 27 | 28 | ; The vblank flag is in an unknown state after reset, 29 | ; so it is cleared here to make sure that vblankwait1 30 | ; does not exit immediately. 31 | bit PPUSTATUS 32 | 33 | ; First of two waits for vertical blank to make sure that the 34 | ; PPU has stabilized 35 | 36 | ; vblankwait1 37 | - bit PPUSTATUS 38 | bpl - 39 | 40 | ; We now have about 30,000 cycles to burn before the PPU stabilizes. 41 | ; One thing we can do with this time is put RAM in a known state. 42 | ; Here we fill it with $00, which matches what (say) a C compiler 43 | ; expects for BSS. Conveniently, X is still 0. 44 | txa 45 | 46 | @clrmem: 47 | sta $00,x 48 | sta $100,x 49 | sta $200,x 50 | sta $300,x 51 | sta $400,x 52 | sta $500,x 53 | sta $600,x 54 | sta $700,x 55 | inx 56 | bne @clrmem 57 | 58 | ; Other things you can do between vblank waits are set up audio 59 | ; or set up other mapper registers. 60 | 61 | IFDEF game_init ; If this subroutine exists, jump to it here. 62 | jsr game_init 63 | ENDIF 64 | 65 | ; init rng with whatever is in A 66 | sta RANDOM+1 67 | ; jsr init_apu 68 | ; wait for vblank 69 | - bit $2002 70 | bpl - 71 | 72 | IFDEF first_vblank 73 | jsr first_vblank 74 | ENDIF 75 | 76 | lda #%10000000 77 | sta PPUCTRL ; enable NMI 78 | lda #%00011010 79 | sta PPUMASK ; enable rendering 80 | 81 | jmp game_start 82 | 83 | ; wait_for_sprite_0: 84 | ; - bit PPUSTATUS ; wait for end of blank 85 | ; bvs - 86 | ; - bit PPUSTATUS ; wait for sprite 0 hit 87 | ; bvc - 88 | ; rts 89 | 90 | wait_for_nmi: 91 | lda #$00 92 | sta VBLANK 93 | - lda VBLANK 94 | beq - 95 | rts 96 | 97 | cycle_rng: 98 | pha 99 | tya 100 | pha 101 | ldy #8 ; iteration count (8 bits) 102 | lda RANDOM 103 | 104 | - asl ; shift the register 105 | rol RANDOM+1 106 | bcc + 107 | eor #$39 ; apply XOR feedback whenever a 1 bit is shifted out 108 | 109 | + dey 110 | bne - 111 | sta RANDOM 112 | pla 113 | tay 114 | pla 115 | rts 116 | 117 | ; read_joy: 118 | ; lda BUTTONS 119 | ; sta TMP 120 | ; jsr get_joy_buttons 121 | ; - lda BUTTONS 122 | ; pha 123 | ; jsr get_joy_buttons 124 | ; pla 125 | ; cmp BUTTONS 126 | ; bne - 127 | ; lda TMP 128 | ; eor BUTTONS 129 | ; and BUTTONS 130 | ; sta NEW_BTNS ; now contains buttons newly pressed in the last frame 131 | ; lda TMP 132 | ; eor BUTTONS 133 | ; and TMP 134 | ; sta RELEASED_BTNS ; now contains the buttons released in the last frame 135 | ; rts 136 | 137 | ; get_joy_buttons: 138 | ; ldx #$01 139 | ; stx JOY 140 | ; dex 141 | ; stx JOY 142 | ; inx 143 | ; -- lda #$01 144 | ; sta BUTTONS,x 145 | ; lsr a ; now A is 0 146 | ; - lda JOY,x 147 | ; lsr a ; bit 0 -> Carry 148 | ; rol BUTTONS,x ; Carry -> bit 0; bit 7 -> Carry 149 | ; bcc - 150 | ; dex 151 | ; beq -- 152 | ; rts 153 | 154 | ; init_apu: 155 | ; ; Init $4000-4013 156 | ; ldy #$13 157 | ; - lda @regs,y 158 | ; sta SQ1_VOL,y 159 | ; dey 160 | ; bpl - 161 | ; 162 | ; ; We have to skip over $4014 (OAMDMA) 163 | ; lda #$0f 164 | ; sta SND_CHN 165 | ; lda #$40 166 | ; sta $4017 167 | ; rts 168 | 169 | @regs: 170 | .hex 30 08 00 00 171 | .hex 30 08 00 00 172 | .hex 80 00 00 00 173 | .hex 30 00 00 00 174 | .hex 00 00 00 00 175 | 176 | ; .org $fffa 177 | 178 | .word nmi 179 | .word reset 180 | .word irq 181 | 182 | -------------------------------------------------------------------------------- /expansion/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | echo -n "Compiling... " 4 | 5 | asm6f -q -m -f -dDEBUG credits.asm credits.nes 6 | 7 | echo "Done." 8 | 9 | -------------------------------------------------------------------------------- /expansion/chr_rom.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/chr_rom.chr -------------------------------------------------------------------------------- /expansion/credits.asm: -------------------------------------------------------------------------------- 1 | 2 | ; .include defs.asm 3 | ; .include macros.asm 4 | 5 | TIMERS_COUNT EQU 8 6 | TIMERS_ADDR EQU $d0 7 | 8 | ; *** VARIABLES *** 9 | .enum $00 10 | SCROLLX .dsb 2 11 | SCROLLY EQU #0 ; Y scroll is always 0 12 | .ende 13 | .enum TIMERS_ADDR 14 | TIMERS .dsb TIMERS_COUNT*2 15 | .ende 16 | ; .enum $200 17 | ; SPRITES .dsb 256 18 | ; .ende 19 | 20 | ; *** PRG ROM *** 21 | .include bank_0.asm 22 | .include empty.asm 23 | .include empty.asm 24 | .include exp_bank_3.asm 25 | .include exp_bank_4.asm 26 | .include exp_bank_5.asm 27 | .include empty.asm 28 | .include bank_7.asm 29 | 30 | ; *** CHR ROM *** 31 | .incbin chr_rom.chr 32 | 33 | -------------------------------------------------------------------------------- /expansion/defs.asm: -------------------------------------------------------------------------------- 1 | 2 | FILLVALUE $ff 3 | 4 | ; *** HEADER *** 5 | 6 | .db "NES", $1a 7 | .db 2 ; PRG ROM banks 8 | .db 1 ; CHR ROM banks 9 | .db $01 ; No Mapper, vertical mirroring 10 | .db $00 11 | .db $00 12 | .db $00 13 | .db $00 14 | .db 0,0,0,0,0 15 | 16 | ; *** MMIO *** 17 | PPUCTRL EQU $2000 18 | PPUMASK EQU $2001 19 | PPUSTATUS EQU $2002 20 | OAMADDR EQU $2003 21 | OAMDATA EQU $2004 22 | PPUSCROLL EQU $2005 23 | PPUADDR EQU $2006 24 | PPUDATA EQU $2007 25 | SQ1_VOL EQU $4000 26 | SQ1_SWEEP EQU $4001 27 | SQ1_LO EQU $4002 28 | SQ1_HI EQU $4003 29 | SQ2_VOL EQU $4004 30 | SQ2_SWEEP EQU $4005 31 | SQ2_LO EQU $4006 32 | SQ2_HI EQU $4007 33 | TRI_LINEAR EQU $4008 34 | TRI_LO EQU $400a 35 | TRI_HI EQU $400b 36 | NOISE_VOL EQU $400c 37 | NOISE_PER EQU $400e 38 | NOISE_LEN EQU $400f 39 | DMC_FREQ EQU $4010 40 | DMC_RAW EQU $4011 41 | DMC_START EQU $4012 42 | DMC_LEN EQU $4013 43 | OAMDMA EQU $4014 44 | SND_CHN EQU $4015 45 | JOY EQU $4016 46 | JOY2 EQU $4017 47 | 48 | ; *** CONSTANTS *** 49 | BTN_RIGHT EQU #$01 50 | BTN_LEFT EQU #$02 51 | BTN_DOWN EQU #$04 52 | BTN_UP EQU #$08 53 | BTN_START EQU #$10 54 | BTN_SELECT EQU #$20 55 | BTN_B EQU #$40 56 | BTN_A EQU #$80 57 | 58 | -------------------------------------------------------------------------------- /expansion/empty.asm: -------------------------------------------------------------------------------- 1 | 2 | .base $8000 3 | .org $c000 4 | -------------------------------------------------------------------------------- /expansion/exp_bank_3.asm: -------------------------------------------------------------------------------- 1 | 2 | .base $8000 3 | 4 | exp_start_dwr_credits: 5 | lda #$a9 ; lda 6 | sta $200 7 | lda #%00000010 ; Change banking mode 8 | sta $201 9 | ldx #$12 10 | - lda b3_fe09+3, x 11 | sta $202,x 12 | dex 13 | bpl - 14 | 15 | lda #$a9 16 | sta $215 17 | lda #5 ; load bank 5 18 | sta $216 19 | ldx #$15 20 | - lda b3_ff96, x 21 | sta $217,x 22 | dex 23 | bpl - 24 | lda #>(credit_start-1) 25 | pha 26 | lda #<(credit_start-1) 27 | pha 28 | jmp $200 29 | 30 | exp_inc_enemy_death_ctr: 31 | lda CURRENT_TILE 32 | asl 33 | clc 34 | adc #160 35 | jsr exp_inc_mon_counter 36 | lda #0 37 | beq exp_inc_counter 38 | 39 | exp_count_win: 40 | lda CURRENT_TILE 41 | asl 42 | clc 43 | adc #80 44 | bne exp_inc_mon_counter 45 | exp_count_encounter: 46 | lda CURRENT_TILE 47 | asl 48 | exp_inc_mon_counter: 49 | tax 50 | ldy $6670,x 51 | iny 52 | bne + 53 | inc $6671,x 54 | + tya 55 | sta $6670,x 56 | rts 57 | 58 | exp_count_spell_use: 59 | lda SELECTED_ITEM 60 | asl 61 | clc 62 | adc #$2c 63 | exp_inc_counter: 64 | tax 65 | ldy $6630,x 66 | iny 67 | bne + 68 | inc $6631,x 69 | + tya 70 | sta $6630,x 71 | exp_load_last_bank: 72 | lda $7004 73 | jmp store_and_load_prg_bank 74 | 75 | exp_sort_inventory: 76 | ldx #$03 77 | - lda ITEMS,x 78 | and #$0f 79 | sta $a8,x 80 | lda ITEMS,x 81 | lsr a 82 | lsr a 83 | lsr a 84 | lsr a 85 | sta $ac,x 86 | lda #$00 87 | sta ITEMS,x 88 | dex 89 | bpl - 90 | lda #$00 91 | -- ldx #$07 92 | - cmp $a8,x 93 | bcs + 94 | lda $a8,x 95 | stx $a7 96 | + dex 97 | bpl - 98 | cmp #$00 99 | beq + 100 | jsr b3_e01b ; add the next item 101 | ldx $a7 102 | lda #$00 103 | sta $a8,x 104 | beq -- 105 | + jmp exp_load_last_bank 106 | 107 | ; exp_torch_in_battle: 108 | ; cmp #$04 ; is this a torch? 109 | ; bne +++ ; no, go to next check 110 | ; lda #$01 111 | ; jsr $e04b ; remove the item from inventory 112 | ; jsr $c7c5 ; show the "hurled a torch" message 113 | ; hex 29 114 | ; lda $e0 115 | ; cmp #$10 ; are we fighting a metal slime? 116 | ; bne ++ ; no, go to higher damage 117 | ; - jsr $c55b ; run the rng cycle routine 118 | ; lda $95 ; load a random number 119 | ; and #$01 ; limit to 0-1 120 | ; bne + ; did we hit it? 121 | ; jmp $e658 ; A miss! 122 | ; + jmp $e694 ; yes, go to damage routine 123 | ; ++ jsr $c55b ; run the rng cycle routine 124 | ; lda $95 ; load a random number 125 | ; and #$03 ; limit to 0-3 126 | ; clc 127 | ; adc #$06 ; add 6 128 | ; jmp $e694 ; jump to damage routine 129 | ; +++ cmp #$05 ; c9 04 ; Fairy Water 130 | ; bne + 131 | ; lda #$02 132 | ; jsr $e04b ; remove the item from inventory 133 | ; jsr $c7c5 ; show the "sprinked fairy water" message 134 | ; hex 2a 135 | ; lda $e0 136 | ; cmp #$10 ; metal slime 137 | ; beq - 138 | ; jmp $e744 139 | ; + jmp $e6fd ; 4c fd e6 140 | 141 | .org $c000 142 | -------------------------------------------------------------------------------- /expansion/exp_bank_5.asm: -------------------------------------------------------------------------------- 1 | .base $c000 2 | 3 | FAMISTUDIO_DPCM_OFF: 4 | ; .incbin music/music.dmc 5 | 6 | .org $fffa 7 | 8 | .word nmi 9 | .word $200 10 | .word irq 11 | -------------------------------------------------------------------------------- /expansion/famistudio_conf.asm: -------------------------------------------------------------------------------- 1 | 2 | FAMISTUDIO_CFG_EXTERNAL = 1 3 | ;====================================================================================================================== 4 | ; 1) SEGMENT CONFIGURATION 5 | ;====================================================================================================================== 6 | 7 | FAMISTUDIO_ASM6_ZP_ENUM = $00F0 8 | FAMISTUDIO_ASM6_BSS_ENUM = $0400 9 | ; FAMISTUDIO_ASM6_CODE_BASE = $8000 10 | 11 | ;====================================================================================================================== 12 | ; 2) AUDIO EXPANSION CONFIGURATION 13 | ;====================================================================================================================== 14 | 15 | ; Konami VRC6 (2 extra square + saw) 16 | ; FAMISTUDIO_EXP_VRC6 = 1 17 | 18 | ; Konami VRC7 (6 FM channels) 19 | ; FAMISTUDIO_EXP_VRC7 = 1 20 | 21 | ; Nintendo MMC5 (2 extra squares, extra DPCM not supported) 22 | ; FAMISTUDIO_EXP_MMC5 = 1 23 | 24 | ; Sunsoft S5B (2 extra squares, advanced features not supported.) 25 | ; FAMISTUDIO_EXP_S5B = 1 26 | 27 | ; Famicom Disk System (extra wavetable channel) 28 | ; FAMISTUDIO_EXP_FDS = 1 29 | 30 | ; Namco 163 (between 1 and 8 extra wavetable channels) + number of channels. 31 | ; FAMISTUDIO_EXP_N163 = 1 32 | ; FAMISTUDIO_EXP_N163_CHN_CNT = 4 33 | 34 | ;====================================================================================================================== 35 | ; 3) GLOBAL ENGINE CONFIGURATION 36 | ;====================================================================================================================== 37 | 38 | ; FAMISTUDIO_CFG_PAL_SUPPORT = 1 39 | FAMISTUDIO_CFG_NTSC_SUPPORT = 1 40 | 41 | ; Support for sound effects playback + number of SFX that can play at once. 42 | FAMISTUDIO_CFG_SFX_SUPPORT = 0 43 | FAMISTUDIO_CFG_SFX_STREAMS = 0 44 | 45 | ; Blaarg's smooth vibrato technique. Eliminates phase resets ("pops") on square channels. Will be ignored if SFX are 46 | ; enabled since they are currently incompatible with each other. This might change in the future. 47 | FAMISTUDIO_CFG_SMOOTH_VIBRATO = 1 48 | 49 | ; Enables DPCM playback support. 50 | FAMISTUDIO_CFG_DPCM_SUPPORT = 1 51 | 52 | ; Must be enabled if you are calling sound effects from a different thread than the sound engine update. 53 | ; FAMISTUDIO_CFG_THREAD = 1 54 | 55 | ;====================================================================================================================== 56 | ; 4) SUPPORTED FEATURES CONFIGURATION 57 | ;====================================================================================================================== 58 | ; FAMISTUDIO_USE_FAMITRACKER_TEMPO = 1 59 | 60 | FAMISTUDIO_USE_PITCH_TRACK = 1 61 | FAMISTUDIO_USE_RELEASE_NOTES = 1 62 | FAMISTUDIO_USE_SLIDE_NOTES = 1 63 | FAMISTUDIO_USE_VIBRATO = 1 64 | FAMISTUDIO_USE_VOLUME_TRACK = 1 65 | FAMISTUDIO_USE_ARPEGGIO = 1 66 | ; FAMISTUDIO_DPCM_OFF = $c000 67 | 68 | -------------------------------------------------------------------------------- /expansion/music/1943.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/1943.fms -------------------------------------------------------------------------------- /expansion/music/batman.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/batman.fms -------------------------------------------------------------------------------- /expansion/music/bloody_tears.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/bloody_tears.fms -------------------------------------------------------------------------------- /expansion/music/bubble_man.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/bubble_man.fms -------------------------------------------------------------------------------- /expansion/music/danger_and_determination.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/danger_and_determination.fms -------------------------------------------------------------------------------- /expansion/music/flash_man.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/flash_man.fms -------------------------------------------------------------------------------- /expansion/music/gimmick_2A03.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/gimmick_2A03.fms -------------------------------------------------------------------------------- /expansion/music/guardian_legend.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/guardian_legend.fms -------------------------------------------------------------------------------- /expansion/music/journey_to_silius.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/journey_to_silius.fms -------------------------------------------------------------------------------- /expansion/music/moving_forward.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/moving_forward.fms -------------------------------------------------------------------------------- /expansion/music/ninja_gaiden.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/ninja_gaiden.fms -------------------------------------------------------------------------------- /expansion/music/on_the_hunt.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/on_the_hunt.fms -------------------------------------------------------------------------------- /expansion/music/shadow_of_the_ninja.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/shadow_of_the_ninja.fms -------------------------------------------------------------------------------- /expansion/music/shatterhand.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/shatterhand.fms -------------------------------------------------------------------------------- /expansion/music/shovel_knight_2A03.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/shovel_knight_2A03.fms -------------------------------------------------------------------------------- /expansion/music/silver_surfer.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/silver_surfer.fms -------------------------------------------------------------------------------- /expansion/music/tecmo_world_wrestling.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/tecmo_world_wrestling.fms -------------------------------------------------------------------------------- /expansion/music/the_end.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/the_end.fms -------------------------------------------------------------------------------- /expansion/music/wood_man.fms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/expansion/music/wood_man.fms -------------------------------------------------------------------------------- /notes/enemy_data.txt: -------------------------------------------------------------------------------- 1 | Enemy Data ($5E5B - $60DB) | | 2 | ============================ | =========================== | ============================= 3 | 0x0 | Strength | 4 | 0x1 | Agility | 5 | 0x2 | Max HP | 6 | 0x3 | Attack Pattern | 7 | 0x4 | Sleep/Stopspell resist | Nybbles 8 | 0x5 | Hurt resist/Dodge | Nybbles 9 | 0x6 | XP | 10 | 0x7 | Max Gold + 1 | 11 | 0x8 - 0xF | Sprite Data?? | 12 | | | 13 | | | 14 | ============================ | =========================== | ============================= 15 | Pattern bits | | 16 | ============================ | =========================== | ============================= 17 | 0x3 | Chance to do special move 2 | 18 | 0xC | Special move 2 | hurt 00xx 19 | | | hurtmore 01xx 20 | | | fire breath 10xx 21 | | | strong fire breath 11xx 22 | | | 23 | 0x30 | Chance to do special move 1 | 24 | 0xC0 | Special move 1 | sleep 00xx 25 | | | stopspell 01xx 26 | | | heal 10xx 27 | | | healmore 11xx 28 | -------------------------------------------------------------------------------- /notes/free_space.txt: -------------------------------------------------------------------------------- 1 | End addresses are non-inclusive 2 | Addresses are hex, other values are decimal 3 | 4 | =============================================================================== 5 | 6 | Free Space in the Original ROM 7 | 8 | Start | End | Size | Bank | Comments 9 | ------------------------------------------------------------------------------- 10 | 3FCA | 3FD8 | 14 | 0 | Unused space (FF) 11 | 7E9E | 7FD8 | 314 | 1 | Unused space (FF) 12 | BED1 | BFD8 | 263 | 2 | Unused space (FF) 13 | C288 | C4F5 | 621 | 3 | This section of code goes unused 14 | C6C9 | C6F0 | 39 | 3 | This section of code goes unused 15 | C7EC | C9B5 | 457 | 3 | This section of code goes unused 16 | F232 | F35B | 129 | 3 | This section of data goes unused 17 | FF54 | FF74 | 32 | 3 | Unused space (FF) 18 | FF7D | FF8E | 11 | 3 | Unused space (FF) 19 | 20 | =============================================================================== 21 | 22 | Newly Freed space 23 | 24 | Start | End | Size | Bank | Comments 25 | ------------------------------------------------------------------------------- 26 | E158 | E19A | 42 | 3 | Freed by the search/take rewrite. 27 | 28 | =============================================================================== 29 | 30 | Space used by the randomizer 31 | 32 | Start | End | Size | Bank | Comments 33 | ------------------------------------------------------------------------------- 34 | 7EA0 | 7ECD | 45 | 1 | Menu Wrap 35 | 7ECD | 7EFB | 46 | 1 | Menu Wrap 36 | 7EFB | 7F02 | 7 | 1 | Menu Wrap 37 | 7F02 | 7F0A | 8 | 1 | Menu Wrap 38 | C475 | C4BC | 71 | 3 | Torch/FW use in battle 39 | C4BC | C4CE | 18 | 3 | Three's Company 40 | C4CE | C4E8 | 26 | 3 | Cursed Princess 41 | C4E8 | C4F5 | 13 | 3 | Scared Metal Slimes 42 | C7EC | C815 | 41 | 3 | Window data for new "Begin New Quest" window 43 | E158 | E16E | 22 | 3 | Scaled Metal Slime XP 44 | FF7D | FF8E | 17 | 3 | Fighter's Ring fix 45 | FF54 | FF57 | 3 | 3 | Fighter's Ring fix 46 | FF54 | FF73 | 31 | 3 | Death Necklace changes 47 | 48 | -------------------------------------------------------------------------------- /notes/items.txt: -------------------------------------------------------------------------------- 1 | Equipment value | 2 | ================ | ==== 3 | == Weapons == | 4 | Bamboo Pole | 0x20 5 | Club | 0x40 6 | Copper Sword | 0x60 7 | Hand Axe | 0x80 8 | Broad Sword | 0xa0 9 | Flame Sword | 0xc0 10 | Erdrick's Sword | 0xe0 11 | | 12 | == Armor == | 13 | Clothes | 0x4 14 | Leather Armor | 0x8 15 | Chain Mail | 0xc 16 | Half Plate Armor | 0x10 17 | Full Plate Armor | 0x14 18 | Magic Armor | 0x18 19 | Erdrick's Armor | 0x1c 20 | | 21 | == Shields == | 22 | Small Shield | 0x1 23 | Large Shield | 0x2 24 | Silver Shield | 0x3 25 | 26 | 27 | Items | 28 | ===== | =================== 29 | 0x1 | Torch 30 | 0x2 | Fairy Water 31 | 0x3 | Wings 32 | 0x4 | Dragon's Scale 33 | 0x5 | Fairy Flute 34 | 0x6 | Fighter's Ring 35 | 0x7 | Erdrick's Token 36 | 0x8 | Gwaelin's Love 37 | 0x9 | Cursed Belt 38 | 0xa | Silver Harp 39 | 0xb | Death Necklace 40 | 0xc | Stones of Sunlight 41 | 0xd | Staff of Rain 42 | 0xe | Rainbow Drop 43 | 0xf | Herb (glitched) 44 | 45 | 46 | == Chests == 47 | Map | X | Y | contents 48 | ========================== | == | == | ========================= 49 | 0x4 (Tantegel) | 1 | 13 | 19 (6 Gold) 50 | 0x4 (Tantegel) | 1 | 15 | 19 (6 Gold) 51 | 0x4 (Tantegel) | 2 | 14 | 19 (6 Gold) 52 | 0x4 (Tantegel) | 3 | 15 | 19 (6 Gold) 53 | 0x5 (Tantegel Throne Room) | 4 | 4 | 22 (120 Gold) 54 | 0x5 (Tantegel Throne Room) | 5 | 4 | 4 (Torch) 55 | 0x5 (Tantegel Throne Room) | 6 | 1 | 3 (Key) 56 | 0xb (Rimuldar) | 24 | 23 | 6 (Wings) 57 | 0x9 (Garinham) | 8 | 5 | 20 (10 Gold) 58 | 0x9 (Garinham) | 8 | 6 | 2 (Herb) 59 | 0x9 (Garinham) | 9 | 5 | 4 (Torch) 60 | 0x6 (Charlock Throne Room) | 11 | 11 | 2 (Herb) 61 | 0x6 (Charlock Throne Room) | 11 | 12 | 21 (500 Gold) 62 | 0x6 (Charlock Throne Room) | 11 | 13 | 6 (Wings) 63 | 0x6 (Charlock Throne Room) | 12 | 12 | 3 (Key) 64 | 0x6 (Charlock Throne Room) | 12 | 13 | 12 (Cursed Belt) 65 | 0x6 (Charlock Throne Room) | 13 | 13 | 2 (Herb) 66 | 0xc (Tantegel Basement) | 4 | 5 | 15 (Stones of Sunlight) 67 | 0xd (Northern Shrine) | 3 | 4 | 16 (Staff of Rain) 68 | 0x24 (Garin's Grave Lv 1) | 11 | 0 | 2 (Herb) 69 | 0x24 (Garin's Grave Lv 1) | 12 | 0 | 18 (5 Gold) 70 | 0x24 (Garin's Grave Lv 1) | 13 | 0 | 19 (6 Gold) 71 | 0x1a (Garin's Grave Lv 3) | 1 | 1 | 12 (Cursed Belt) 72 | 0x1a (Garin's Grave Lv 3) | 13 | 6 | 13 (Silver Harp) 73 | 0x10 (Charlock Cave Lv 2) | 5 | 5 | 17 (Erdrick's Sword) 74 | 0x17 (Mountain Cave Lv 2) | 1 | 6 | 14 (Death Necklace) 75 | 0x17 (Mountain Cave Lv 2) | 3 | 2 | 4 (Torch) 76 | 0x17 (Mountain Cave Lv 2) | 2 | 2 | 9 (Fighter's Ring) 77 | 0x17 (Mountain Cave Lv 2) | 10 | 9 | 20 (10 Gold) 78 | 0x16 (Mountain Cave Lv 1) | 13 | 5 | 2 (Herb) 79 | 0x1d (Erdrick's Cave Lv 2) | 9 | 3 | 23 (Erdrick's Tablet) 80 | 81 | 82 | ==Chest contents== 83 | Byte | What it is 84 | ==== | =========================== 85 | 0x0 | Broken 86 | 0x1 | Broken? 87 | 0x2 | Herb 88 | 0x3 | Magic Key 89 | 0x4 | Torch 90 | 0x5 | Fairy Water 91 | 0x6 | Wings 92 | 0x7 | Dragon's Scale 93 | 0x8 | Fairy Flute 94 | 0x9 | Fighter's Ring 95 | 0xA | Erdrick's Token 96 | 0xB | Gwaelin's Love 97 | 0xC | Cursed Belt 98 | 0xD | Silver Harp 99 | 0xE | Death Necklace/ 5-20 Gold 100 | 0xF | Stones of Sunlight 101 | 0x10 | Staff of Rain 102 | 0x11 | Erdrick's Sword 103 | 0x12 | 5-20 Gold 104 | 0x13 | 6-13 Gold 105 | 0x14 | 10-17 gold 106 | 0x15 | 500-756 gold 107 | 0x16 | 120 Gold 108 | 0x17 | Erdrick's Tablet 109 | 110 | -------------------------------------------------------------------------------- /notes/maps.txt: -------------------------------------------------------------------------------- 1 | Map Number | ROM Address | Map | Size | Border Tile | Border Tile address 2 | ========== | =============== | ==================== | ======= | ============= | =================== 3 | 1 | 0x1D6D - 0x2668 | Overworld | 120x120 | 0x0F (water) | 0x33 4 | 2 | 0xC0 - 0x187 | Charlock | 20x20 | 0x06 (swamp) | 0x38 5 | 3 | 0x188 - 0x24f | Hauksness | 20x20 | 0x01 (desert) | 0x3d 6 | 4 | 0x250 - 0x411 | Tantegel | 30x30 | 0x00 (grass) | 0x42 7 | 5 | 0x412 - 0x444 | Tantegel Throne Room | 10x10 | 0x15 (roof) | 0x47 8 | 6 | 0x444 - 0x605 | Charlock Throne Room | 30x30 | 0x0F (water) | 0x4c 9 | 7 | 0x606 - 0x825 | Kol | 24x24 | 0x0B (trees) | 0x51 10 | 8 | 0x726 - 0x8E7 | Brecconary | 30x30 | 0x00 (grass) | 0x56 11 | 9 | 0xAAA - 0xB71 | Garinham | 20x20 | 0x00(grass) | 0x5b 12 | 10 | 0x8E8 - 0xAA9 | Cantlin | 30x30 | 0x04 (brick) | 0x60 13 | 11 | 0xB72 - 0xD33 | Rimuldar | 30x30 | 0x00 (grass) | 0x65 14 | 12 | 0xD34 - 0xD65 | Tantegel Basement | 10x10 | 0x10 (block) | 0x6a 15 | 13 | 0xD66 - 0xD97 | Northern Shrine | 10x10 | 0x10 (block) | 0x6f 16 | 14 | 0xD98 - 0xDC9 | Southern Shrine | 10x10 | 0x10 (block) | 0x74 17 | 15 | 0xDCA - 0xE91 | Charlock Cave Lv 1 | 20x20 | 0x10 (block) | 0x79 18 | 16 | 0xE92 - 0xEC3 | Charlock Cave Lv 2 | 10x10 | 0x10 (block) | 0x7e 19 | 17 | 0xEC4 - 0xEF5 | Charlock Cave Lv 3 | 10x10 | 0x10 (block) | 0x83 20 | 18 | 0xEF6 - 0xF27 | Charlock Cave Lv 4 | 10x10 | 0x10 (block) | 0x88 21 | 19 | 0xF28 - 0xF59 | Charlock Cave Lv 5 | 10x10 | 0x10 (block) | 0x8d 22 | 20 | 0xF5A - 0xF8B | Charlock Cave Lv 6 | 10x10 | 0x10 (block) | 0x92 23 | 21 | 0xF8C - 0xFE5 | Swamp Cave | 6x30 | 0x10 (block) | 0x97 24 | 22 | 0xFE6 - 0x1047 | Mountain Cave | 14x14 | 0x10 (block) | 0x9c 25 | 23 | 0x1048 - 0x10A9 | Mountain Cave Lv 2 | 14x14 | 0x10 (block) | 0xa1 26 | 24 | 0x10AA - 0x1171 | Garin's Grave Lv 1 | 20x20 | 0x10 (block) | 0xa6 27 | 25 | 0x126C - 0x12BF | Garin's Grave Lv 2 | 14x12 | 0x10 (block) | 0xab 28 | 26 | 0x1172 - 0x1239 | Garin's Grave Lv 3 | 20x20 | 0x10 (block) | 0xb0 29 | 27 | 0x123A - 0x126B | Garin's Grave Lv 4 | 10x10 | 0x10 (block) | 0xb5 30 | 28 | 0x12C0 - 0x12F1 | Erdrick's Cave | 10x10 | 0x10 (block) | 0xba 31 | 29 | 0x12F2 - 0x1323 | Erdrick's Cave Lv 2 | 10x10 | 0x10 (block) | 0xbf 32 | 33 | 34 | Locations | Map | X | Y 35 | ========================== | === | === | === 36 | Tantegel | 1 | 43 | 43 37 | Brecconary | 1 | 48 | 41 38 | Garinham | 1 | 2 | 2 39 | | | | 40 | Kol | 1 | 104 | 10 41 | Northern Shrine | 1 | 81 | 1 42 | | | | 43 | Erdrick's Cave | 1 | 28 | 12 44 | Hauksness | 1 | 25 | 89 45 | Cantlin | 1 | 73 | 102 46 | Rimuldar | 1 | 102 | 72 47 | Southern Shrine | 1 | 108 | 109 48 | | | | 49 | Swamp cave entrance | 1 | 104 | 44 50 | Mountain Cave | 1 | 29 | 57 51 | Swamp cave exit | 1 | 104 | 49 52 | Charlock Castle | 1 | 48 | 48 53 | | | | 54 | Magic refill | 4 | 18 | 26 55 | Gwaelin | 21 | 5 | 19 56 | Flute | 7 | 9 | 6 57 | Erdrick's Armor | 3 | 18 | 12 58 | Erdrick's Token | 1 | 83 | 113 59 | Silver Harp | 26 | 13 | 6 60 | Stones of Sunlight | 12 | 4 | 5 61 | Staff of Rain guard | 13 | 5 | 4 62 | Staff of Rain | 13 | 3 | 4 63 | Rainbow Drop | 14 | 3 | 5 64 | Bridge to Charlock | 1 | 65 | 49 65 | Entrance to Charlock Cave | 2 | 10 | 1 66 | Erdrick's Sword | 16 | 5 | 5 67 | Dragonlord | 6 | 17 | 24 68 | 69 | 70 | 71 | Border Tiles | 72 | ============= | ==== 73 | Grass | 0x0 74 | Desert | 0x1 75 | Hills | 0x2 76 | Stairs up | 0x3 77 | Brick | 0x4 78 | Stairs down | 0x5 79 | Swamp | 0x6 80 | Town | 0x7 81 | Cave | 0x8 82 | Castle | 0x9 83 | Bridge | 0xA 84 | Trees | 0xB 85 | Treasure chest | 0xC 86 | Barrier | 0xD 87 | Orange block | 0xE 88 | Water | 0xF 89 | Block | 0x10 90 | Door | 0x11 91 | Moutain | 0x12 92 | Shop sign | 0x13 93 | Inn Sign | 0x14 94 | Root | 0x15 95 | | 0x16 96 | | 0x17 97 | | 0x18 98 | | 0x19 99 | | 0x1A 100 | | 0x1C 101 | | 0x1D 102 | | 0x1E 103 | | 0x1F 104 | 105 | -------------------------------------------------------------------------------- /notes/music.txt: -------------------------------------------------------------------------------- 1 | Address | Value | Song Name | Location 2 | 31BF | 5 | Overworld | Overworld 3 | 31C0 | 6 | Cave 1 | Charlock 4 | 31C1 | 9 | Cave 4 | Hauksness 5 | 31C2 | 3 | Castle | Tantegel 6 | 31C3 | 2 | Throne Room | Tantegel Throne Room 7 | 31C4 | D | Cave 8 | Charlock Throne Room 8 | 31C5 | 4 | Town | Kol 9 | 31C6 | 4 | Town | Brecconary 10 | 31C7 | 4 | Town | Garinham 11 | 31C8 | 4 | Town | Cantlin 12 | 31C9 | 4 | Town | Rimuldar 13 | 31CA | 3 | Castle | Tantegel Basement 14 | 31CB | 3 | Castle | Northern Shrine 15 | 31CC | 3 | Castle | Southern Shrine 16 | 31CD | 7 | Cave 2 | Charlock Cave Lv 1 17 | 31CE | 8 | Cave 3 | Charlock Cave Lv 2 18 | 31CF | 9 | Cave 4 | Charlock Cave Lv 3 19 | 31D0 | A | Cave 5 | Charlock Cave Lv 4 20 | 31D1 | B | Cave 6 | Charlock Cave Lv 5 21 | 31D2 | C | Cave 7 | Charlock Cave Lv 6 22 | 31D3 | 6 | Cave 1 | Swamp Cave 23 | 31D4 | 6 | Cave 1 | Mountain Cave 24 | 31D5 | 7 | Cave 2 | Mountain Cave Lv 2 25 | 31D6 | 6 | Cave 1 | Garin's Grave Lv 1 26 | 31D7 | 7 | Cave 2 | Garin's Grave Lv 2 27 | 31D8 | 8 | Cave 3 | Garin's Grave Lv 3 28 | 31D9 | 9 | Cave 4 | Garin's Grave Lv 4 29 | 31DA | 6 | Cave 1 | Erdrick's Cave 30 | 31DB | 7 | Cave 2 | Erdrick's Cave Lv 2 31 | -------------------------------------------------------------------------------- /notes/ram.txt: -------------------------------------------------------------------------------- 1 | Address | Function | Notes 2 | =============== | ======================= | ============================================================================ 3 | 0x3a | X position | 4 | 0x3b | Y position | 5 | 0x45 | Current Map | 6 | 0x47 | Controller 1 Poll | 0x80=right, 0x40=left, 0x20=down, 0x10=up, 0x8=start, 0x4=select, 0x2=B, 0x1=A 7 | 0x51 - ?? | NPC Data | 16 bits -------------------------> 3 bits -> sprite 8 | | | 5 bits -> x coordinate 9 | | | 3 bits -> direction 10 | | | 5 bits -> y coordinate 11 | 0x8e | Map X pos | 12 | 0x8f | Map Y pos | 13 | 0x94-0x95 | RNG State | 14 | 0xba - 0xbb | Exp Points | 15 | 0xbc - 0xbd | Gold | 16 | 0xbe | Equipment | 17 | 0xbf | Key count | 18 | 0xc0 | Herb count | 19 | 0xc1 | Item slot 1 & 2 | 20 | 0xc2 | Item slot 3 & 4 | 21 | 0xc3 | Item slot 5 & 6 | 22 | 0xc4 | Item slot 7 & 8 | 23 | 0xc5 | Current HP | 24 | 0xc6 | Current MP | 25 | 0xc7 | Level | 26 | 0xc8 | Strength | Read-only 27 | 0xc9 | Agility | Read-only 28 | 0xca | Max HP | Read-only 29 | 0xcb | Max MP | Read-only 30 | 0xcc | Attack Power | Read-only 31 | 0xcd | Defense Power | Read-only 32 | 0xce | Spells unlocked | 0x80=repel, 0x40=return, 0x20=outside, 0x10=stopspell, 33 | | | 0x8=radiant, 0x4=sleep, 0x2=hurt, 0x1=heal 34 | 0xcf | Spells/Quest Prog | 0x80=death necklace equipped, 0x40=cursed belt equipped, 35 | | | 0x20=fighters ring equipped, 0x10=dragon's scale equipped, 36 | | | 0x8=rainbow bridge, 0x4=stairs in charlock found, 0x2=hurtmore, 0x1=healmore 37 | 0xd0 | Light radius | For radiant 38 | 0xd1 | Cursor X? | 39 | 0xd2 | Cursor Y? | 40 | 0xd7 | Last selected menu item | 0x00 - 0x09 (0xFF for none) 41 | 0xd8 | Cursor X pos | 42 | 0xd9 | Cursor Y pos | 43 | 0xda | Radiant Timer | 44 | 0xdf | Status bits | 0x80=Hero asleep, 0x40=Enemy asleep, 0x20=Enemy's spell stopped, 45 | | | 0x10=Hero's spell stopped, 0x8=You have left throne room, 0x4=Death necklace obtained, 0x2=Returned Gwaelin, 46 | | | 0x1=Carrying Gwaelin 47 | 0xe0 | Current Tile | Enemy index when in battle 48 | 0xe2 | Enemy HP | Does not clear after battle. 49 | | | 50 | 0xe4 | Quest progress | 0x80=unused, 0x40=Killed Green Dragon, 0x20=unused, 0x10=unused, 0x8=unused, 51 | | | 0x4=Killed Dragonlord, 0x2=Killed Golem, 0x1=unused 52 | 0xe5 | Message Speed | 0 = fast, 1 = normal, 2 = slow 53 | 0x320 | Treasure chest array | 54 | 0x6000-0x8000 | SRAM | 55 | 56 | -------------------------------------------------------------------------------- /notes/rom.txt: -------------------------------------------------------------------------------- 1 | Address | Use | Notes 2 | ====================== | ===================================== | ======================================================= 3 | 0 - F | iNES header | 4 | 2F - BF | Map Metadata | (5 bytes) 1-2 = Pointer to data, 3=X size, 4=Y size, 5 | | | 5=Border tile 6 | | | 7 | C0 - 188 | Charlock Map | 8 | 189 - 250 | Hauksness Map | 9 | 251 - 411 | Tantegel Map | 10 | 412 - 443 | Tantegel Throne Room Map | 11 | 445 - 606 | Charlock Throne room Map | 12 | Towns | | 13 | 607 - 726 | Kol Map | 14 | 727 - 8E8 | Brecconary Map | 15 | 8E8 - AAA | Cantlin Map | 16 | AAB - B72 | Garinham Map | 17 | B73 - D34 | Rimuldar Map | 18 | Shrines | | 19 | D34 - D65 | Tantegel Basement Map | 20 | D66 - D97 | Northern Shrine Map | 21 | D99 - DCA | Southern Shrine Map | 22 | Dragonlord Cavern | | 23 | DCB - E92 | Dragonlord Cavern B1 Map | 24 | E93 - EC4 | Dragonlord Cavern B2 Map | 25 | EC5 - EF6 | Dragonlord Cavern B3 Map | 26 | EF7 - F28 | Dragonlord Cavern B4 Map | 27 | F29 - F5A | Dragonlord Cavern B5 Map | 28 | F5B - F8C | Dragonlord Cavern B6 Map | 29 | Other Caves | | 30 | F8D - FE6 | Cave to Rimuldar Map | 31 | FE7 - 1048 | Cave West of Tantegel B1 Map | 32 | 1048 - 10A9 | Cave West of Tantegel B2 Map | 33 | 10AA - 1171 | Garin's Grave B1 Map | 34 | 1172 - 1239 | Garin's Grave B3 Map | 35 | 123A - 126B | Garin's Grave B4 Map | 36 | 126C - 12BF | Garin's Grave B2 Map | 37 | 12C0 - 12F1 | Erdrick's Cave B1 Map | 38 | 12F2 - 1323 | Erdrick's Cave B2 Map | 39 | Various Data | | 40 | 1957 - 1992 | Weapon & Item costs (calculation) | 41 | 19A1-19CB | Weapon Shop Inventory | 42 | 19CC - 19DE | Item Shop Inventory | 43 | 1A9B - 1A9D | Player palette (along with some npcs) | 44 | 1C9F - 1D62 | Layout data for fight background | 45 | 1D63 - 1D6C | MP Requirements for Magic Spells | 46 | 1D6D - 2662 | Overworld map | RLE encoded, 1st nibble is tile, 2nd how many - 1 47 | 2663 - 26DA | Overworld map pointers | 16 bits each - address of each row of the map. 48 | | | (value - 0x8000 + 16) 49 | 2C4B - 2C5A | Rainbow Bridge Replace Code? | 50 | 31BE - 31DB | Music Pointers | 51 | 3F30 - 3FB8 | Title Screen Data | 52 | 3F58-3F61 | (c)1986 ENIX | Title screen text 53 | 3F6D-3F75 | (c)1989 ENIX | Title screen text 54 | 3F82-3F95 | LICENSED TO NINTENDO | Title screen text 55 | 3FA1-3FB8 | TM TRADEMARK TO NINTENDO | Title screen text 56 | 44DB - 5363 | Music Data | http://datacrystal.romhacking.net/wiki/Dragon_Warrior:ROM_map#Music_Data 57 | 549F - 58D9 | Ending Text | 58 | 5DDD - 5E58 | Chest Data | Four bytes long: Map,X,Y,Contents 59 | 5E5B - 60DB | Enemy Data | Sixteen bytes each ---> 60 | 60DD - 6190 | Player stats | Strength, Agility, HP, MP, Spell Mask 61 | | | (2 bytes, big endian) 62 | 6FC7 - 752B | Menu Text | 63 | 7AC0 - 7EAD | Item, Enemy, and Spell Menu Text | 64 | 7E20 - 7E63 | Weapon & Item Costs (text) | 65 | 8039 - BCBA | Dialog text | 66 | A236 - A298 | NPC Token location text | 67 | AD95 - ADAC | "The spell will not work." | 68 | BEE1 - BFE7 | Empty Space | 69 | CBCC - ? | Death handling code | 70 | CD61 - CD77 | Axe Knight encounter code | 71 | CD78 - CD94 | Green Dragon encounter code | 72 | CD95 - CDA6 | Golem encounter code | 73 | D70A | Max number of herbs (6) | 74 | D81E | Max number or keys (6) | 75 | DB10 - DB1F | "Return" placement code | 76 | DE9B - DEB2 | Rainbow Drop use code | 77 | DF47 - DF68 | Gwaelin's Love Calculations | 78 | E11B-E159 | Token find code | 79 | E15A - E16F | Flute find code | 80 | E170 - E199 | Armor find code | 81 | E8E4 - E8F3 | Axe Knight run code | 82 | E90B - E91A | Green Dragon run code | 83 | E938 - E947 | Golem run code | 84 | EAF8 - EB1F | "Thou has leaned a new spell" code | Checks your level to see if you learned a spell 85 | F36C - F3A6 | Level up limits | 86 | F3D8 - F470 | Warp Data (From) | 3 bytes (map,x,y) 87 | F471 - F50A | Warp Data (To) | 3 bytes (map,x,y) 88 | F532-F551 | Overworld Enemy Zones? | 1 nybble each 89 | F552-F557 | Dungeon enemy zones? | 1 byte each 90 | F55F - F5C3 | Enemy Zone info | 5 bytes per zone, 20 zones. Each byte is an enemy ID 91 | 10010-1400E | Game Graphics | CHR ROM 92 | -------------------------------------------------------------------------------- /notes/warps.txt: -------------------------------------------------------------------------------- 1 | Offsets do not include ROM header 2 | 3 | From | Offset | Map | X | Y | To | Offset | Map | X | Y | Location | Index 4 | ==== | ====== | === | === | === | ==== | ====== | === | == | == | ==================== | 5 | F3C8 | 0 | 1 | 2 | 2 | F461 | 153 | 9 | 0 | 14 | Garinham | 0 6 | F3CB | 3 | 1 | 81 | 1 | F464 | 156 | 13 | 4 | 9 | Northern Shrine | 1 7 | F3CE | 6 | 1 | 104 | 10 | F477 | 159 | 7 | 19 | 23 | Kol | 2 8 | F3D1 | 9 | 1 | 48 | 41 | F46A | 162 | 8 | 0 | 15 | Brecconary | 3 9 | F3D4 | 12 | 1 | 43 | 43 | F46D | 165 | 4 | 11 | 29 | Tantegel | 4 10 | F3D7 | 15 | 1 | 104 | 44 | F470 | 168 | 21 | 0 | 0 | Swamp Cave | 5 11 | F3DA | 18 | 1 | 48 | 48 | F473 | 171 | 2 | 10 | 19 | Charlock | 6 12 | F3DD | 21 | 1 | 104 | 49 | F476 | 174 | 21 | 0 | 29 | Swamp Cave | 7 13 | F3E0 | 24 | 1 | 29 | 57 | F479 | 177 | 22 | 0 | 7 | Mountain Cave Lv. 1 | 8 14 | F3E3 | 27 | 1 | 102 | 72 | F47C | 180 | 11 | 29 | 14 | Rimuldar | 9 15 | F3E6 | 30 | 1 | 25 | 89 | F47F | 183 | 3 | 0 | 10 | Hauksness | 10 16 | F3E9 | 33 | 1 | 73 | 102 | F482 | 186 | 10 | 15 | 0 | Cantlin | 11 17 | F3EC | 36 | 1 | 108 | 109 | F495 | 189 | 14 | 0 | 4 | Southern Shrine | 12 18 | F3EF | 39 | 1 | 28 | 12 | F488 | 192 | 28 | 0 | 0 | Erdrick's Cave Lv. 1 | 13 19 | F3F2 | 42 | 2 | 10 | 1 | F48B | 195 | 15 | 9 | 0 | Charlock Cave Lv. 1 | 14 20 | F3F5 | 45 | 2 | 4 | 14 | F48E | 198 | 15 | 8 | 13 | Charlock Cave Lv. 1 | 15 21 | F3F8 | 48 | 2 | 15 | 14 | F491 | 201 | 15 | 17 | 15 | Charlock Cave Lv. 1 | 16 22 | F3FB | 51 | 4 | 29 | 29 | F494 | 204 | 12 | 0 | 4 | Tantegel Basement | 17 23 | F3FE | 54 | 5 | 8 | 8 | F497 | 207 | 4 | 7 | 7 | Tantegel | 18 24 | F401 | 57 | 9 | 19 | 0 | F49A | 210 | 24 | 6 | 11 | Garin's Grave Lv. 1 | 19 25 | F404 | 60 | 15 | 15 | 1 | F49D | 213 | 16 | 8 | 0 | Charlock Cave Lv. 2 | 20 26 | F407 | 63 | 15 | 13 | 7 | F4A0 | 216 | 16 | 4 | 4 | Charlock Cave Lv. 2 | 21 27 | F40A | 66 | 15 | 19 | 7 | F4A3 | 219 | 16 | 9 | 8 | Charlock Cave Lv. 2 | 22 28 | F40D | 69 | 15 | 14 | 9 | F4A6 | 222 | 16 | 8 | 9 | Charlock Cave Lv. 2 | 23 29 | F410 | 72 | 15 | 2 | 14 | F4A9 | 225 | 16 | 0 | 1 | Charlock Cave Lv. 2 | 24 30 | F413 | 75 | 15 | 2 | 4 | F4AC | 228 | 16 | 0 | 0 | Charlock Cave Lv. 2 | 25 31 | F416 | 78 | 15 | 8 | 19 | F4AF | 231 | 16 | 5 | 0 | Charlock Cave Lv. 2 | 26 32 | F419 | 81 | 16 | 3 | 0 | F4B2 | 234 | 17 | 7 | 0 | Charlock Cave Lv. 3 | 27 33 | F41C | 84 | 16 | 9 | 1 | F4B5 | 237 | 17 | 2 | 2 | Charlock Cave Lv. 3 | 28 34 | F41F | 87 | 16 | 0 | 8 | F4B8 | 240 | 17 | 5 | 4 | Charlock Cave Lv. 3 | 29 35 | F422 | 90 | 16 | 1 | 9 | F4BB | 243 | 17 | 0 | 9 | Charlock Cave Lv. 3 | 30 36 | F425 | 93 | 17 | 1 | 6 | F4BE | 246 | 18 | 0 | 9 | Charlock Cave Lv. 4 | 31 37 | F428 | 96 | 17 | 7 | 7 | F4C1 | 249 | 18 | 7 | 7 | Charlock Cave Lv. 4 | 32 38 | F42B | 99 | 18 | 2 | 2 | F4C4 | 252 | 19 | 9 | 0 | Charlock Cave Lv. 5 | 33 39 | F42E | 102 | 18 | 8 | 1 | F4C7 | 255 | 19 | 4 | 0 | Charlock Cave Lv. 5 | 34 40 | F431 | 105 | 19 | 5 | 5 | F4CA | 258 | 20 | 0 | 0 | Charlock Cave Lv. 6 | 35 41 | F434 | 108 | 19 | 0 | 0 | F4CD | 261 | 20 | 0 | 6 | Charlock Cave Lv. 6 | 36 42 | F437 | 111 | 20 | 9 | 0 | F4D0 | 264 | 20 | 0 | 0 | Charlock Cave Lv. 6 | 37 43 | F43A | 114 | 20 | 9 | 6 | F4D3 | 267 | 6 | 10 | 29 | Charlock Throne Room | 38 44 | F43D | 117 | 22 | 0 | 0 | F4D6 | 270 | 23 | 0 | 0 | Mountain Cave Lv. 2 | 39 45 | F440 | 120 | 22 | 6 | 5 | F4D9 | 273 | 23 | 6 | 5 | Mountain Cave Lv. 2 | 40 46 | F443 | 123 | 22 | 12 | 12 | F4DC | 276 | 23 | 12 | 12 | Mountain Cave Lv. 2 | 41 47 | F446 | 126 | 24 | 1 | 18 | F4DF | 279 | 25 | 11 | 2 | Garin's Grave Lv. 2 | 42 48 | F449 | 129 | 25 | 1 | 1 | F4E2 | 282 | 26 | 1 | 26 | Garin's Grave Lv. 3 | 43 49 | F44C | 132 | 25 | 12 | 1 | F4E5 | 285 | 26 | 18 | 1 | Garin's Grave Lv. 3 | 44 50 | F44F | 135 | 25 | 5 | 6 | F4E8 | 288 | 26 | 6 | 11 | Garin's Grave Lv. 3 | 45 51 | F452 | 138 | 25 | 1 | 10 | F4EB | 291 | 26 | 2 | 17 | Garin's Grave Lv. 3 | 46 52 | F455 | 141 | 25 | 12 | 10 | F4EE | 294 | 26 | 18 | 13 | Garin's Grave Lv. 3 | 47 53 | F458 | 144 | 26 | 9 | 5 | F4F1 | 297 | 27 | 0 | 4 | Garin's Grave Lv. 4 | 48 54 | F45B | 147 | 26 | 10 | 9 | F4F4 | 300 | 27 | 5 | 4 | Garin's Grave Lv. 4 | 49 55 | F45E | 150 | 28 | 9 | 9 | F4F7 | 303 | 29 | 8 | 9 | Erdrick's Cave Lv 2 | 50 56 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 1 ]; then 4 | echo "Please specify a version number" 5 | exit 1 6 | fi; 7 | 8 | cd $(dirname $0)/build 9 | qmake CONFIG+="RELEASE CLI" ../dwrandomizer-cli.pro 10 | make 11 | cp dwrandomizer ../builds/dwrandomizer-cli 12 | rm -r * 13 | 14 | qmake CONFIG+=RELEASE ../dwrandomizer.pro 15 | make 16 | cp dwrandomizer ../builds/ 17 | rm -r * 18 | 19 | qmake-win CONFIG+=RELEASE ../dwrandomizer.pro 20 | make 21 | cp release/dwrandomizer.exe ../builds 22 | rm -r * 23 | 24 | cd ../builds 25 | cp ../README.md ./ 26 | tar Jcf dwrandomizer-$1-linux.tar.xz dwrandomizer-cli dwrandomizer README.md 27 | 28 | mv README.md README.txt 29 | zip dwrandomizer-$1-windows.zip dwrandomizer.exe README.txt 30 | 31 | -------------------------------------------------------------------------------- /resources/dwrandomizer.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=DWRandomizer 3 | Exec=/usr/bin/dwrandomizer 4 | Icon=dwrandomizer 5 | Type=Application 6 | Categories=Utility; 7 | -------------------------------------------------------------------------------- /tools/build_expansion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from glob import glob 4 | from subprocess import run 5 | from os.path import dirname, basename, realpath, join, exists 6 | from os import chdir, remove, getcwd 7 | from distutils.spawn import find_executable 8 | 9 | from ips import Patch 10 | 11 | 12 | def generate_header(): 13 | print("Generating header file...") 14 | with open('../common/expansion.h', 'w') as h, open('credits.lua', 'r') as f: 15 | h.write(f'/** This file is generated by {basename(__file__)} */\n') 16 | h.write('#ifndef _EXPANSION_H_\n') 17 | h.write('#define _EXPANSION_H_\n') 18 | h.write('\n') 19 | h.write('#include "dwr_types.h"\n') 20 | h.write('\n') 21 | h.write('enum hooktype {\n') 22 | h.write(' DIALOGUE,\n') 23 | h.write(' JSR = 0x20,\n') 24 | h.write(' JMP = 0x4c,\n') 25 | h.write('};\n') 26 | h.write('\n') 27 | h.write('enum subroutine {\n') 28 | for entry in f: 29 | k,v = [x.strip() for x in entry.split('=')] 30 | if not k[0].isalpha(): 31 | continue 32 | v = int(v, 16) 33 | if (0xc288 <= v < 0xf35b): 34 | h.write(f' {k.upper()} = 0x{v:X},\n') 35 | h.write('};\n') 36 | h.write('\n') 37 | h.write('void add_hook(dw_rom *rom, enum hooktype type, uint16_t address,\n') 38 | h.write(' enum subroutine to_addr);\n') 39 | h.write('void bank_3_patch(dw_rom *rom);\n') 40 | h.write('void fill_expansion(dw_rom *rom);\n') 41 | h.write('\n') 42 | h.write('#endif\n') 43 | 44 | def generate_c_file(b3_patch:bytes, expansion:bytes): 45 | print("Generating C file...") 46 | with open('../common/expansion.c', 'w') as c: 47 | c.write(f'/** This file is generated by {basename(__file__)} */\n') 48 | c.write(f'/** Assembly source available in the expansion directory */\n\n') 49 | c.write('#include \n') 50 | c.write('#include \n') 51 | c.write('#include "expansion.h"\n') 52 | c.write('#include "credit_music.h"\n') 53 | c.write('#include "dwr_types.h"\n') 54 | c.write('#include "patch.h"\n') 55 | c.write('\n') 56 | c.write('void add_hook(dw_rom *rom, enum hooktype type, uint16_t address,\n') 57 | c.write(' enum subroutine to_addr)\n') 58 | c.write('{\n') 59 | c.write(' switch(type) {\n') 60 | c.write(' case DIALOGUE:\n') 61 | c.write(' vpatch(rom, address, 4, 0x20, to_addr & 0xff, to_addr >> 8, 0xea);\n') 62 | c.write(' break;\n') 63 | c.write(' case JSR:\n') 64 | c.write(' case JMP:\n') 65 | c.write(' vpatch(rom, address, 3, type, to_addr & 0xff, to_addr >> 8);\n') 66 | c.write(' break;\n') 67 | c.write(' default:\n') 68 | c.write(' break;\n') 69 | c.write(' }\n') 70 | c.write('}\n') 71 | c.write('\n') 72 | c.write('void bank_3_patch(dw_rom *rom)\n') 73 | c.write('{\n') 74 | empty = [0xff] * len(b3_patch) 75 | p = Patch.create(empty, b3_patch) 76 | for r in p.records: 77 | c.write(f' vpatch(rom, 0x{r.address+0xc288:04x},' 78 | f'{len(r.content):4d},') 79 | for i,b in enumerate(r.content): 80 | if i: 81 | c.write(',') 82 | if not i % 12: 83 | c.write('\n ') 84 | c.write(f' 0x{b:02x}') 85 | c.write('\n );\n') 86 | c.write('}\n\n') 87 | 88 | c.write('void fill_expansion(dw_rom *rom)\n') 89 | c.write('{\n') 90 | empty = [0xff] * len(expansion) 91 | p = Patch.create(empty, expansion) 92 | for r in p.records: 93 | if r.address == 0x4000: 94 | continue # single byte placeholder for music, ignore it 95 | c.write(f' pvpatch(&rom->expansion[0x{r.address:04x}],' 96 | f'{len(r.content):4d},') 97 | for i,b in enumerate(r.content): 98 | if i: 99 | c.write(',') 100 | if not i % 12: 101 | c.write('\n ') 102 | c.write(f' 0x{b:02x}') 103 | c.write('\n );\n') 104 | c.write('}\n\n') 105 | 106 | def main(): 107 | chdir(join(dirname(realpath(__file__)), '..', 'expansion')) 108 | asm6 = find_executable('asm6f') or find_executable('asm6') 109 | if run([asm6, '-q', '-f', '-dDWR_BUILD', 'credits.asm', 'credits.nes'] 110 | ).returncode: 111 | return -1 112 | 113 | with open('credits.nes', 'rb') as f: 114 | f.seek(0xc000 + 16) 115 | expansion= f.read(0x10000) 116 | f.seek(0x1c288 + 16) 117 | b3_patch = f.read(0xf35b - 0xc288) 118 | generate_header() 119 | generate_c_file(b3_patch, expansion) 120 | remove('credits.nes') 121 | remove('credits.lua') 122 | 123 | if __name__ == "__main__": 124 | main() 125 | -------------------------------------------------------------------------------- /tools/build_music.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from glob import glob 4 | from subprocess import run 5 | from os.path import dirname, basename, realpath, join, exists 6 | from os import chdir, remove, getcwd 7 | from distutils.spawn import find_executable 8 | 9 | MUSIC_ADDR = 0x8000 10 | 11 | class Music: 12 | def __init__(self, name): 13 | self.filename = name 14 | self.name = name[:name.rfind('.')] 15 | print(f'Adding music {self.name}...') 16 | self.asm6 = find_executable('asm6f') or find_executable('asm6') 17 | self.famistudio = find_executable('famistudio') 18 | self.music = self.dmc = b'' 19 | self.addr = None 20 | self.assemble() 21 | 22 | def generate_asm(self): 23 | print('Generating assembly...') 24 | run([self.famistudio, f'{self.filename}', 'famistudio-asm-export', 25 | f'_{self.name}.asm', '-famistudio-asm-format:asm6']) 26 | 27 | def cleanup(self): 28 | remove('_m.asm') 29 | remove(f'_{self.name}.bin') 30 | remove(f'_{self.name}.asm') 31 | if exists(f'_{self.name}.dmc'): 32 | remove(f'_{self.name}.dmc') 33 | 34 | def assemble(self): 35 | self.generate_asm() 36 | with open('_m.asm', 'w') as f: 37 | f.write('FAMISTUDIO_DPCM_PTR EQU $00\n') 38 | f.write(f'.org ${MUSIC_ADDR:X}\n') 39 | f.write(f'include _{self.name}.asm\n') 40 | print('Assembling...') 41 | if run([self.asm6, '-q', '_m.asm', f'_{self.name}.bin']).returncode: 42 | exit(-1); 43 | with open(f'_{self.name}.bin', 'rb') as f: 44 | self.music = f.read() 45 | if exists(f'_{self.name}.dmc'): 46 | with open(f'_{self.name}.dmc', 'rb') as f: 47 | self.dmc = f.read() 48 | self.cleanup() 49 | 50 | def set_addr(self, addr): 51 | self.addr = addr 52 | 53 | def music_size(self): 54 | return len(self.music) 55 | 56 | def dmc_size(self): 57 | if self.dmc: 58 | return len(self.dmc) 59 | return 0; 60 | 61 | def total_size(self): 62 | return len(self.music) + len(self.dmc) 63 | 64 | def music_constant(self): 65 | if self.addr is None: 66 | raise ValueError(f"No address set for {self.name}") 67 | return (f"const uint8_t *music_{self.name}_start = " 68 | f"&music_bytes[{self.addr}];\n") 69 | 70 | def dmc_constant(self): 71 | if self.dmc: 72 | return (f"const uint8_t *dmc_{self.name}_start = " 73 | f"&music_bytes[{self.addr+self.music_size()}];\n") 74 | return '' 75 | 76 | def music_struct(self): 77 | return ("{ .start = music_%s_start, .size = 0x%x }" 78 | % (self.name, len(self.music))) 79 | 80 | def dmc_struct(self): 81 | if self.dmc: 82 | return ("{ .start = dmc_%s_start, .size = 0x%x }" 83 | % (self.name, len(self.dmc))) 84 | else: 85 | return "{ .start = NULL, .size = 0 }" 86 | 87 | def __bytes__(self): 88 | return self.music + (self.dmc or b'') 89 | 90 | def create_header(music:list[Music]): 91 | with open('../../common/credit_music.h', 'w') as h: 92 | h.write(f'/** This file is generated by {basename(__file__)} */\n\n') 93 | h.write('#ifndef _CREDIT_MUSIC_H\n') 94 | h.write('#define _CREDIT_MUSIC_H\n\n') 95 | h.write('#include \n') 96 | h.write('#include \n') 97 | h.write('#include "dwr_types.h"\n\n') 98 | 99 | h.write('struct music_data {\n') 100 | h.write(' const uint8_t *start;\n') 101 | h.write(' const size_t size;\n') 102 | h.write('};\n\n') 103 | h.write('void add_music(dw_rom* rom, int track);\n') 104 | h.write(f'const extern size_t track_count;\n') 105 | h.write('\n') 106 | h.write('#endif\n') 107 | print("Generated header file") 108 | 109 | def create_c_file(music:list[Music], music_data): 110 | with open('../../common/credit_music.c', 'w') as c: 111 | c.write(f'/** This file is generated by {basename(__file__)} */\n\n') 112 | c.write('#include \n') 113 | c.write('#include \n') 114 | c.write('#include "credit_music.h"\n') 115 | c.write('#include "dwr_types.h"\n') 116 | c.write('#include "patch.h"\n') 117 | c.write('\n'); 118 | c.write('static const uint8_t music_bytes[] = {') 119 | for i,b in enumerate(music_data): 120 | if i: 121 | c.write(', ') 122 | if not i % 12: 123 | c.write('\n ') 124 | c.write(f'0x{b:02x}') 125 | c.write('\n};\n\n') 126 | c.write(f'const size_t track_count = {len(music)};\n\n') 127 | 128 | c.write('static void add_dpcm(dw_rom *rom, int track)\n') 129 | c.write('{\n ') 130 | consts = [m.dmc_constant() for m in music if m.dmc_constant()] 131 | c.write(' '.join([const for const in consts if const])) 132 | c.write('\n') 133 | c.write(' struct music_data dmc_choice[] = {\n') 134 | c.write(' ') 135 | c.write(',\n '.join([m.dmc_struct() for m in music])) 136 | c.write('\n };\n') 137 | c.write(' struct music_data *dmc = &dmc_choice[track];\n') 138 | c.write(' if (dmc->start)\n') 139 | c.write(' ppatch(&rom->expansion[0x8000], dmc->size, dmc->start);\n') 140 | c.write('}\n\n') 141 | 142 | c.write('void add_music(dw_rom *rom, int track)\n') 143 | c.write('{\n ') 144 | c.write(' '.join([m.music_constant() for m in music])) 145 | c.write('\n') 146 | c.write(' struct music_data music_choice[] = {\n') 147 | 148 | c.write(' ') 149 | c.write(',\n '.join([m.music_struct() for m in music])) 150 | c.write('\n') 151 | c.write(' };\n') 152 | c.write(' struct music_data *music = &music_choice[track];\n') 153 | c.write(' ppatch(&rom->expansion[0x4000], music->size, music->start);\n') 154 | c.write(' add_dpcm(rom, track);\n') 155 | c.write('}\n\n') 156 | 157 | print("Generated C file") 158 | 159 | 160 | def main(): 161 | chdir(join(dirname(realpath(__file__)), '..', 'expansion', 'music')) 162 | music_names = [x for x in glob('*.txt') + glob('*.fms')] 163 | music = [Music(m) for m in music_names] 164 | music_data = b''.join([bytes(m) for m in music]) 165 | 166 | addr = 0 167 | for m in music: 168 | m.set_addr(addr) 169 | addr += m.total_size() 170 | 171 | create_c_file(music, music_data) 172 | create_header(music) 173 | 174 | if __name__ == "__main__": 175 | main() 176 | 177 | -------------------------------------------------------------------------------- /tools/curve_data/mon_agi.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 3,3,6,8,12,14,16,18,20,24,26,22,22,42,30,34,255,38,36,40,50,48,90,56,60,40,78,68,64,70,74,80,70,82,84,40,86,90,255,255 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #Beta_491 5 | ^-7.696329251267564,11.412803592343945,-2.0953013078667917,0.17068501484807957,-0.005712660511493273,6.723981544176638e-05 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_dodge.txt: -------------------------------------------------------------------------------- 1 | 10 2 | 1,1,1,4,1,1,1,2,6,2,6,4,2,2,2,4,1,4,2,4,1,2,2,4,0,1,1,2,15,7,2,2,2,1,2,1,2,2,8,8 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #Beta_491 5 | ^0.16715459693038692,0.004994660125692795,0.022882989522377564,0.050852468833527203,-0.01899139628432672,0.00276423745596809,-0.00021099621897919147,9.218496364238239e-06,-2.32101949653519e-07,3.1346608250456317e-09,-1.7591815157369517e-11 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_gold.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 1,3,5,7,15,19,24,20,18,29,24,41,49,47,59,61,5,74,79,94,109,104,109,119,9,650,149,134,147,154,159,168,184,164,149,147,151,142,200,200 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #2.2_Beta_491 5 | ^-5.412228497998058,8.512778468387427,-1.7312632721229664,0.1560551738655128,-0.005098998914876418,5.638482680403456e-05 6 | #2.2 7 | ^-15.589068825915412,13.281633876685321,-2.3758004823140944,0.19063401086793125,-0.005861916111341896,6.185171349216302e-05 8 | #3.0 9 | ^-153.00793271673868,284.2718724719048,-181.74947413497537,57.014098325897635,-10.150090517124674,1.113262515544717,-0.07862090539258011,0.0036396408970707566,-0.00010971845872177492,2.0729070162690267e-06,-2.2275110183191443e-08,1.0383640532609873e-10 10 | -------------------------------------------------------------------------------- /tools/curve_data/mon_hp.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 2,3,5,7,12,13,13,22,23,20,16,24,28,18,33,39,3,33,37,35,44,37,40,40,153,35,47,48,38,70,72,74,65,67,98,135,99,106,255,255 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #Beta_491 5 | ^-3.736289884089558,5.422688356299423,-0.8389673452460288,0.07236387774917684,-0.002601235415781611,3.318835134891174e-05 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_hr.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,3,15,0,0,0,15,0,2,1,15,1,7,7,1,15,15,15 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #Beta_491 5 | ^0.4314693776787841,-1.5664045346083948,0.8529833853114857,-0.1771048400236765,0.01799585004910412,-0.0009845403089581877,2.947647208577527e-05,-4.5291082376858194e-07,2.7867550489446558e-09 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_sleep.txt: -------------------------------------------------------------------------------- 1 | 10 2 | 0,0,0,0,0,0,0,0,0,0,2,0,3,0,1,7,15,3,4,15,2,4,7,5,15,13,6,2,15,7,7,8,15,15,15,2,15,15,8,8 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #Beta_491 5 | ^-0.19522634033269348,0.0027062049290357856,0.01237738626799184,0.02735078913927832,-0.011130163381360846,0.0016886032484722438,-0.0001306290733001985,5.6891545792548995e-06,-1.4121558220430732e-07,1.8653624253963177e-09,-1.0180705237172738e-11 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_stop.txt: -------------------------------------------------------------------------------- 1 | 7 2 | 0,1,0,2,2,1,3,4,3,4,8,2,2,4,2 3 | 2.7,5.3,8,10.7,13.3,16,18.7,21.3,24,26.7,29.3,32,34.7,37.3,40 4 | #Beta_491 5 | ^-0.08458180321190412,0.5401797217575453,-0.2797847184732541,0.05207538905308297,-0.00453500220327152,0.0001987153225581766,-4.203801383039288e-06,3.410121385272191e-08 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_str.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 5,7,9,11,11,14,18,20,18,24,22,28,28,36,40,44,10,40,50,47,52,56,60,68,120,48,76,78,79,86,88,86,80,94,98,100,105,120,255,255 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #Beta_491 5 | ^-6.669620803842882,11.986588276842362,-2.2661671142685984,0.1818510420657916,-0.005869674265773839,6.615713537705403e-05 6 | -------------------------------------------------------------------------------- /tools/curve_data/mon_xp.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 1,2,3,4,8,12,16,14,15,18,20,25,28,31,40,42,255,47,52,58,58,64,70,72,350,6,78,83,90,95,135,105,120,130,180,155,172,350,128,128 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 4 | #2.2_Beta_491 5 | ^0.1021343775438055,0.49473462717265304,0.13414863527908247,0.032298648707288075,-0.009037240980161442,0.0008932851448447719,-4.1231873788179154e-05,8.990615445684386e-07,-7.447159111606538e-09 6 | #2.2 7 | ^-19.744946833293117,25.884526582525744,-9.685788490935158,1.7211112469700018,-0.16014213041574735,0.008399315345376778,-0.0002488712251730522,3.877547371414262e-06,-2.463576632817791e-08 8 | -------------------------------------------------------------------------------- /tools/curve_data/player_agi.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 4,8,11,15,19,23,26,30,34,39,44,48,52,57,64,69,75,81,84,87,90,93,95,97,99,101,105,107,115,120,130 3 | 0,1,1.789,2.578,3.367,4.156,4.945,5.734,6.523,7.312,8.101,8.890,9.679,10.468,11.257,12.046,12.835,13.624,14.413,15.202,16.364,17.727,19.091,20.455,21.818,23.182,24.545,25.909,27.273,28.636,30 4 | #Vanilla 5 | 4,4,4,6,8,10,10,17,20,22,31,35,40,48,55,64,70,78,84,86,88,90,90,94,98,100,105,107,115,120,130 6 | #2.2_Alpha_468 7 | 4,10.17065844,16.27358993,22.30715836,28.26962633,34.15914482,39.97374121,45.7113056,51.36957491,56.94611432,62.43829545,67.84327066,73.15794226,78.37892555,83.50250391,88.52457363,93.44057522,98.24540693,102.9333139,107.4977434,111.9311527,116.2247458,120.3681042,124.348649,128.1508224,131.7547713,135.1340651,138.2513157,141.0483484,143.4172255,145 8 | #2.2_Beta_491 9 | 4,4,5,7,9,12,17,23,30,38,47,56,64,71,78,84,88,91,93,94,95,95,96,97,100,103,108,113,119,124,128 10 | #2.2 11 | 3.1489474893782576,8.683869377252046,13.096943693234305,17.131938791388514,21.284467035687356,25.845898382218294,30.94385702919998,36.579301134809334,42.66018560281953,49.03170793604862,55.50313715761902,61.8712258000277,67.94020496202722,73.53836243331746,78.53120388704802,82.83119714013202,86.40409948136943,89.27186806738239,91.5121533863611,93.25437578961903,94.6723850909618,95.97370323386366,97.38535002645668,99.13625194433024,101.43623400114156,104.45159468703537,108.27726397487979,112.905544394302,118.19143517354735,123.81453944913926,129.23755454336052 12 | #3.0 13 | ^3.148947489377686,6.41515966116918,-1.0661437835489849,0.19987630931904798,-0.014402685932145512,0.00043713260565562723,-4.745739151708051e-06 14 | 15 | -------------------------------------------------------------------------------- /tools/curve_data/player_hp.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 15,15,22,24,31,35,38,40,46,50,54,62,63,70,78,86,92,100,115,130,138,149,158,165,170,174,180,189,195,200,210 3 | 0,1,1.789,2.578,3.367,4.156,4.945,5.734,6.523,7.312,8.101,8.890,9.679,10.468,11.257,12.046,12.835,13.624,14.413,15.202,16.364,17.727,19.091,20.455,21.818,23.182,24.545,25.909,27.273,28.636,30 4 | #Vanilla 5 | 15,15,22,24,31,35,38,40,46,50,54,62,63,70,78,86,92,100,115,130,138,149,158,165,170,174,180,189,195,200,210 6 | #2.2_Alpha_468 7 | 10,10,17.18908984,24.38314037,31.58233246,38.78686048,45.99693397,53.21277937,60.43464225,67.66278974,74.89751355,82.1391335,89.38800173,96.64450794,103.9090856,111.1822199,118.4644572,125.756418,133.0588123,140.3724609,147.6983234,155.0375364,162.3914673,169.7617927,177.1506159,184.5606535,191.9955497,199.4604493,206.9631719,214.5170666,222.1504664,230 8 | #2.2_Beta_491 9 | 10,13,22,28,33,37,40,44,49,54,60,67,75,84,93,103,113,123,132,142,150,158,165,170,176,180,184,189,194,201,210 10 | #2.2 11 | 10.769305218816912,19.252206127048204,24.92991563394758,29.058888416508438,32.61005965037137,36.30312283140244,40.639131968582156,45.931428148205185,52.334890469390814,59.87351135090404,68.46629620928756,77.9514875083043,88.1091131796908,98.68185941522123,109.3942678300823,119.97025699755875,130.14896835502913,139.69893648127365,148.43058374509127,156.20703932522804,162.9532826016169,168.66361091792638,173.40743171542277,177.33337903813936,180.67175440936163,183.73529207941607,186.91824864477715,190.69381703848038,195.60986489184356,202.28299726751004,211.3909437637897 12 | -------------------------------------------------------------------------------- /tools/curve_data/player_mp.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 0,0,0,5,16,20,24,26,29,36,40,50,58,64,70,72,90,95,100,105,110,120,130,140,150,161,168,175,180,190,200 3 | 0,1,1.789,2.578,3.367,4.156,4.945,5.734,6.523,7.312,8.101,8.890,9.679,10.468,11.257,12.046,12.835,13.624,14.413,15.202,16.364,17.727,19.091,20.455,21.818,23.182,24.545,25.909,27.273,28.636,30 4 | #Vanilla 5 | 0,0,0,5,16,20,24,26,29,36,40,50,58,64,70,72,95,100,108,115,128,135,146,153,161,161,168,175,180,190,200 6 | #2.2_Alpha_468 7 | 0,0,6.972541135,13.95711671,20.95417861,27.96421307,34.98774476,42.02534142,49.07761939,56.14525003,63.22896743,70.32957746,77.44796884,84.5851264,91.74214745,98.92026205,106.1208584,113.3455151,120.5960428,127.8745393,135.1834624,142.5257307,149.9048656,157.3251972,164.7921764,172.312871,179.8968033,187.5574875,195.315594,203.2067024,211.307244,220 8 | #2.2_Beta_491 9 | 0,0,2,7,12,16,21,27,35,43,52,62,72,82,93,103,113,122,131,138,145,151,155,159,163,166,170,174,178,184,191,200 10 | #2.2 11 | -3.7270868502803163,2.0350278451915713,6.628037405281954,10.861842379894231,15.330918083990746,20.44271829038901,26.44457738515802,33.44911098561463,41.45811502092015,50.3849632752769,60.07550339372497,70.32745135053898,80.90828438022524,91.57163237111838,102.07216772157905,112.17899365879055,121.68753102015644,130.42990349729843,138.28382134265308,145.17996353867,151.10785842960965,156.12026281594086,160.33603951133932,163.94153336228518,167.19044573026048,170.40220743654962,173.95885016963618,178.30037635520085,183.9186274887217,191.34965093067103,201.16456516431657 12 | #3.0 13 | ^-3.727086850280071,6.676421416657624,-1.1006456990547417,0.19759337455550344,-0.01152029068749235,0.00026797946913290565,-2.0854686109674302e-06 14 | -------------------------------------------------------------------------------- /tools/curve_data/player_str.txt: -------------------------------------------------------------------------------- 1 | 11 2 | 2,4,9,16,23,29,35,41,47,52,58,64,70,76,81,85,88,92,94,97,99,101,104,107,111,114,120,126,132,137,141 3 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 4 | #Vanilla 5 | 0,4,5,7,7,12,16,18,22,30,35,40,48,52,60,68,72,72,85,87,92,95,97,99,103,113,117,125,130,135,140 6 | #2.2_Alpha_468 7 | 4,9.921350482,15.80605499,21.65304332,27.46117331,33.22922307,38.95588201,44.63974044,50.27927745,55.87284668,61.41865957,66.9147653,72.35902683,77.74909179,83.08235689,88.35592378,93.56654384,98.71054777,103.7837547,108.7813522,113.6977352,118.5262827,123.2590405,127.8862521,132.3956334,136.7711836,140.99108,145.0235289,148.8171422,152.2711864,155 8 | #2.2_Beta_491 9 | 1.469,4.876,7.451,10.049,13.211,17.224,22.178,28.012,34.559,41.584,48.821,56.003,62.880,69.248,74.955,79.917,84.117,87.611,90.518,93.012,95.307,97.635,100.225,103.269,106.890,111.102,115.763,120.529,124.796,127.644,127.769 10 | #2.2 11 | -5.544350339570432,4.0756157882684505,10.132146712641909,14.380122444673177,18.05403119799983,21.957611927587674,26.546372420559944,32.002982939041814,38.30554541502029,45.288738197219274,52.697836349990055,60.235607504217214,67.60208326023957,74.52720614278665,80.79635210793067,86.26872860205306,90.88864817282743,94.68967763221713,97.79166277148772,100.39062862823619,102.74155530543263,105.13402934248506,107.86077063830368,111.17903492639918,115.2648918019854,120.16037830109588,125.71352803172707,131.51127585698055,136.8052381302328,140.43036848232103,140.71648916072996 12 | #3.0 13 | ^2.5317219064841225,5.420847459516875,-0.3793744751677438,0.10014869410933366,-0.008497255220331646,0.0002843288176665623,-3.30935201379537e-06 14 | 15 | -------------------------------------------------------------------------------- /tools/curve_data/player_xp.txt: -------------------------------------------------------------------------------- 1 | 3 2 | 0,7,23,47,110,220,450,800,1300,2000,2900,4000,5500,7500,10000,13000,16000,19000,22000,26000,30000,34000,38000,42000,46000,50000,54000,58000,62000,65535 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 4 | -------------------------------------------------------------------------------- /tools/curve_data/vanilla_stats.txt: -------------------------------------------------------------------------------- 1 | Player Stats 2 | Level HP MP Str Agi XP New Spells 3 | 1 15( 16) 0( 3) 4( 6) 4( 6) 0 4 | 2 22( 22) 0( 3) 5( 7) 4( 6) 7 5 | 3 24( 24) 5( 7) 7( 9) 6( 8) 23 heal 6 | 4 31( 30) 16( 17) 7( 9) 8( 10) 47 hurt 7 | 5 35( 34) 20( 21) 12( 13) 10( 12) 110 8 | 6 38( 37) 24( 24) 16( 17) 10( 12) 220 9 | 7 40( 39) 26( 26) 18( 19) 17( 18) 450 sleep 10 | 8 46( 44) 29( 29) 22( 22) 20( 21) 800 11 | 9 50( 48) 36( 35) 30( 30) 22( 22) 1300 radiant 12 | 10 54( 51) 40( 39) 35( 34) 31( 30) 2000 stopspell 13 | 11 62( 58) 50( 48) 40( 39) 35( 34) 2900 14 | 12 63( 59) 58( 55) 48( 46) 40( 39) 4000 outside 15 | 13 70( 66) 64( 60) 52( 49) 48( 46) 5500 return 16 | 14 78( 73) 70( 66) 60( 57) 55( 52) 7500 17 | 15 86( 80) 72( 67) 68( 64) 64( 60) 10000 repel 18 | 16 92( 85) 95( 88) 72( 67) 70( 66) 13000 19 | 17 100( 93) 100( 93) 72( 67) 78( 73) 16000 healmore 20 | 18 115(106) 108(100) 85( 79) 84( 78) 19000 21 | 19 130(120) 115(106) 87( 81) 86( 80) 22000 hurtmore 22 | 20 138(127) 128(118) 92( 85) 88( 82) 26000 23 | 21 149(137) 135(124) 95( 88) 90( 84) 30000 24 | 22 158(145) 146(134) 97( 90) 90( 84) 34000 25 | 23 165(151) 153(140) 99( 92) 94( 87) 38000 26 | 24 170(156) 161(147) 103( 95) 98( 91) 42000 27 | 25 174(159) 161(147) 113(104) 100( 93) 46000 28 | 26 180(165) 168(154) 117(108) 105( 97) 50000 29 | 27 189(173) 175(160) 125(115) 107( 99) 54000 30 | 28 195(178) 180(165) 130(120) 115(106) 58000 31 | 29 200(183) 190(174) 135(124) 120(111) 62000 32 | 30 210(192) 200(183) 140(129) 130(120) 65535 33 | 34 | 35 | Monster Stats 36 | Name HP Str Agi XP Gold SR SSR HR Dodge Spells 37 | Slime 3 5 3 1 1 0 15 0 1 38 | Red Slime 4 7 3 1 2 0 15 0 1 39 | Drakee 6 9 6 2 2 0 15 0 1 40 | Ghost 7 11 8 3 4 0 15 0 4 41 | Magician 13 11 12 4 11 0 0 0 1 hurt (50%) 42 | Magidrakee 15 14 14 5 11 0 0 0 1 hurt (50%) 43 | Scorpion 20 18 16 6 15 0 15 0 1 44 | Druin 22 20 18 7 15 0 15 0 2 45 | Poltergeist 23 18 20 8 17 0 0 0 6 hurt (75%) 46 | Droll 25 24 24 10 24 0 14 0 2 47 | Drakeema 20 22 26 11 19 2 0 0 6 heal (25%), hurt (50%) 48 | Skeleton 30 28 22 11 29 0 15 0 4 49 | Warlock 30 28 22 13 34 3 1 0 2 sleep (25%), hurt (50%) 50 | Metal Scorpion 22 36 42 14 39 0 15 0 2 51 | Wolf 34 40 30 16 49 1 15 0 2 52 | Wraith 36 44 34 17 59 7 0 0 4 heal (25%) 53 | Metal Slime 4 10 255 115 5 15 15 15 1 hurt (75%) 54 | Specter 36 40 38 18 69 3 1 0 4 sleep (25%), hurt (75%) 55 | Wolflord 38 50 36 20 79 4 7 0 2 stopspell (50%) 56 | Druinlord 35 47 40 20 84 15 0 0 4 heal (75%), hurt (25%) 57 | Drollmagi 38 52 50 22 89 2 2 0 1 stopspell (50%) 58 | Wyvern 42 56 48 24 99 4 15 0 2 59 | Rogue Scorpion 35 60 90 26 109 7 15 0 2 60 | Wraith Knight 46 68 56 28 119 5 0 3 4 heal (75%) 61 | Golem 70 120 60 5 9 15 15 15 0 62 | Goldman 50 48 40 6 199 13 15 0 1 63 | Knight 55 76 78 33 129 6 7 0 1 stopspell (50%) 64 | Magiwyvern 58 78 68 34 139 2 0 0 2 sleep (50%) 65 | Demon Knight 50 79 64 37 149 15 15 15 15 66 | Werewolf 60 86 70 40 154 7 15 0 7 67 | Green Dragon 65 88 74 45 159 7 15 2 2 fire breath 1 (25%) 68 | Starwyvern 65 86 80 43 159 8 0 1 2 healmore (75%), fire breath 1 (25%) 69 | Wizard 65 80 70 50 164 15 7 15 2 hurtmore (50%) 70 | Axe Knight 70 94 82 54 164 15 3 1 1 sleep (25%) 71 | Blue Dragon 70 98 84 60 149 15 15 7 2 fire breath 1 (25%) 72 | Stoneman 160 100 40 65 139 2 15 7 1 73 | Armored Knight 90 105 86 70 139 15 7 1 2 healmore (75%), hurtmore (25%) 74 | Red Dragon 100 120 90 100 139 15 7 15 2 sleep (25%), fire breath 1 (25%) 75 | Dragonlord 1 100 90 75 0 0 15 15 15 0 stopspell (25%), hurtmore (75%) 76 | Dragonlord 2 130 140 200 0 0 15 15 15 0 fire breath 2 (50%) 77 | -------------------------------------------------------------------------------- /tools/curve_data/weapons.txt: -------------------------------------------------------------------------------- 1 | 4 2 | 10,20,60,70,90,180,300,560,800,1000,1500,3000,7700,9800,14800 3 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 4 | #Beta_496 5 | ^3.514576883197151,-131.34297021780944,104.16571157815333,-20.19142289169297,1.2180107366833113 6 | 7 | -------------------------------------------------------------------------------- /tools/patchgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from sys import argv,exit 4 | from ips import Patch 5 | 6 | 7 | def main(): 8 | if len(argv) < 3: 9 | print(f"Usage: {argv[0]} ") 10 | exit(1) 11 | with open(argv[1], 'rb') as original_file: 12 | original = bytearray(original_file.read()) 13 | # blank out the unused code since it's often blanked in edits 14 | original[0xc298:0xc505] = [0xff] * (0xc4f5 - 0xc288) 15 | 16 | expansion = None 17 | with open(argv[2], 'rb') as changed_file: 18 | changed = changed_file.read() 19 | if len(changed) > 0x14010: 20 | expansion = changed[0xc010:0x1c010] 21 | changed = changed[:0xc010] + changed[0x1c010:] 22 | 23 | p = Patch.create(original, changed) 24 | for r in p.records: 25 | if r.address > 0x10: 26 | print(" vpatch(rom, 0x%05x, %4d," % 27 | (r.address - 0x10, len(r.content)), end=" ") 28 | else: 29 | print(" pvpatch(&rom->header[0x%05x], %4d," % 30 | (r.address, len(r.content)), end=" ") 31 | for i,b in enumerate(r.content[:-1]): 32 | if not i % 12: 33 | print("\n ", end="") 34 | print(" 0x%02x," % b, end="") 35 | print(" 0x%02x);" % r.content[-1]) 36 | 37 | if expansion: 38 | empty = [0xff] * len(expansion) 39 | p = Patch.create(empty, expansion) 40 | for r in p.records: 41 | print(" pvpatch(&rom->expansion[0x%05x], %4d," % 42 | (r.address, len(r.content)), end=" ") 43 | for i,b in enumerate(r.content[:-1]): 44 | if not i % 12: 45 | print("\n ", end="") 46 | print(" 0x%02x," % b, end="") 47 | print(" 0x%02x);" % r.content[-1]) 48 | 49 | if __name__ == "__main__": 50 | main() 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /tools/polyfit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Sample run: 4 | # xargs python3 polyfit.py < curve_data/player_str.txt 5 | 6 | import sys 7 | import os 8 | 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | 12 | if __name__ == "__main__": 13 | if os.path.exists(sys.argv[1]): 14 | with open(sys.argv[1], 'r') as f: 15 | args = [x.strip() for x in f.readlines() if x.strip()] 16 | else: 17 | args = sys.argv[1:] 18 | y = np.array(sorted([float(y.strip()) for y in args[1].split(',')])) 19 | x = np.array(sorted([float(x.strip()) for x in args[2].split(',')])) 20 | x_range = range(0, int(max(x)+1)) 21 | try: 22 | coef = np.polyfit(x, y, int(args[0])) 23 | except TypeError as e: 24 | print(f"y={len(y)}, x={len(x)}") 25 | print(str(e)) 26 | sys.exit() 27 | poly = np.poly1d(coef) 28 | poly_values2 = [poly(v) for v in x_range] 29 | plt.plot(x_range, poly_values2, label="New") 30 | 31 | 32 | coef = list(reversed(coef)) 33 | plt.grid(True) 34 | 35 | print('Coefficients:') 36 | print('{') 37 | print(' MIN,') 38 | print(' MAX,') 39 | for i in range(14): 40 | if len(coef) > i: 41 | print(f' {coef[i]},') 42 | else: 43 | print(f' 0.0,') 44 | print('};') 45 | 46 | 47 | plt.scatter(x, y, s=10, label="Fit points") 48 | label = None 49 | for arg in args[3:]: 50 | if arg.startswith('#'): 51 | label = arg[1:].replace('_', ' ') 52 | continue 53 | if arg.startswith('^'): 54 | factors = [float(x) for x in arg[1:].split(',')] 55 | poly = np.poly1d(list(reversed(factors))) 56 | val = np.array([poly(y) for y in x_range]) 57 | else: 58 | val = np.array([float(y) for y in arg.split(',')]) 59 | plt.plot(range(0, len(val)), val, label=label) 60 | label = None 61 | plt.legend() 62 | plt.show() 63 | 64 | -------------------------------------------------------------------------------- /webui/base32.js: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/agnoster/base32-js 2 | 3 | 4 | ;(function(){ 5 | 6 | // This would be the place to edit if you want a different 7 | // Base32 implementation 8 | 9 | var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; 10 | 11 | /** 12 | * Build a lookup table and memoize it 13 | * 14 | * Return an object that maps a character to its 15 | * byte value. 16 | */ 17 | 18 | var lookup = function() { 19 | var table = {} 20 | // Invert 'alphabet' 21 | for (var i = 0; i < alphabet.length; i++) { 22 | table[alphabet[i]] = i 23 | } 24 | lookup = function() { return table } 25 | return table 26 | } 27 | 28 | /** 29 | * A streaming encoder 30 | * 31 | * var encoder = new base32.Encoder() 32 | * var output1 = encoder.update(input1) 33 | * var output2 = encoder.update(input2) 34 | * var lastoutput = encode.update(lastinput, true) 35 | */ 36 | 37 | function Encoder() { 38 | var skip = 0 // how many bits we will skip from the first byte 39 | var bits = 0 // 5 high bits, carry from one byte to the next 40 | 41 | this.output = '' 42 | 43 | // Read one byte of input 44 | // Should not really be used except by "update" 45 | this.readByte = function(byte) { 46 | // coerce the byte to an int 47 | if (typeof byte == 'string') byte = byte.charCodeAt(0) 48 | 49 | if (skip < 0) { // we have a carry from the previous byte 50 | bits |= (byte >> (-skip)) 51 | } else { // no carry 52 | bits = (byte << skip) & 248 53 | } 54 | 55 | if (skip > 3) { 56 | // not enough data to produce a character, get us another one 57 | skip -= 8 58 | return 1 59 | } 60 | 61 | if (skip < 4) { 62 | // produce a character 63 | this.output += alphabet[bits >> 3] 64 | skip += 5 65 | } 66 | 67 | return 0 68 | } 69 | 70 | // Flush any remaining bits left in the stream 71 | this.finish = function(check) { 72 | var output = this.output + (skip < 0 ? alphabet[bits >> 3] : '') + (check ? '$' : '') 73 | this.output = '' 74 | return output 75 | } 76 | } 77 | 78 | /** 79 | * Process additional input 80 | * 81 | * input: string of bytes to convert 82 | * flush: boolean, should we flush any trailing bits left 83 | * in the stream 84 | * returns: a string of characters representing 'input' in base32 85 | */ 86 | 87 | Encoder.prototype.update = function(input, flush) { 88 | for (var i = 0; i < input.length; ) { 89 | i += this.readByte(input[i]) 90 | } 91 | // consume all output 92 | var output = this.output 93 | this.output = '' 94 | if (flush) { 95 | output += this.finish() 96 | } 97 | return output 98 | } 99 | 100 | // Functions analogously to Encoder 101 | 102 | function Decoder() { 103 | var skip = 0 // how many bits we have from the previous character 104 | var byte = 0 // current byte we're producing 105 | 106 | this.output = '' 107 | 108 | // Consume a character from the stream, store 109 | // the output in this.output. As before, better 110 | // to use update(). 111 | this.readChar = function(char) { 112 | if (typeof char != 'string'){ 113 | if (typeof char == 'number') { 114 | char = String.fromCharCode(char) 115 | } 116 | } 117 | var val = lookup()[char] 118 | if (typeof val == 'undefined') { 119 | // character does not exist in our lookup table 120 | return // skip silently. An alternative would be: 121 | // throw Error('Could not find character "' + char + '" in lookup table.') 122 | } 123 | val <<= 3 // move to the high bits 124 | byte |= val >>> skip 125 | skip += 5 126 | if (skip >= 8) { 127 | // we have enough to preduce output 128 | this.output += String.fromCharCode(byte) 129 | skip -= 8 130 | if (skip > 0) byte = (val << (5 - skip)) & 255 131 | else byte = 0 132 | } 133 | 134 | } 135 | 136 | this.finish = function(check) { 137 | var output = this.output + (skip < 0 ? alphabet[bits >> 3] : '') + (check ? '$' : '') 138 | this.output = '' 139 | return output 140 | } 141 | } 142 | 143 | Decoder.prototype.update = function(input, flush) { 144 | for (var i = 0; i < input.length; i++) { 145 | this.readChar(input[i]) 146 | } 147 | var output = this.output 148 | this.output = '' 149 | if (flush) { 150 | output += this.finish() 151 | } 152 | return output 153 | } 154 | 155 | /** Convenience functions 156 | * 157 | * These are the ones to use if you just have a string and 158 | * want to convert it without dealing with streams and whatnot. 159 | */ 160 | 161 | // String of data goes in, Base32-encoded string comes out. 162 | function encode(input) { 163 | var encoder = new Encoder() 164 | var output = encoder.update(input, true) 165 | return output 166 | } 167 | 168 | // Base32-encoded string goes in, decoded data comes out. 169 | function decode(input) { 170 | var decoder = new Decoder() 171 | var output = decoder.update(input, true) 172 | let outputBytes = new Uint8Array(output.length); 173 | for (let i=0; i < output.length; i++) { 174 | outputBytes[i] = output.charCodeAt(i); 175 | } 176 | return outputBytes; 177 | } 178 | 179 | var base32 = { 180 | Decoder: Decoder, 181 | Encoder: Encoder, 182 | encode: encode, 183 | decode: decode, 184 | } 185 | 186 | if (typeof window !== 'undefined') { 187 | // we're in a browser - OMG! 188 | window.base32 = base32 189 | } 190 | })(); 191 | -------------------------------------------------------------------------------- /webui/index.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font-family: Arial, sans-serif; 4 | background-color: #888; 5 | margin: 0; 6 | font-size: 16px; 7 | /* prevent chrome mobile from being stupid */ 8 | -webkit-text-size-adjust: none; 9 | } 10 | 11 | #application { 12 | background-color: #fff; 13 | max-width: 800px; 14 | padding: 1em; 15 | margin: auto; 16 | user-select: none; 17 | } 18 | 19 | #application > img { 20 | filter: drop-shadow(2px 2px 1px #aaa); 21 | } 22 | 23 | h1, h3 { 24 | text-align: center; 25 | } 26 | 27 | tabbar { 28 | display: block; 29 | } 30 | 31 | tab { 32 | display: inline-block; 33 | border: 1px solid black; 34 | border-bottom-width: 0; 35 | padding: 0.5em 1em; 36 | margin: 0; 37 | background-color: #ddd; 38 | border-radius: 4px 4px 0 0; 39 | font-weight: bold; 40 | } 41 | 42 | tab.active { 43 | padding: calc(0.5em + 2px) 1em 0.5em 1em; 44 | position: relative; 45 | top: 1px; 46 | } 47 | 48 | tab:hover, tab.active { 49 | background-color: #fff; 50 | } 51 | 52 | tabcontent { 53 | display: grid; 54 | grid-template-columns: 50% 50%; 55 | grid-template-rows: 50px 50px 50px 50px 50px 50px; 56 | border: 1px solid black; 57 | border-radius: 0 0 4px 4px; 58 | padding: 3em; 59 | } 60 | 61 | /* Hide the "spinner" in number fields */ 62 | input::-webkit-outer-spin-button, 63 | input::-webkit-inner-spin-button { 64 | -webkit-appearance: none; 65 | margin: 0; 66 | } 67 | 68 | /* Firefox */ 69 | input[type=number] { 70 | -moz-appearance: textfield; 71 | } 72 | 73 | .modal { 74 | background-color: #fff; 75 | } 76 | 77 | .invalid { 78 | border-color: red; 79 | } 80 | 81 | div.description { 82 | color: #666; 83 | } 84 | 85 | @media (prefers-color-scheme: dark) { 86 | body { 87 | background-color: #111; 88 | color: #ccc; 89 | } 90 | 91 | #application { 92 | background-color: #333; 93 | } 94 | 95 | tab { 96 | background-color: #222; 97 | } 98 | 99 | tab:hover, tab.active { 100 | background-color: #333; 101 | } 102 | 103 | button, select { 104 | background-color: #333; 105 | color: #ccc; 106 | border-color: #3a3a3a; 107 | } 108 | input { 109 | background-color: #111; 110 | color: #ccc; 111 | border-color: #333; 112 | } 113 | #application > img { 114 | filter: drop-shadow(2px 2px 1px #000); 115 | } 116 | div.description { 117 | color: #888; 118 | } 119 | 120 | .modal { 121 | background-color: #333; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /webui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DWRandomizer 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /webui/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/logo.png -------------------------------------------------------------------------------- /webui/modal.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * A class for creating a modal window 5 | */ 6 | class Modal { 7 | constructor(width, height, title, okText, cancelText, okFunc) { 8 | if (Modal._instance) 9 | throw 'Only one instance of this class can exist at once'; 10 | Modal._instance = this; 11 | this.main = this.create('div', null, { 12 | 'position': 'absolute', 13 | 'top': '0', 14 | 'bottom': '0', 15 | 'left': '0', 16 | 'right': '0', 17 | }); 18 | this.overlay = this.create('div', null, { 19 | 'position': 'absolute', 20 | 'top': '0', 21 | 'bottom': '0', 22 | 'left': '0', 23 | 'right': '0', 24 | 'background-color': 'black', 25 | 'opacity': '0.5' 26 | }); 27 | this.overlay.click(() => { this.close(); }); 28 | document.body.append(this.main); 29 | this.main.append(this.overlay); 30 | let dialogOffset = (this.overlay.offsetHeight - height) / 2; 31 | this.dialog = this.create('div', null, { 32 | 'padding': '0.2em', 33 | 'outline': '1px solid black', 34 | 'font-weight': 'bold', 35 | 'text-align': 'center', 36 | 'margin': 'auto', 37 | 'position': 'relative', 38 | 'margin-top': dialogOffset + 'px', 39 | 'width': width + 'px', 40 | 'height': height + 'px', 41 | 'z-index': '3' 42 | }); 43 | this.dialog.classList.add('modal'); 44 | this.main.prepend(this.dialog); 45 | if (title) { 46 | let heading = this.create('h3', title); 47 | this.dialog.append(heading); 48 | } 49 | let canceler = this.create('div', null, { 50 | 'position': 'absolute', 51 | 'bottom': '0.5em', 52 | 'right': '1em', 53 | }); 54 | this.dialog.append(canceler); 55 | if (okText) { 56 | let okButton = this.create('button', okText) 57 | okButton.click(okFunc); 58 | canceler.append(okButton); 59 | } 60 | if (cancelText) { 61 | let cancelButton = this.create('button', cancelText) 62 | cancelButton.click(evt => { 63 | this.close(); 64 | }); 65 | canceler.append(cancelButton); 66 | } 67 | } 68 | 69 | /** 70 | * Creates a new HTML element 71 | * 72 | * @param element The element type (e.g. div, span, etc) 73 | * @param text Text to be inserted into the element. Pass null/undefined 74 | * to leave the element empty 75 | * @param style An object containing any additional style attributes to be 76 | * added to the object 77 | */ 78 | create(element, text, style) { 79 | let el = document.createElement(element); 80 | if (text) 81 | el.innerText = text 82 | if (style) { 83 | for (let key in style) 84 | el.style.setProperty(key, style[key]); 85 | } 86 | return el; 87 | } 88 | close() { 89 | this.main.remove(); 90 | Modal._instance = null; 91 | } 92 | } 93 | 94 | /** 95 | * Creates a modal for loading & storing flags 96 | */ 97 | class FlagsModal extends Modal { 98 | constructor() { 99 | super(400, 300, 'Presets', null, 'Cancel'); 100 | let builtinPresets = { 101 | 'Standard': 'IVIAAVCAKACAAAAAAAAAAEAA', 102 | 'Fast Standard': 'IVIAAVCAKACFAAAAAAAAAIAA', 103 | 'Easy Standard': 'IVIAAVCFKACACQAAKAAAAZAA', 104 | 'Tiebreaker': 'IVKQAVCEKEAFKRIAAAAAAYAA', 105 | } 106 | this.dialog.append(this.create('div', 'Save', { 107 | 'font-weight': 'normal', 108 | 'margin-bottom': '0.5em', 109 | })); 110 | let saver = this.create('div'); 111 | let nameBox = this.create('input'); 112 | nameBox.placeholder = 'Preset Name'; 113 | nameBox.setAttribute('maxlength', '50'); 114 | saver.append(nameBox); 115 | let saveButton = this.create('button', 'Save current'); 116 | saver.append(saveButton) 117 | this.dialog.append(saver); 118 | this.dialog.append(saver) 119 | let flagSelect = this.create('select'); 120 | for (let [key,value] of Object.entries(builtinPresets)) { 121 | let opt = this.create('option', key) 122 | opt.value = value 123 | flagSelect.append(opt); 124 | } 125 | this.dialog.append(this.create('div', 'Load/Delete', { 126 | 'font-weight': 'normal', 127 | 'margin-top': '2em', 128 | 'margin-bottom': '0.5em', 129 | })); 130 | let loader = this.create('div'); 131 | let storedPresets = localStorage.getItem('storedPresets'); 132 | if (storedPresets) { 133 | storedPresets = JSON.parse(storedPresets); 134 | for (let [key,value] of Object.entries(storedPresets)) { 135 | let opt = this.create('option', key) 136 | opt.value = value 137 | flagSelect.append(opt); 138 | } 139 | } else { 140 | storedPresets = {}; 141 | } 142 | loader.append(flagSelect) 143 | let loadButton = this.create('button', 'Load preset', { 144 | 'margin-left': '1em', 145 | }); 146 | let deleteButton = this.create('button', 'Delete Preset', { 147 | 'margin-left': '1em', 148 | }); 149 | loader.append(this.create('br')); 150 | loader.append(this.create('br')); 151 | loader.append(loadButton) 152 | loader.append(deleteButton) 153 | this.dialog.append(loader) 154 | // init events 155 | saveButton.click(evt => { 156 | if (nameBox.value) { 157 | storedPresets[nameBox.value] = Interface.getFlags() 158 | localStorage.setItem('storedPresets', 159 | JSON.stringify(storedPresets)); 160 | this.close() 161 | } 162 | }); 163 | loadButton.click(evt => { 164 | Interface.setFlags(flagSelect.value) 165 | this.close(); 166 | }); 167 | deleteButton.click(evt => { 168 | let option = flagSelect.selectedOptions[0] 169 | delete storedPresets[option.innerText]; 170 | localStorage.setItem('storedPresets', 171 | JSON.stringify(storedPresets)); 172 | option.remove(); 173 | }); 174 | deleteButton.disabled = 'true'; 175 | flagSelect.change(function() { 176 | if (this.selectedIndex < Object.keys(builtinPresets).length) { 177 | deleteButton.disabled = 'true'; 178 | } else { 179 | deleteButton.disabled = undefined; 180 | } 181 | }); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /webui/sprites/Arkista's Ring Christine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Arkista's Ring Christine.png -------------------------------------------------------------------------------- /webui/sprites/Barry Sanders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Barry Sanders.png -------------------------------------------------------------------------------- /webui/sprites/Blaster Master Jason.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Blaster Master Jason.png -------------------------------------------------------------------------------- /webui/sprites/Blinky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Blinky.png -------------------------------------------------------------------------------- /webui/sprites/Bo Jackson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Bo Jackson.png -------------------------------------------------------------------------------- /webui/sprites/Bomberman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Bomberman.png -------------------------------------------------------------------------------- /webui/sprites/Clyde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Clyde.png -------------------------------------------------------------------------------- /webui/sprites/DW2 Prince of Cannock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW2 Prince of Cannock.png -------------------------------------------------------------------------------- /webui/sprites/DW2 Prince of Midenhall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW2 Prince of Midenhall.png -------------------------------------------------------------------------------- /webui/sprites/DW2 Princess of Moonbrooke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW2 Princess of Moonbrooke.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Fighter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Fighter.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Goof-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Goof-off.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Merchant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Merchant.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Pilgrim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Pilgrim.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Sage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Sage.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Soldier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Soldier.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Female Wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Female Wizard.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Ghost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Ghost.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Hero.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Fighter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Fighter.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Goof-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Goof-off.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Merchant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Merchant.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Pilgrim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Pilgrim.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Sage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Sage.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Soldier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Soldier.png -------------------------------------------------------------------------------- /webui/sprites/DW3 Male Wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW3 Male Wizard.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Alena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Alena.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Brey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Brey.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Celia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Celia.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Cristo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Cristo.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Doran.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Doran.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Healie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Healie.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Hero.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Heroine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Heroine.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Mara.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Mara.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Nara.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Nara.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Ragnar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Ragnar.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Taloon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Taloon.png -------------------------------------------------------------------------------- /webui/sprites/DW4 Tov (The Dog).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Tov (The Dog).png -------------------------------------------------------------------------------- /webui/sprites/DW4 Yeti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DW4 Yeti.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Guan Yu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Guan Yu.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Huang Zhong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Huang Zhong.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Jiang Wei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Jiang Wei.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Lu Bu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Lu Bu.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Ma Chao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Ma Chao.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Zhang Fei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Zhang Fei.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Zhao Yun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Zhao Yun.png -------------------------------------------------------------------------------- /webui/sprites/DoaE Zhuge Liang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/DoaE Zhuge Liang.png -------------------------------------------------------------------------------- /webui/sprites/Dragonlord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Dragonlord.png -------------------------------------------------------------------------------- /webui/sprites/FF Black Belt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Black Belt.png -------------------------------------------------------------------------------- /webui/sprites/FF Black Mage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Black Mage.png -------------------------------------------------------------------------------- /webui/sprites/FF Black Wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Black Wizard.png -------------------------------------------------------------------------------- /webui/sprites/FF Fighter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Fighter.png -------------------------------------------------------------------------------- /webui/sprites/FF Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Knight.png -------------------------------------------------------------------------------- /webui/sprites/FF Master.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Master.png -------------------------------------------------------------------------------- /webui/sprites/FF Ninja.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Ninja.png -------------------------------------------------------------------------------- /webui/sprites/FF Red Mage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Red Mage.png -------------------------------------------------------------------------------- /webui/sprites/FF Red Wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Red Wizard.png -------------------------------------------------------------------------------- /webui/sprites/FF Thief.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF Thief.png -------------------------------------------------------------------------------- /webui/sprites/FF White Mage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF White Mage.png -------------------------------------------------------------------------------- /webui/sprites/FF White Wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF White Wizard.png -------------------------------------------------------------------------------- /webui/sprites/FF4 DK Cecil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF4 DK Cecil.png -------------------------------------------------------------------------------- /webui/sprites/FF4 Edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/FF4 Edge.png -------------------------------------------------------------------------------- /webui/sprites/Gwaelin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Gwaelin.png -------------------------------------------------------------------------------- /webui/sprites/Inky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Inky.png -------------------------------------------------------------------------------- /webui/sprites/Jerry Rice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Jerry Rice.png -------------------------------------------------------------------------------- /webui/sprites/Kirby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Kirby.png -------------------------------------------------------------------------------- /webui/sprites/Lala.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Lala.png -------------------------------------------------------------------------------- /webui/sprites/Link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Link.png -------------------------------------------------------------------------------- /webui/sprites/Lolo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Lolo.png -------------------------------------------------------------------------------- /webui/sprites/Loto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Loto.png -------------------------------------------------------------------------------- /webui/sprites/Luigi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Luigi.png -------------------------------------------------------------------------------- /webui/sprites/Mario.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Mario.png -------------------------------------------------------------------------------- /webui/sprites/Metal Slime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Metal Slime.png -------------------------------------------------------------------------------- /webui/sprites/Mina the Hollower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Mina the Hollower.png -------------------------------------------------------------------------------- /webui/sprites/Ms. Pac-Man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Ms. Pac-Man.png -------------------------------------------------------------------------------- /webui/sprites/Pac-Man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Pac-Man.png -------------------------------------------------------------------------------- /webui/sprites/Pinky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Pinky.png -------------------------------------------------------------------------------- /webui/sprites/Plumplim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Plumplim.png -------------------------------------------------------------------------------- /webui/sprites/Random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Random.png -------------------------------------------------------------------------------- /webui/sprites/Red Slime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Red Slime.png -------------------------------------------------------------------------------- /webui/sprites/Slime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Slime.png -------------------------------------------------------------------------------- /webui/sprites/StarTropics Mike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/StarTropics Mike.png -------------------------------------------------------------------------------- /webui/sprites/Sue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Sue.png -------------------------------------------------------------------------------- /webui/sprites/Waluigi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Waluigi.png -------------------------------------------------------------------------------- /webui/sprites/Wario.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Wario.png -------------------------------------------------------------------------------- /webui/sprites/Yoshi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgrew/dwrandomizer/de1ef139434684d87669d472844a9937d06d6526/webui/sprites/Yoshi.png --------------------------------------------------------------------------------