diff --git a/.gitignore b/.gitignore index d5cb625..e01bc98 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ to_compress/ tools/rom-value-generator/payload-generator text_errors.txt terminal_output.txt +tools/payload-generator/payload-generator diff --git a/Makefile b/Makefile index 7e779c2..91d8636 100644 --- a/Makefile +++ b/Makefile @@ -255,7 +255,6 @@ $(GENERATE_STAMP): $(TEXT_HELPER_INPUTS) $(PAYLOAD_GEN_INPUTS) compress_lz10.sh @echo "----------------------------------------------------------------" @echo @tools/rom-value-generator/payload-generator to_compress - @cp -a tools/gb-payload-generator/build/. to_compress/ @echo "Compressing bin files!" @echo -n "[" @find to_compress -name "*.bin" -print0 | xargs -0 -n1 ./compress_lz10.sh diff --git a/include/link_handler.h b/include/link_handler.h index bacbf1d..fbc7563 100644 --- a/include/link_handler.h +++ b/include/link_handler.h @@ -32,6 +32,8 @@ enum ConnectionState WAIT_FOR_TRADE, TRADE_PREAMBLE, TRADE, + END, + PARTY_PREAMBLE, COLOSSEUM, CANCEL, @@ -70,24 +72,26 @@ struct LinkState bool test_packet_fail = false; // ??? byte data_packet[PACKET_SIZE]; + byte curr_payload[0x2A0]; + int curr_payload_size = 0; bool irq_enabled = true; // Stores if the IRQ is currently enabled, used for pausing and sending one byte at a time // This is info that was passed in via handleIncomingByte byte *box_data_storage; - byte *curr_payload; GB_ROM *curr_gb_rom; PokeBox *box; const u16 *debug_charset; bool cancel_connection; }; -void setup(byte *box_data_storage, byte *curr_payload, GB_ROM *curr_rom, PokeBox *box, const u16 *debug_charset, bool cancel_connection); +void setup(byte *box_data_storage, GB_ROM *curr_rom, PokeBox *box, const u16 *debug_charset, bool cancel_connection); byte handleIncomingByte(); int loop(byte *box_data_storage, byte *curr_payload, GB_ROM *curr_rom, PokeBox *box, const u16 *debug_charset, bool cancel_connection); byte exchange_parties(byte curr_in, byte *curr_payload); byte exchange_boxes(byte curr_in, byte *party_data, GB_ROM *curr_gb_rom, const u16 *debug_charset); byte exchange_remove_array(byte curr_in, PokeBox *box, bool cancel_connection); +void load_universal_payload(); void handshake(); #endif /* LINK_HANDLER_H_ */ diff --git a/include/pokemon_party.h b/include/pokemon_party.h index 5a126aa..a4f0469 100644 --- a/include/pokemon_party.h +++ b/include/pokemon_party.h @@ -30,8 +30,6 @@ public: byte box_data_array[0x462]; private: - void init_payload(); - u8 current_payload[PAYLOAD_SIZE]; int last_error; bool stabilize_mythic = false; diff --git a/source/link_handler.cpp b/source/link_handler.cpp index fb88852..35d679d 100644 --- a/source/link_handler.cpp +++ b/source/link_handler.cpp @@ -18,6 +18,9 @@ #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" #include "flash_mem.h" +#include "universalPayloadGen1_bin.h" +#include "universalPayloadGen2_bin.h" + LinkSPI linkSPIInstance; LinkSPI *linkSPI = &linkSPIInstance; LinkState *currLinkState; @@ -71,7 +74,7 @@ void print(const char *format, ...) } } -void setup(byte *box_data_storage, byte *curr_payload, GB_ROM *curr_rom, PokeBox *box, const u16 *debug_charset, bool cancel_connection) +void setup(byte *box_data_storage, GB_ROM *curr_rom, PokeBox *box, const u16 *debug_charset, bool cancel_connection) { REG_TM3D = -0x4000 / 60; REG_TM3CNT = TM_FREQ_1024 | TM_ENABLE; @@ -82,7 +85,6 @@ void setup(byte *box_data_storage, byte *curr_payload, GB_ROM *curr_rom, PokeBox currLinkState = new LinkState; currLinkState->box_data_storage = box_data_storage; - currLinkState->curr_payload = curr_payload; currLinkState->curr_gb_rom = curr_rom; currLinkState->box = box; currLinkState->debug_charset = debug_charset; @@ -136,11 +138,13 @@ byte handleIncomingByte() if (currLinkState->in_data == 0xD0) { currLinkState->gen = 1; + load_universal_payload(); return 0xD4; } if (currLinkState->in_data == 0x61) { currLinkState->gen = 2; + load_universal_payload(); return 0x61; } } @@ -174,8 +178,15 @@ byte handleIncomingByte() }; return tradePreambleBytes[currLinkState->section_data_counter]; case TRADE: + if (currLinkState->section_data_counter == currLinkState->curr_payload_size - 1) + { + currLinkState->conState = END; + } return currLinkState->curr_payload[currLinkState->section_data_counter]; break; + case END: + currLinkState->irq_enabled = false; + break; default: return currLinkState->in_data; @@ -623,4 +634,18 @@ byte exchange_remove_array(byte curr_in, PokeBox *box, bool cancel_connection) } } return 0xFF; +} + +void load_universal_payload() +{ + if (currLinkState->gen == 1) + { + memcpy(currLinkState->curr_payload, universalPayloadGen1_bin, universalPayloadGen1_bin_size); + currLinkState->curr_payload_size = universalPayloadGen1_bin_size; + } + else if (currLinkState->gen == 2) + { + memcpy(currLinkState->curr_payload, universalPayloadGen2_bin, universalPayloadGen2_bin_size); + currLinkState->curr_payload_size = universalPayloadGen2_bin_size; + } } \ No newline at end of file diff --git a/source/pokemon_party.cpp b/source/pokemon_party.cpp index 235143d..ff37e6d 100644 --- a/source/pokemon_party.cpp +++ b/source/pokemon_party.cpp @@ -15,10 +15,6 @@ #include "ptgb_save_data_manager.h" #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" -#include "payload_rb_experimental_lz10_bin.h" -#include "payload_rb_lz10_bin.h" -#include "payload_y_experimental_lz10_bin.h" - static const byte gen1_rb_debug_box_data[0x462] = { // Num of Pokemon 0x14, @@ -180,9 +176,8 @@ void Pokemon_Party::start_link() u16 debug_charset[256]; load_localized_charset(debug_charset, 3, ENGLISH); - init_payload(); - setup(&box_data_array[0], current_payload, &curr_gb_rom, &box, debug_charset, false); + setup(&box_data_array[0], &curr_gb_rom, &box, debug_charset, false); // This used to clear out the box data, probably isn't needed anymore // memset(box_data_array, 0, curr_gb_rom.box_data_size); @@ -349,40 +344,4 @@ bool Pokemon_Party::get_contains_missingno() out |= box.getPokemon(i)->getSpeciesIndexNumber() == MISSINGNO; } return out; -} - -void Pokemon_Party::init_payload() -{ - u8 decompression_buffer[1512]; - const u8 *payload_src; - u32 payload_file_size; - - // WARNING: Ensure sure decompression_buffer is large enough! - - /* - if (curr_gb_rom.generation == 1) - { - if (curr_gb_rom.version == YELLOW_ID) - { - payload_src = gb_gen1_payloads_Y_lz10_bin; - } - else - { - payload_src = gb_gen1_payloads_RB_lz10_bin; - } - } - else // if(curr_gb_rom.generation == 2) - { - payload_src = gb_gen2_payloads_lz10_bin; - }*/ - - // For now this is going to be hardcoded, just as a test. - payload_src = payload_rb_experimental_lz10_bin; - - // byte 2-4 of the compressed data store the decompressed size - payload_file_size = payload_src[1] | (payload_src[2] << 8) | (payload_src[3] << 16); - LZ77UnCompWram(payload_src, decompression_buffer); - - payload_file_reader payload_reader(decompression_buffer, payload_file_size); - payload_reader.read_payload(current_payload, curr_gb_rom.language, curr_gb_rom.version); } \ No newline at end of file diff --git a/tools/gb-payload-generator/Makefile b/tools/gb-payload-generator/Makefile index 1f77623..46d6311 100644 --- a/tools/gb-payload-generator/Makefile +++ b/tools/gb-payload-generator/Makefile @@ -3,14 +3,15 @@ SHELL := /bin/bash ASM_DIR := src/payloads OUTPUT_DIR := build DEPENDENCIES_DIR := dependencies -OBJECT_FILE := $(OUTPUT_DIR)/output.o +OBJECT_FILE := $(OUTPUT_DIR)/$${file%%.*}.o +DATA_DIR := ../../data/ PAYLOADS := $(notdir $(wildcard $(ASM_DIR)/*.asm)) DEPENDENCY_FILES := $(notdir $(wildcard $(DEPENDENCIES_DIR)/*.asm)) .PHONY: all base language_specific clean -all: base language_specific +all: base language_specific link base: | $(OUTPUT_DIR) @set -e; \ @@ -37,6 +38,10 @@ language_specific: | $(OUTPUT_DIR) done; \ done +link: + @ls + @cp $(OUTPUT_DIR)/*.bin $(DATA_DIR) + $(OUTPUT_DIR): @mkdir -p $(OUTPUT_DIR) diff --git a/tools/gb-payload-generator/documentation/ROMHEADERS.txt b/tools/gb-payload-generator/documentation/ROMHEADERS.txt new file mode 100644 index 0000000..703dd04 --- /dev/null +++ b/tools/gb-payload-generator/documentation/ROMHEADERS.txt @@ -0,0 +1,119 @@ +Yellow + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 4C 4F 57 00 +80 30 31 03 1B 05 03 01 33 00 97 04 7C + +Yellow FR + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 41 50 53 44 +80 30 31 03 1B 05 03 01 33 00 61 66 FB + +Yellow DE + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 41 50 53 46 +80 30 31 03 1B 05 03 01 33 00 5F B7 C1 + +Yellow IT + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 41 50 53 49 +80 30 31 03 1B 05 03 01 33 00 5C 4E 8F + +Yellow SP + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 41 50 53 53 +80 30 31 03 1B 05 03 01 33 00 52 56 37 + +Yellow JP 1.0 + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 4C 4F 57 00 +00 30 31 03 13 05 03 00 33 00 20 9C 29 + +Yellow JP 1.1 + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 4C 4F 57 00 +00 30 31 03 13 05 03 00 33 01 1F 88 58 + +Yellow JP 1.2 + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 4C 4F 57 00 +00 30 31 03 13 05 03 00 33 02 1E ED D9 + +Yellow JP 1.3 + +50 4F 4B 45 4D 4F 4E 20 59 45 4C 4C 4F 57 00 +00 30 31 03 13 05 03 00 33 03 1D D9 84 + +Red EN + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 13 05 03 01 33 00 20 91 E6 + +Blue EN + +50 4F 4B 45 4D 4F 4E 20 42 4C 55 45 00 00 00 +00 30 31 03 13 05 03 01 33 00 D3 9D 0A + +Red FR + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 1B 05 03 01 33 00 18 7A FC + +Blue FR + +50 4F 4B 45 4D 4F 4E 20 42 4C 55 45 00 00 00 +00 30 31 03 1B 05 03 01 33 00 CB 56 A4 + +Red DE + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 1B 05 03 01 33 00 18 5C DC + +Blue DE + +50 4F 4B 45 4D 4F 4E 20 42 4C 55 45 00 00 00 +00 30 31 03 1B 05 03 01 33 00 CB 2E BC + +Red IT + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 1B 05 03 01 33 00 18 89 D2 + +Blue IT + +50 4F 4B 45 4D 4F 4E 20 42 4C 55 45 00 00 00 +00 30 31 03 1B 05 03 01 33 00 CB 5E 9C + +Red SP + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 1B 05 03 01 33 00 18 38 4A + +Blue SP + +50 4F 4B 45 4D 4F 4E 20 42 4C 55 45 00 00 00 +00 30 31 03 1B 05 03 01 33 00 CB 14 D7 + +Red JP v1.0 + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 03 04 03 00 33 00 32 A2 C1 + +Green JP v1.0 + +50 4F 4B 45 4D 4F 4E 20 47 52 45 45 4E 00 00 +00 30 31 03 03 04 03 00 33 00 9C DD D5 + +Red JP v1.1 + +50 4F 4B 45 4D 4F 4E 20 52 45 44 00 00 00 00 +00 30 31 03 03 04 03 00 33 01 31 B8 66 + +Green JP v1.1 + +50 4F 4B 45 4D 4F 4E 20 47 52 45 45 4E 00 00 +00 30 31 03 03 04 03 00 33 01 9B F5 47 + +Blue JP + +50 4F 4B 45 4D 4F 4E 20 42 4C 55 45 00 00 00 +00 30 31 03 03 04 03 00 33 00 E5 DC 36 \ No newline at end of file diff --git a/tools/gb-payload-generator/documentation/ROMHEADERS_GEN2.txt b/tools/gb-payload-generator/documentation/ROMHEADERS_GEN2.txt new file mode 100644 index 0000000..68a627e --- /dev/null +++ b/tools/gb-payload-generator/documentation/ROMHEADERS_GEN2.txt @@ -0,0 +1,109 @@ +Gold EN + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 45 80 POKEMON_GLDAAUE. +00000144: 30 31 03 10 06 03 01 33 00 4b 68 2d 01.....3.Kh- + +Gold DE + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 44 80 POKEMON_GLDAAUD. +00000144: 30 31 03 10 06 03 01 33 00 4c dc 97 01.....3.L.. + +Gold FR + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 46 80 POKEMON_GLDAAUF. +00000144: 30 31 03 10 06 03 01 33 00 4a 6f c6 01.....3.Jo. + +Gold IT + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 49 80 POKEMON_GLDAAUI. +00000144: 30 31 03 10 06 03 01 33 00 47 ce 0c 01.....3.G.. + +Gold SP + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 53 80 POKEMON_GLDAAUS. +00000144: 30 31 03 10 06 03 01 33 00 3d 93 53 01.....3.=.S + +Gold JP rev0 + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 4a 80 POKEMON_GLDAAUJ. +00000144: 30 31 03 10 05 03 00 33 00 48 8a 70 01.....3.H.p` + +Gold JP revA + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 4a 80 POKEMON_GLDAAUJ. +00000144: 30 31 03 10 05 03 00 33 01 47 84 60 01.....3.G. + +Gold KOR + +00000134: 50 4f 4b 45 4d 4f 4e 5f 47 4c 44 41 41 55 4b c0 POKEMON_GLDAAUK. +00000144: 30 31 00 10 06 03 01 33 00 08 77 8a 01.....3..w. + +Silver EN + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 45 80 POKEMON_SLVAAXE. +00000144: 30 31 03 10 06 03 01 33 00 2a 0d ae 01.....3.*.. + +Silver DE + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 44 80 POKEMON_SLVAAXD. +00000144: 30 31 03 10 06 03 01 33 00 2b cd 6e 01.....3.+.n + +Silver FR + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 46 80 POKEMON_SLVAAXF. +00000144: 30 31 03 10 06 03 01 33 00 29 fb 8c 01.....3.).. + +Silver IT + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 49 80 POKEMON_SLVAAXI. +00000144: 30 31 03 10 06 03 01 33 00 26 73 50 01.....3.&sP + +Silver SP + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 53 80 POKEMON_SLVAAXS. +00000144: 30 31 03 10 06 03 01 33 00 1c 06 4b 01.....3...K + +Silver JP rev0 + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 4a 80 POKEMON_SLVAAXJ. +00000144: 30 31 03 10 05 03 00 33 00 27 76 91 01.....3.'v. + +Silver JP revA + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 4a 80 POKEMON_SLVAAXJ. +00000144: 30 31 03 10 05 03 00 33 01 26 1d 34 01.....3.&.4 + +Silver KOR + +00000134: 50 4f 4b 45 4d 4f 4e 5f 53 4c 56 41 41 58 4b c0 POKEMON_SLVAAXK. +00000144: 30 31 00 10 06 03 01 33 00 e7 98 5b 01.....3...[ + +Crystal EN + +00000134: 50 4d 5f 43 52 59 53 54 41 4c 00 42 59 54 45 c0 PM_CRYSTAL.BYTE. +00000144: 30 31 00 10 06 03 01 33 01 26 18 d2 01.....3.&.. + +Crystal DE + +00000134: 50 4d 5f 43 52 59 53 54 41 4c 00 42 59 54 44 c0 PM_CRYSTAL.BYTD. +00000144: 30 31 00 10 06 03 01 33 00 28 49 82 01.....3.(I. + +Crystal FR + +00000134: 50 4d 5f 43 52 59 53 54 41 4c 00 42 59 54 46 c0 PM_CRYSTAL.BYTF. +00000144: 30 31 00 10 06 03 01 33 00 26 f2 e2 01.....3.&.. + +Crystal IT + +00000134: 50 4d 5f 43 52 59 53 54 41 4c 00 42 59 54 49 c0 PM_CRYSTAL.BYTI. +00000144: 30 31 00 10 06 03 01 33 00 23 db ba 01.....3.#.. + +Crystal SP + +00000134: 50 4d 5f 43 52 59 53 54 41 4c 00 42 59 54 53 c0 PM_CRYSTAL.BYTS. +00000144: 30 31 00 10 06 03 01 33 00 19 42 f4 01.....3..B. + +Crystal JP + +00000134: 50 4d 5f 43 52 59 53 54 41 4c 00 42 58 54 4a c0 PM_CRYSTAL.BXTJ. +00000144: 30 31 00 10 06 05 00 33 00 22 9a 40 01.....3.".@ \ No newline at end of file diff --git a/tools/gb-payload-generator/documentation/ROMHEADER_CHECKSUMS.txt b/tools/gb-payload-generator/documentation/ROMHEADER_CHECKSUMS.txt new file mode 100644 index 0000000..fcb7640 --- /dev/null +++ b/tools/gb-payload-generator/documentation/ROMHEADER_CHECKSUMS.txt @@ -0,0 +1,25 @@ +Yellow 97 04 7C +Yellow FR 61 66 FB +Yellow DE 5F B7 C1 +Yellow IT 5C 4E 8F +Yellow SP 52 56 37 +Yellow JP 1.0 20 9C 29 +Yellow JP 1.1 1F 88 58 +Yellow JP 1.2 1E ED D9 +Yellow JP 1.3 1D D9 84 + +Red EN 20 91 E6 +Blue EN D3 9D 0A +Red FR 18 7A FC +Blue FR CB 56 A4 +Red DE 18 5C DC +Blue DE CB 2E BC +Red IT 18 89 D2 +Blue IT CB 5E 9C +Red SP 18 38 4A +Blue SP CB 14 D7 +Red JP v1.0 32 A2 C1 +Green JP v1.0 9C DD D5 +Red JP v1.1 31 B8 66 +Green JP v1.1 9B F5 47 +Blue JP E5 DC 36 \ No newline at end of file diff --git a/tools/gb-payload-generator/documentation/ROMHEADER_CHECKSUMS_GEN2.txt b/tools/gb-payload-generator/documentation/ROMHEADER_CHECKSUMS_GEN2.txt new file mode 100644 index 0000000..3b35526 --- /dev/null +++ b/tools/gb-payload-generator/documentation/ROMHEADER_CHECKSUMS_GEN2.txt @@ -0,0 +1,33 @@ +Gold EN 4b 68 2d +Gold DE 4c dc 97 +Gold FR 4a 6f c6 +Gold IT 47 ce 0c +Gold SP 3d 93 53 +Gold JP rev0 48 8a 70 +Gold JP revA 47 84 60 +Gold KOR 08 77 8a +Silver EN 2a 0d ae +Silver DE 2b cd 6e +Silver FR 29 fb 8c +Silver IT 26 73 50 +Silver SP 1c 06 4b +Silver JP rev0 27 76 91 +Silver JP revA 26 1d 34 +Silver KOR e7 98 5b +Crystal EN 26 18 d2 +Crystal DE 28 49 82 +Crystal FR 26 f2 e2 +Crystal IT 23 db ba +Crystal SP 19 42 f4 +Crystal JP 22 9a 40 + +Serial_ExchangeBytes + +gs en 06aa 0710 = 66 +gs jp 06a9 070f = 66 +kor gs 0698 06fe = 66 +c 06ef 075F = 70 + +PlaceWaitingText + +all 01:4000 \ No newline at end of file diff --git a/tools/gb-payload-generator/documentation/UniversalPayloadGen2.txt b/tools/gb-payload-generator/documentation/UniversalPayloadGen2.txt new file mode 100644 index 0000000..baa4307 --- /dev/null +++ b/tools/gb-payload-generator/documentation/UniversalPayloadGen2.txt @@ -0,0 +1,127 @@ + Full party data to be sent: + +4E 4E 85 84 8D 8D 84 8B 4E 4E 4E 4E 4E 4E 4E 4E +01 4F 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 80 80 80 +80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 +80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 D8 +C6 4E 80 80 80 80 80 80 80 80 80 80 D8 C5 01 50 +5A 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 1E 80 80 80 80 80 80 80 80 80 +80 80 80 80 80 D8 C5 50 + + Components of the setup + +Patch List (placed at 0xC5D0 on G/S, 0xC6D0 on C) + +FD FD FD FD FD FF FF + +RNG seed + +// any value works + +Trainer ID ; content chosen to display as little graphic corruption as possible + +4E 4E + +Trainer name ; limited to 6 chars due to JP character limits + +85 84 8D 8D 84 8B + +non JP trainer name ; additional bytes sent as part of the non-JP trainer names + +4E 4E 4E 4E 4E + +Party Data + +4E 4E 4E ; gen 2 does some strange copying involving names, these assure that we're not encountering any accidental errors because of that. +01 4F ; 0x4F sets the current write pointer to 0xC4E1 (G/S) or 0xC5E1 (C). This ensures consistency between languages. Using 0x4F like this on KOR would cause a crash, 0x01 is used to effectively hide it by forming a 2-byte text character. +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E +4E 4E 4E 4E 4E 4E 4E 4E 4E 4E 4E ; moves write pointer to 0xDF99 (G/S) or 0xE099 (C) +80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 +80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 +80 80 D8 C6 ; stack smashes Crystal and redirects to Patch List once the next text terminator is read. +4E +80 80 80 80 80 80 80 80 80 80 D8 C5 ; stack smashes Gold/Silver (non-KOR) and redirects to Patch List once the next text terminator is read. +01 50 ; on KOR, 01 50 forms a 2-byte text character, causing it to keep printing. On non-KOR, the 0x50 is read separately and acts as a text terminator. Everything past this is only used by KOR. +5A ; 0x5A sets the current write pointer to 0xC4E1 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +59 59 59 59 59 ; moves write pointer to 0xCFA9 +1E ; moves write pointer to 0xCFBD +80 80 80 80 80 80 80 80 80 80 80 80 80 80 D8 C5 ; stack smashes Gold/Silver (KOR) and redirects to Patch List once the next text terminator is read. +50 ; acts as text terminator. + + +0x4F (non-KOR) and 0x5F (KOR) place the current character at 0xC4E1. + +Each use of 0x4E (non-KOR) and 0x59 (kor) starts writing 40 bytes after the start of the current line. + +The location of the stack smash is not always constant: + - For Gold/Silver (non-KOR), we aim to overwrite 0xDFCB and 0xDFCC + - For Crystal, we aim to overwrite 0xE0BB and 0xE0BC + - For Gold/Silver (KOR), we aim to overwrite 0xCFCB and 0x CDCC + + Notes on the addresses of Korean control code characters: + +KOR TEXT: 0F7E + +below 0C - 1229 +5A - 118B +59 - 1179 +00 - 1218? +57 - 11D4 +56 - 11BC +5C - 1193 +5B - 1066 +51 - 106D +52 - 1074 +35 - 10C8 +36 - 10CF +37 - 10D6 +4D - 107B +4E - 1082 +47 - 10A5 +49 - 1097 +4B - 109E +4A - 1090 +55 - 1089 +1F - 10AC +1E - 1182 +5D - 11E2 +48 - 10B3 +5E - 1211 +5F - 11F7 +46 - 10BA +33 - 10C1 +34 - 0F7A +1D - space +4C - 11F3 +53 - 10DD +54 - 10E3 +4F - 10FB +E4 - 1030 +E5 - 1037 \ No newline at end of file diff --git a/tools/gb-payload-generator/include/constants/attribution.txt b/tools/gb-payload-generator/include/constants/attribution.txt new file mode 100644 index 0000000..6250392 --- /dev/null +++ b/tools/gb-payload-generator/include/constants/attribution.txt @@ -0,0 +1 @@ +All files in this folder were taken from the pokered pret disassembly: https://github.com/pret/pokered \ No newline at end of file diff --git a/tools/gb-payload-generator/include/constants/charmap.asm b/tools/gb-payload-generator/include/constants/charmap.asm index f096797..d426611 100644 --- a/tools/gb-payload-generator/include/constants/charmap.asm +++ b/tools/gb-payload-generator/include/constants/charmap.asm @@ -3,6 +3,7 @@ ; Control characters (see home/text.asm) charmap "", $00 + charmap "", $1e charmap "", $49 charmap "", $4a ; "" charmap "<_CONT>", $4b ; implements "" @@ -18,7 +19,9 @@ charmap "<……>", $56 ; "……" charmap "", $57 charmap "", $58 + charmap "",$59 charmap "", $59 + charmap "",$5a charmap "", $5a charmap "", $5b ; "PC" charmap "", $5c ; "TM" diff --git a/tools/gb-payload-generator/include/constants/pokemon_constants.asm b/tools/gb-payload-generator/include/constants/pokemon_constants.asm new file mode 100644 index 0000000..ea206bb --- /dev/null +++ b/tools/gb-payload-generator/include/constants/pokemon_constants.asm @@ -0,0 +1,209 @@ +; pokemon ids +; indexes for: +; - MonsterNames (see data/pokemon/names.asm) +; - EvosMovesPointerTable (see data/pokemon/evos_moves.asm) +; - CryData (see data/pokemon/cries.asm) +; - PokedexOrder (see data/pokemon/dex_order.asm) +; - PokedexEntryPointers (see data/pokemon/dex_entries.asm) + const_def + const NO_MON ; $00 + const RHYDON ; $01 + const KANGASKHAN ; $02 + const NIDORAN_M ; $03 + const CLEFAIRY ; $04 + const SPEAROW ; $05 + const VOLTORB ; $06 + const NIDOKING ; $07 + const SLOWBRO ; $08 + const IVYSAUR ; $09 + const EXEGGUTOR ; $0A + const LICKITUNG ; $0B + const EXEGGCUTE ; $0C + const GRIMER ; $0D + const GENGAR ; $0E + const NIDORAN_F ; $0F + const NIDOQUEEN ; $10 + const CUBONE ; $11 + const RHYHORN ; $12 + const LAPRAS ; $13 + const ARCANINE ; $14 + const MEW ; $15 + const GYARADOS ; $16 + const SHELLDER ; $17 + const TENTACOOL ; $18 + const GASTLY ; $19 + const SCYTHER ; $1A + const STARYU ; $1B + const BLASTOISE ; $1C + const PINSIR ; $1D + const TANGELA ; $1E + const_skip ; $1F + const_skip ; $20 + const GROWLITHE ; $21 + const ONIX ; $22 + const FEAROW ; $23 + const PIDGEY ; $24 + const SLOWPOKE ; $25 + const KADABRA ; $26 + const GRAVELER ; $27 + const CHANSEY ; $28 + const MACHOKE ; $29 + const MR_MIME ; $2A + const HITMONLEE ; $2B + const HITMONCHAN ; $2C + const ARBOK ; $2D + const PARASECT ; $2E + const PSYDUCK ; $2F + const DROWZEE ; $30 + const GOLEM ; $31 + const_skip ; $32 + const MAGMAR ; $33 + const_skip ; $34 + const ELECTABUZZ ; $35 + const MAGNETON ; $36 + const KOFFING ; $37 + const_skip ; $38 + const MANKEY ; $39 + const SEEL ; $3A + const DIGLETT ; $3B + const TAUROS ; $3C + const_skip ; $3D + const_skip ; $3E + const_skip ; $3F + const FARFETCHD ; $40 + const VENONAT ; $41 + const DRAGONITE ; $42 + const_skip ; $43 + const_skip ; $44 + const_skip ; $45 + const DODUO ; $46 + const POLIWAG ; $47 + const JYNX ; $48 + const MOLTRES ; $49 + const ARTICUNO ; $4A + const ZAPDOS ; $4B + const DITTO ; $4C + const MEOWTH ; $4D + const KRABBY ; $4E + const_skip ; $4F + const_skip ; $50 + const_skip ; $51 + const VULPIX ; $52 + const NINETALES ; $53 + const PIKACHU ; $54 + const RAICHU ; $55 + const_skip ; $56 + const_skip ; $57 + const DRATINI ; $58 + const DRAGONAIR ; $59 + const KABUTO ; $5A + const KABUTOPS ; $5B + const HORSEA ; $5C + const SEADRA ; $5D + const_skip ; $5E + const_skip ; $5F + const SANDSHREW ; $60 + const SANDSLASH ; $61 + const OMANYTE ; $62 + const OMASTAR ; $63 + const JIGGLYPUFF ; $64 + const WIGGLYTUFF ; $65 + const EEVEE ; $66 + const FLAREON ; $67 + const JOLTEON ; $68 + const VAPOREON ; $69 + const MACHOP ; $6A + const ZUBAT ; $6B + const EKANS ; $6C + const PARAS ; $6D + const POLIWHIRL ; $6E + const POLIWRATH ; $6F + const WEEDLE ; $70 + const KAKUNA ; $71 + const BEEDRILL ; $72 + const_skip ; $73 + const DODRIO ; $74 + const PRIMEAPE ; $75 + const DUGTRIO ; $76 + const VENOMOTH ; $77 + const DEWGONG ; $78 + const_skip ; $79 + const_skip ; $7A + const CATERPIE ; $7B + const METAPOD ; $7C + const BUTTERFREE ; $7D + const MACHAMP ; $7E + const_skip ; $7F + const GOLDUCK ; $80 + const HYPNO ; $81 + const GOLBAT ; $82 + const MEWTWO ; $83 + const SNORLAX ; $84 + const MAGIKARP ; $85 + const_skip ; $86 + const_skip ; $87 + const MUK ; $88 + const_skip ; $89 + const KINGLER ; $8A + const CLOYSTER ; $8B + const_skip ; $8C + const ELECTRODE ; $8D + const CLEFABLE ; $8E + const WEEZING ; $8F + const PERSIAN ; $90 + const MAROWAK ; $91 + const_skip ; $92 + const HAUNTER ; $93 + const ABRA ; $94 + const ALAKAZAM ; $95 + const PIDGEOTTO ; $96 + const PIDGEOT ; $97 + const STARMIE ; $98 + const BULBASAUR ; $99 + const VENUSAUR ; $9A + const TENTACRUEL ; $9B + const_skip ; $9C + const GOLDEEN ; $9D + const SEAKING ; $9E + const_skip ; $9F + const_skip ; $A0 + const_skip ; $A1 + const_skip ; $A2 + const PONYTA ; $A3 + const RAPIDASH ; $A4 + const RATTATA ; $A5 + const RATICATE ; $A6 + const NIDORINO ; $A7 + const NIDORINA ; $A8 + const GEODUDE ; $A9 + const PORYGON ; $AA + const AERODACTYL ; $AB + const_skip ; $AC + const MAGNEMITE ; $AD + const_skip ; $AE + const_skip ; $AF + const CHARMANDER ; $B0 + const SQUIRTLE ; $B1 + const CHARMELEON ; $B2 + const WARTORTLE ; $B3 + const CHARIZARD ; $B4 + const_skip ; $B5 + const FOSSIL_KABUTOPS ; $B6 + const FOSSIL_AERODACTYL ; $B7 + const MON_GHOST ; $B8 + const ODDISH ; $B9 + const GLOOM ; $BA + const VILEPLUME ; $BB + const BELLSPROUT ; $BC + const WEEPINBELL ; $BD + const VICTREEBEL ; $BE + +DEF NUM_POKEMON_INDEXES EQU const_value - 1 + +; starters +DEF STARTER1 EQU CHARMANDER +DEF STARTER2 EQU SQUIRTLE +DEF STARTER3 EQU BULBASAUR + +; ghost Marowak in Pokémon Tower +DEF RESTLESS_SOUL EQU MAROWAK diff --git a/tools/gb-payload-generator/include/constants/symbols.asm b/tools/gb-payload-generator/include/constants/symbols.asm index f7188a7..da04c64 100644 --- a/tools/gb-payload-generator/include/constants/symbols.asm +++ b/tools/gb-payload-generator/include/constants/symbols.asm @@ -1,4 +1,9 @@ +DEF NULL = 0x0 +DEF FarCall = 0x8 +DEF Bankswitch_GSC = 0x10 +DEF SerialInterrupt = 0x58 DEF Start = 0x100 +DEF ClearScreen_KOR = 0x0F00 DEF ClearScreen = 0x190F DEF PlaceString = 0x1955 DEF SoftReset = 0x1F49 @@ -11,13 +16,34 @@ DEF SavePartyAndDexDataBank = 0x1C DEF SavePartyAndDexData = 0x780F DEF RemovePokemon = 0x7B68 +DEF wMusicFadeID = 0xC1A9 DEF wTileMap = 0xC3A0 DEF wSerialPartyMonsPatchList = 0xC508 DEF wSerialEnemyMonsPatchList = 0xC5D0 +DEF wSerialEnemyMonsPatchList_GS = 0xC5D0 +DEF wSerialEnemyMonsPatchList_C = 0xC6D0 DEF wSerialOtherGameboyRandomNumberListBlock = 0xCD91 DEF wWhichPokemon = 0xCF92 DEF wRemoveMonFromBox = 0xCF95 DEF wSerialEnemyDataBlock = 0xD893 DEF wBoxCount = 0xDA80 -DEF hOnCGB = 0xFFFE \ No newline at end of file +DEF SerialPatchAlignedAddress = 0xC800 +DEF SpecificPayloadAddress = 0xC900 +DEF SerialOffset_GS = 0x66 +DEF SerialOffset_C = 0x70 + +DEF hOnCGB = 0xFFFE +DEF hCGB_GS = 0xFFE8 +DEF hCGB_C = 0xFFE6 + +DEF PlaceWaitingText = 0x4000 +DEF PlaceWaitingTextBank = 0x01 + +DEF CHECKSUMPACKET_SIZE = 7 +DEF PATCHLIST_SIZE = 200 + +DEF RNGSIZE_GEN2 = 0x11 +DEF LINKDATASIZE_GEN2 = 0x1C2 +DEF PATCHLIST_GEN2 = 0xC8 +DEF LINKMAILSIZE_GEN1 = 0x186 \ No newline at end of file diff --git a/tools/gb-payload-generator/include/macros/attribution.txt b/tools/gb-payload-generator/include/macros/attribution.txt new file mode 100644 index 0000000..296638d --- /dev/null +++ b/tools/gb-payload-generator/include/macros/attribution.txt @@ -0,0 +1 @@ +const.asm and its contents were taken from the pokered pret disassembly: https://github.com/pret/pokered \ No newline at end of file diff --git a/tools/gb-payload-generator/include/macros/const.asm b/tools/gb-payload-generator/include/macros/const.asm new file mode 100644 index 0000000..d6a3467 --- /dev/null +++ b/tools/gb-payload-generator/include/macros/const.asm @@ -0,0 +1,58 @@ +; Enumerate constants + +MACRO? const_def + IF _NARG >= 1 + DEF const_value = \1 + ELSE + DEF const_value = 0 + ENDC + IF _NARG >= 2 + DEF const_inc = \2 + ELSE + DEF const_inc = 1 + ENDC +ENDM + +MACRO? const + DEF \1 EQU const_value + DEF const_value += const_inc +ENDM + +MACRO? const_export + const \1 + EXPORT \1 +ENDM + +MACRO? shift_const + DEF \1 EQU 1 << const_value + DEF const_value += const_inc +ENDM + +MACRO? const_skip + if _NARG >= 1 + DEF const_value += const_inc * (\1) + else + DEF const_value += const_inc + endc +ENDM + +MACRO? const_next + if (const_value > 0 && \1 < const_value) || (const_value < 0 && \1 > const_value) + fail "const_next cannot go backwards from {const_value} to \1" + else + DEF const_value = \1 + endc +ENDM + +MACRO? dw_const + dw \1 + const \2 +ENDM + +MACRO? rb_skip + IF _NARG == 1 + rsset _RS + \1 + ELSE + rsset _RS + 1 + ENDC +ENDM diff --git a/tools/gb-payload-generator/src/payloads/payload_rb.asm b/tools/gb-payload-generator/src/payloads/payload_rb.asm deleted file mode 100644 index 5a345a6..0000000 --- a/tools/gb-payload-generator/src/payloads/payload_rb.asm +++ /dev/null @@ -1,137 +0,0 @@ -INCLUDE "../../include/constants/charmap.asm" -INCLUDE "../../include/constants/serial_constants.asm" -INCLUDE "../../include/constants/symbols.asm" -INCLUDE "../../include/payload/species.asm" -INCLUDE "../../include/payload/payload.asm" -INCLUDE "../../include/payload/patches.asm" -INCLUDE "../../include/payload/settings.asm" - -DEF packetStartAddress = 0xCFE7 -DEF packetSize = 8 - -SECTION "Payload", ROM0 -Payload: -LOAD "RNGSeed", WRAM0[wSerialOtherGameboyRandomNumberListBlock - 1] -RNGSeed: - ds 5 - jp SerialPatchList -.end -ds RNGSEED_SIZE - (RNGSeed.end - RNGSeed), 0 -ENDL - - -LOAD "PartyData", WRAMX[wSerialEnemyDataBlock - 1] -PartyDataPreamble: - ds 7, SERIAL_PREAMBLE_BYTE -.end - -PartyData: - db RIVAL_NAME - ds 11 - STRLEN(RIVAL_NAME), CHARVAL("@") -.partyCount - db 0x06 -.partyList - ds 0x160, shortMon - db 0xFC - db 0xFF -.transferList - ds 30, SERIAL_PREAMBLE_BYTE - ds 11, 0xFF -.end -ds PAYLOAD_SIZE - (PartyData.end - PartyDataPreamble), 0 -ENDL - -LOAD "serialPatch", WRAM0[wSerialEnemyMonsPatchList - 1] -SerialPatchPreamble: - ds 5, SERIAL_PREAMBLE_BYTE - ds 2, SERIAL_PATCH_LIST_PART_TERMINATOR -.end - -SerialPatchList: - call ClearScreen - ld hl, wTileMap + 0x8F - ld bc, (textBorderHeight << 8) + textBorderWidth - call CableClub_TextBoxBorder - ld l, LOW(0x44) - ld de, .waitString - call PlaceString - -.sendPacketLoop - ld hl, 0xCFFD - ld a, [hli] - ld d, [hl] - ld e, a - ld hl, packetStartAddress - ld c, 0 -.packet_loop - ld b, 0 - ld a, [de] - add a, c - ld c, a - ld a, [de] - inc de - cp a, SERIAL_NO_DATA_BYTE - jr nz, .feBypass - dec a - inc b -.feBypass - ld [hli], a - ld [hl], b - inc hl - ld a, LOW(packetStartAddress + 2 * packetSize) - cp a, l - jr nz, .packet_loop - ld a, c - res 7, a - ld [hli], a - ld a, d - ld [hli], a - ld a, e - ld [hli], a - - ld a, 1 - ldh [0xFFAA], a - ld hl, 0xCFE5 - ld [hl], SERIAL_PREAMBLE_BYTE - inc hl - ld [hl], 0 - dec hl - ld de, 0xCFFA - ld bc, 0x15 - call Serial_ExchangeBytes - ld a, [0xCFFE] - inc a - jr nz, .sendPacketLoop - - inc a - ldh [0xFFAA], a - ld [wRemoveMonFromBox], a - ld hl, 0x316 - ld de, PartyData.transferList - ld bc, 0x1E - call Serial_ExchangeBytes - ld hl, PartyData.transferList -.removeArrayLoop - ld a, [wBoxCount] - ld b, a - ld a, [hli] - cp a, 0xFF - jr z, .saveBox - cp a, b - jr nc, .removeArrayLoop - - ld [wWhichPokemon], a - push hl - call RemovePokemon - pop hl - jr .removeArrayLoop -.saveBox - ld b, SaveCurrentBoxDataBank - ld hl, SaveCurrentBoxData - call Bankswitch - jp SoftReset -.waitString - db "SENDING DATA@" -.end -ds PATCHLIST_SIZE - (SerialPatchList.end - SerialPatchPreamble), 0 - \ No newline at end of file diff --git a/tools/gb-payload-generator/src/payloads/payload_rb_experimental.asm b/tools/gb-payload-generator/src/payloads/payload_rb_experimental.asm deleted file mode 100644 index a8895a9..0000000 --- a/tools/gb-payload-generator/src/payloads/payload_rb_experimental.asm +++ /dev/null @@ -1,161 +0,0 @@ -INCLUDE "../../include/constants/charmap.asm" -INCLUDE "../../include/constants/serial_constants.asm" -INCLUDE "../../include/constants/symbols.asm" -INCLUDE "../../include/payload/species.asm" -INCLUDE "../../include/payload/payload.asm" -INCLUDE "../../include/payload/patches.asm" -INCLUDE "../../include/payload/settings.asm" - -SECTION "Universal payload non-JP R/B", ROM0 - -; RNG Seed -; 10 Bytes -; Location of the entrance vector - -LOAD "RNGSeed", WRAM0[wSerialOtherGameboyRandomNumberListBlock - 1] -RNGSeed: - ds 5 - jp SerialPatchList -.end -ds RNGSEED_SIZE - (RNGSeed.end - RNGSeed), 0 -ENDL - -; Payload, consisting of preamble, rival name and actual party data - -; Preamble (offset 0x00) -; 0x07 in length -; must be filled with 0xFD, one 0xFD will be consumed and fail to transfer. - -; Rival name (offset 0x07) -; 0x0B in lenth -; Set to the stored name - -; Party Data (offset 0x12) -; Can be up to 0x1A8 bytes in length. -; First byte determines number of pokémon (arbitrary value) -; Following values determine party data, the main part we care about is the pokémon list. -; Since we disrupt the stack with the party list, the party list itself does not need to be terminated. - -LOAD "PAYLOAD", WRAMX[wSerialEnemyDataBlock - 1] -PartyPreamble: - ds 7, SERIAL_PREAMBLE_BYTE -.end -RivalName: - db RIVAL_NAME - ds 11 - STRLEN(RIVAL_NAME), CHARVAL("@") -PartyData: - db 0x06 -.partyList - ds 0x160, shortMon - db pointerMon -.end -ds PAYLOAD_SIZE - (PartyData.end - PartyPreamble), 0 -ENDL - -; SerialPatchPreamble (offset 0x1B4) -; 0x07 in length -; Set as five 0xFD and two 0xFF, prevents patchlist from modifying anything on the party list. - -; SerialPatchList (offset 0x1BB) -; At 0x1BB / 0x1DE, 0xC2 in length (0xC4, but the last 2 are unused) -; Fill with custom code - -LOAD "serialPatch", WRAM0[wSerialEnemyMonsPatchList - 1] -SerialPatchPreamble: - ds 5, SERIAL_PREAMBLE_BYTE - ds 2, SERIAL_PATCH_LIST_PART_TERMINATOR -.end -SerialPatchList: - ld bc, 0x0168 - ld hl, 0xC3A0 -.clearScreenLoop - ld a, 0x7F - ld [hli], a - dec bc - ld a, b - or c - jr nz, .clearScreenLoop - - ld hl, PRINTWAITINGTEXT_OFFSET - ld de, .callPrintWaitingText + 1 - ld bc, PRINTWAITINGTEXT_SEARCH - call .findPointerAndPatch -.callPrintWaitingText - call .callPrintWaitingText - - ld hl, SERIAL_EXCHANGEBYTES_OFFSET - ld de, .callSerial_ExchangeBytes + 3 - ld bc, SERIAL_EXCHANGEBYTES_SEARCH - call .findPointerAndPatch -.sendChecksum - ld hl, 0x14E ; cartridge checksum - ld a, [hli] - ld b, [hl] - - ld hl, SerialPatchPreamble + 3 ; prepare to send cartridge checksum - ld [hli], a - ld [hl], b - inc hl - add a, b - res 7, a - ld [hl], a ; place checksum - ld hl, SerialPatchPreamble + 2 - ld de, wSerialPartyMonsPatchList + 2 - push hl - push hl - push de - ld bc, 0x5 - call .callSerial_ExchangeBytes - pop de - pop hl - ld bc, 0xFF ; placeholder, exact size to be determined - call .callSerial_ExchangeBytes - ; to do: add verification that the payload is correctly processed - pop hl - inc hl - push hl - push hl - pop de - ld c, 0xC0 -.findNotPreamble - ld a, [hli] - cp SERIAL_PREAMBLE_BYTE - jr z, .findNotPreamble -.alignPayload - ld [de], a - inc de - ld a, [hli] - dec c - jp nz, .alignPayload - pop hl - ld a, [hl] - and a, a - jr z, .sendChecksum - inc a - jp z, Start - jp hl -.callSerial_ExchangeBytes - ld a, 1 - jp .callSerial_ExchangeBytes -.findPointerAndPatch -; b = first opcode to search for -; c = second opcode to search for -; de = address to write pointer to -; hl = offset to start searching from -; return destination pointer in hl, made to minimize amount of M-cycles taken - ld a, [hli] - cp b - jr nz, .findPointerAndPatch - ld a, [hl] - cp c - jr nz, .findPointerAndPatch - dec hl - ld a, l - ld [de], a - inc de - ld a, h - ld [de], a - ret -.end -ds PATCHLIST_SIZE - (SerialPatchList.end - SerialPatchPreamble), 0 -ENDL \ No newline at end of file diff --git a/tools/gb-payload-generator/src/payloads/payload_y_experimental.asm b/tools/gb-payload-generator/src/payloads/payload_y_experimental.asm deleted file mode 100644 index 5ed068d..0000000 --- a/tools/gb-payload-generator/src/payloads/payload_y_experimental.asm +++ /dev/null @@ -1,207 +0,0 @@ -INCLUDE "../../include/constants/charmap.asm" -INCLUDE "../../include/constants/serial_constants.asm" -INCLUDE "../../include/constants/symbols.asm" -INCLUDE "../../include/constants/hardware.inc" -INCLUDE "../../include/payload/species.asm" -INCLUDE "../../include/payload/payload.asm" -INCLUDE "../../include/payload/patches.asm" -INCLUDE "../../include/payload/settings.asm" - -SECTION "Universal payload non-JP Y", ROM0 - -; RNG Seed -; 10 Bytes -; Location of the entrance vector - -LOAD "RNGSeed", WRAM0[wSerialOtherGameboyRandomNumberListBlock - 1] -RNGSeed: - ds 5 - jp SerialPatchList -.end -ds RNGSEED_SIZE - (RNGSeed.end - RNGSeed), 0 -ENDL - -; Payload, consisting of preamble, rival name and actual party data - -; Preamble (offset 0x00) -; 0x07 in length -; must be filled with 0xFD, one 0xFD will be consumed and fail to transfer. - -; Rival name (offset 0x07) -; 0x0B in lenth -; Set to the stored name - -; Party Data (offset 0x12) -; Can be up to 0x1A8 bytes in length. -; First byte determines number of pokémon (arbitrary value) -; Following values determine party data, the main part we care about is the pokémon list. -; Since we disrupt the stack with the party list, the party list itself does not need to be terminated. - -LOAD "PAYLOAD", WRAMX[wSerialEnemyDataBlock - 1] -PartyPreamble: - ds 7, SERIAL_PREAMBLE_BYTE -.end -RivalName: - db RIVAL_NAME - ds 11 - STRLEN(RIVAL_NAME), CHARVAL("@") -PartyData: - db 0x06 -.partyList - ds 0x160, shortMon - db pointerMon -.end -ds PAYLOAD_SIZE - (PartyData.end - PartyPreamble), 0 -ENDL - -; SerialPatchPreamble (offset 0x1B4) -; 0x07 in length -; Set as five 0xFD and two 0xFF, prevents patchlist from modifying anything on the party list. - -; SerialPatchList (offset 0x1BB) -; At 0x1BB / 0x1DE, 0xC2 in length (0xC4, but the last 2 are unused) -; Fill with custom code - -; FD FD FD FD FF FF 00 00 00 00 00 00 00 00 00 00 -; 00 00 00 01 68 01 00 00 00 21 A0 C3 3E 7F 22 0B -; 78 B1 20 F8 21 ED 49 11 04 C6 00 00 00 01 6B 21 -; CD 75 C6 CD 03 C6 21 F1 0B 11 71 C6 06 E0 00 00 -; 00 0E AB CD 75 C6 21 4E 01 2A 46 21 D2 C5 22 70 -; 23 F5 00 00 00 F1 80 CB BF 77 21 D1 C5 11 0A C5 -; E5 E5 D5 01 05 00 00 00 00 CD 6E C6 D1 E1 01 FF -; 00 CD 6E C6 E1 23 E5 E5 0E C0 00 00 00 E5 D1 2A -; FE FD 28 FB 12 13 2A 0D C2 54 C6 E1 7E F5 00 00 -; 00 F1 A7 28 B1 3C C0 F0 FE C6 10 C3 00 01 3E 01 -; C3 6E C6 00 00 2A B8 20 FC 7E B9 20 F8 2B 7D 12 -; 13 7C 12 C9 - -; FD FD 8C 84 96 FF|00 00 00 00 00 00 00 00 00 00 -; 00 00 00[00]00 00 8C 84 96 00 00 00 00 00 00 00 -; 00 00 00 00 00 00 00 00 00 00 8C 84 96 00 00 00 -; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8C 84 -; 96 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -; 00 00 8C 84 96 00 00 00 00 00 00 00 00 00 00 00 -; 00 00 00 00 00 00 8C 84 96 00 00 00 00 00 00 00 -; 00 00 00 00 00 00 00 00 00 00 8C 84 96 00 00 00 -; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8C 84 -; 96 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -; 00 00 8C 84 96 00 00 00 00 00 00 00 00 00 00 00 -; 00 00 00 00 00 00 8C 84 96 00 00 00 00 00 00 00 -; 00 00 00 00 00 00 00 00 19 19 8C 84 96 19 19 19 - -; 27 bytes lost -> adc h ; add h; sub a [hl] - -LOAD "serialPatch", WRAM0[wSerialEnemyMonsPatchList - 1] -SerialPatchPreamble: - ds 5, SERIAL_PREAMBLE_BYTE - ds 2, SERIAL_PATCH_LIST_PART_TERMINATOR -.end -SerialPatchList: - ds 13, 0 ; start from 0xC5E4 - ld bc, 0x0168 - ds 3, 0 - ld hl, 0xC3A0 -.clearScreenLoop - ld a, 0x7F - ld [hli], a - dec bc - ld a, b - or c - jr nz, .clearScreenLoop - ld hl, PRINTWAITINGTEXT_OFFSET - ld de, .callPrintWaitingText + 1 - ds 3, 0 - ld bc, PRINTWAITINGTEXT_SEARCH - call .findPointerAndPatch -.callPrintWaitingText - call .callPrintWaitingText - - ld hl, SERIAL_EXCHANGEBYTES_OFFSET - ld de, .callSerial_ExchangeBytes + 3 - ld b, HIGH(SERIAL_EXCHANGEBYTES_SEARCH) - ds 3, 0 - ld c, LOW(SERIAL_EXCHANGEBYTES_SEARCH) - call .findPointerAndPatch -.sendChecksum - ld hl, 0x14E ; cartridge checksum - ld a, [hli] - ld b, [hl] - - ld hl, SerialPatchPreamble + 3 ; prepare to send cartridge checksum - ld [hli], a - ld [hl], b - inc hl - push af - ds 3, 0 - pop af - add a, b - res 7, a - ld [hl], a ; place checksum - ld hl, SerialPatchPreamble + 2 - ld de, wSerialPartyMonsPatchList + 2 - push hl - push hl - push de - ld bc, 0x5 - ds 3, 0 - call .callSerial_ExchangeBytes - pop de - pop hl - ld bc, 0xFF ; placeholder, exact size to be determined - call .callSerial_ExchangeBytes - ; to do: add verification that the payload is correctly processed - pop hl - inc hl - push hl - push hl - ld c, 0xC0 - ds 3, 0 - push hl - pop de -.findNotPreamble - ld a, [hli] - cp SERIAL_PREAMBLE_BYTE - jr z, .findNotPreamble -.alignPayload - ld [de], a - inc de - ld a, [hli] - dec c - jp nz, .alignPayload - pop hl - ld a, [hl] - push af - ds 3, 0 - pop af - and a, a - jr z, .sendChecksum - inc a - ret nz - ldh a, [hOnCGB] - add a, BOOTUP_A_CGB - 1 - jp Start -.callSerial_ExchangeBytes - ld a, 1 - jp .callSerial_ExchangeBytes - ds 2, 0 ; first byte of 3 gets overwritten by RAMPatch -.findPointerAndPatch -; b = first opcode to search for -; c = second opcode to search for -; de = address to write pointer to -; hl = offset to start searching from -; return destination pointer in hl, made to minimize amount of M-cycles taken - ld a, [hli] - cp b - jr nz, .findPointerAndPatch - ld a, [hl] - cp c - jr nz, .findPointerAndPatch - dec hl - ld a, l - ld [de], a - inc de - ld a, h - ld [de], a - ret -.end -ds PATCHLIST_SIZE - (SerialPatchList.end - SerialPatchPreamble), 0 -ENDL \ No newline at end of file diff --git a/tools/gb-payload-generator/src/payloads/universalPayloadGen1.asm b/tools/gb-payload-generator/src/payloads/universalPayloadGen1.asm new file mode 100644 index 0000000..7a9fc2b --- /dev/null +++ b/tools/gb-payload-generator/src/payloads/universalPayloadGen1.asm @@ -0,0 +1,258 @@ +INCLUDE "../../include/constants/charmap.asm" +INCLUDE "../../include/macros/const.asm" +INCLUDE "../../include/constants/serial_constants.asm" +INCLUDE "../../include/constants/pokemon_constants.asm" +INCLUDE "../../include/constants/symbols.asm" +INCLUDE "../../include/constants/hardware.inc" +INCLUDE "../../include/payload/payload.asm" +INCLUDE "../../include/payload/patches.asm" +INCLUDE "../../include/payload/settings.asm" + +SECTION "Payload", ROM0 +Payload: +LOAD "RNGSeed", WRAM0[wSerialOtherGameboyRandomNumberListBlock - 1] +RNGSeed: + ds 7, 0 + jp SerialPatchPreamble.end +.end +ds RNGSEED_SIZE - (RNGSeed.end - RNGSeed), 0 +ENDL + + +LOAD "PartyData", WRAMX[wSerialEnemyDataBlock - 1] +PartyDataPreamble: + ds 7, SERIAL_PREAMBLE_BYTE +.end + +PartyData: + db RIVAL_NAME + ds 6 - STRLEN(RIVAL_NAME), '@' ; This setup is universal, so take JP name size into account. + ds 5, DITTO ; on JP, this becomes part of party data. On other versions, this becomes part of the name. +.partyCount + db DITTO +.partyList + ds 9, DITTO ; Along with previous values, ensures that ditto's species names will be visible on screen. + ds 4, 0xE0 ; Blank name on JP, leaves patch list data as intact as possible. + ds 37, MEW ; Mew is the best available filler, only taking 3 normal text chars of space on every language. + db 0xBF ; Only affects INT Yellow, places FA 60 D3 47 FA 67 D3 CD 7E 47 at 0xC83E. The first character is later read as a pointer. + ds 33, MEW + db 0xC6 ; Only affects INT Yellow, places 19 2A 66 6F E9 FD 47 C9 48 A6 at 0xCAE6. This fetches a pointer from 0xC83D and jumps towards it, effectively jumping to 0xFA0E. + ds 29, MEW + db 0 ; Only affects EN Yellow, places D0 04 19 3D 18 F9 93 91 80 88 8D 84 91 8F 8E 8A BA 21 F0 C6 at 0xCD3D, covering up 0xCD4F and 0xCD50 with safe values. + db 0xC6 ; Only affects EN Yellow, places 19 2A 66 6F E9 FD 47 C9 48 A6 at 0xCD52. This fetches a pointer from 0xCD95 and jumps towards it, effectively jumping to 0xFA1C. + ds 2, MEW + db 0xE3 ; Blank on non-JP RB. This nickname would normally be placed at 0xCD8E, which must be kept clear for the RB payload to work properly. + ds 5, MEW + ds 3, 0xE0 ; Blank on JP, keeps JP as clean as possible. One of these values also prevents the game from becoming unresponsive on non-JP Yellow. + db 0xE3 ; Only affects EN Yellow, places 07 FA 71 C9 FE FF 28 1C FA 70 at 0xCE42. The 8th and 9th character are read as a pointer. + ds 18, 0xE0 + db MEW ; Prevents sound corruption on non-JP versions + ds 27, 0xE0 + db MR_MIME ; Affects the stack on JP versions, following species names will instead be written from address offset 0xD819. + ds 17, 0xE0 + db RAICHU ; Same name on all non-JP versions, prevents wLetterPrintingDelayFlags from being overwritten to values that would slow down text printing. + ds 28, 0xE0 ; On non-JP versions, the 0xE0 at offset 16 will be overwritten to a 0xFE. On EN Yellow, this enables serial interrupt ACE using printer opcode 0xFA, with an effect pointer at 0xCD4F + db PIDGEOTTO ; On JP, the diacritics on the 1st and 2nd characters of this species name (ピジョン) will overwrite the stack, leading to a return to 0xE5E4. + ds 51, MEW + db 0xE4 ; Blank on RB, places C9 FE 81 20 15 FA 71 C9 FE 00 at 0xD9AA, the latter 6 characters are then reinterpreted as species IDs. This causes EN Yellow to get stuck printing 0xC9's name, while ensuring the stack smash species ID remains intact. WHen the player presses A twice on this state, the game will execute code starting from (due to the placement of 0xFE's species name intercepting the expected jump towards 0xFA0E). + ds 62, MEW + jr .skip ; On EN Y, this is placed at 0xD9EC, and safely causes a jump to a safer jump. + ds 14, MEW + db 0xFC ; Used as a stack smasher on all non-JP versions. On RB, this jumps execution to 0xCD8A. On Y, this jumps execution to 0xCAE2. + ds 26, MEW + jp SerialPatchPreamble.end ; Placed at 0xFA1C on non-JP, non-EN versions of Y. + ds 2, MEW +.skip + xor a + ld [0xD499], a + ld b, 1 + ds 3, 0 + call 0x0058 + ld hl, SerialPatchPreamble.end + jp 0x3E84 ; Bankswitch in EN Yellow. PrintWaitingText is located in ROM bank 01, so we must switch to correctly find it. +.end +ds PAYLOAD_SIZE - (PartyData.end - PartyDataPreamble), 0 +ENDL + +LOAD "serialPatch", WRAM0[wSerialEnemyMonsPatchList] +SerialPatchPreamble: + ds 5, SERIAL_PREAMBLE_BYTE + db 0xCA ; places 0xFE in the correct place for the non-JP payload. Due to differences in name sizes, the 0xFE is placed at a -5 offset on the JP versions. This does not cause issues. + ds 2, SERIAL_PATCH_LIST_PART_TERMINATOR +.end +ENDL + +SerialPatchListPayload: + ds 1, 0 + ld bc, 0x0167 + ld hl, 0xC507 ; bottom right screen tile, will always be 0x7F +.clearScreenLoop ; replace all tiles on screen with blank tiles. + dec bc + ld a, [hld] + ld [hl], a + jr .skip + ds 1, 0 ; this value should land on 0xC5E4, the JP entry point4 + jr SerialPatchListPayload + 1 ; not overwritten on JP + ds 3, 0 +.skip + ld a, b + or c + jr nz, .clearScreenLoop + ld hl, SerialPatchListAligned + 1 + inc a ; possibly overwritten on JP + ld [0xC002], a ; always overwritten on JP + ds 1, 0 + push hl + pop de +.findOpcode ; yes, we're cramming this in!! + ld a, [hli] + push af + ld [0xC002], a ; always overwritten on non-JP + ds 1, 0 + pop af + and a, a ; we're skipping all 0 values + jr z, .findOpcode +.alignPayload + ld [de], a + inc e + ld a, [hli] + jr nz, .alignPayload ; align stuff until we hit 0xC6xx +.end +LOAD "serialPatchAligned", WRAM0[0xC607 - 1] +SerialPatchListAligned: + ds 1, 0 + ld hl, PRINTWAITINGTEXT_OFFSET + ld bc, PRINTWAITINGTEXT_SEARCH + ds 4, 0 + call .findPointerAndPatch +.callPrintWaitingText ; use the built in ROM function to print the "waiting" text + call .callPatchedPointer + ld hl, SERIAL_EXCHANGEBYTES_OFFSET + ld bc, SERIAL_EXCHANGEBYTES_SEARCH + call .findPointerAndPatch + ds 5, 0 +.sendChecksum + ld hl, 0x14E ; locate cartridge checksum + ld a, [hli] + ld b, [hl] + ld hl, SerialPatchPreamble + 2 ; prepare to send cartridge checksum + ld [hli], a + ld [hl], b + inc hl + add a, b + res 7, a + ld [hl], a ; place checksum + ds 5, 0 ; expected result is FD FD [16 bit cartridge checksum] [8 bit safety checksum]. There are no valid cartridge checksums containing 0xFD or 0xFE. + ld l, LOW(SerialPatchPreamble) ; send checksum data from this address + ld de, wSerialPartyMonsPatchList ; receive payload at this address + push hl + ld bc, 7 + push de + call .callSerial_ExchangeBytes ; send checksum to PTGB, bc = 0000 on exit + pop de + pop hl + push de + ds 4, 0 + ld c, 200 ; serial patch list size + call .callSerial_ExchangeBytes ; receive specific payload from PTGB + pop hl + push hl + push hl + pop de +.findNotPreamble ; we can't be sure if the payload arrived in the exact desired position. Because of this, let's align the payload. + ld a, [hli] + cp SERIAL_PREAMBLE_BYTE + jr z, .findNotPreamble +.alignPayload ; now that we have found the first non-preamble value, let's align it properly. + ld [de], a + ds 5, 0 + inc e ; we're only aligning stuff within the 0xC500 space + ld a, [hli] + jr nz, .alignPayload + pop hl + ld a, [hl] ; check first non-preamble byte of payload. If 00, resend checksum (incorrect calculated checksum). If FF, an error has occured (correct calculated checksum, but the cartridge checksum is not recognized), so safely reset instead. If any other values, jump to new payload! + and a, a + jr z, .sendChecksum + push hl ; What I wouldn't give for a conditional jp hl + inc a + ret nz + ldh a, [hOnCGB] ; assuming we're on Yellow, we're going to be responsible and make sure the game loads using the correct color mode. + jr .skipFiller + ds 4, 0 +.skipFiller + add a, BOOTUP_A_CGB - 1 + jp Start +.findPointerAndPatch ; searches for specific opcodes from a certain offset and places the resulting pointer at a specific location +; b = first opcode to search for +; c = second opcode to search for +; de = address to write pointer to +; hl = offset to start searching from +; return destination pointer in hl, made to minimize amount of M-cycles taken + ld de, .callPatchedPointer + 1 +.findPointerAndPatchLoop + ld a, [hli] + cp b + jr nz, .findPointerAndPatchLoop + ld a, [hl] + cp c + jr nz, .findPointerAndPatchLoop + ds 4, 0 + dec hl + ld a, l + ld [de], a + inc de + ld a, h + ld [de], a + ret +.callSerial_ExchangeBytes + ld a, IE_SERIAL + ldh [rIE], a +.callPatchedPointer + db 0xC3 +.end +ds PATCHLIST_SIZE - (SerialPatchListAligned.end - SerialPatchListAligned) - (SerialPatchListPayload.end - SerialPatchListPayload) - (SerialPatchPreamble.end - SerialPatchPreamble) - 1, 0 +ENDL + +; FD FD FD FD FD CA FF FF 00 01 67 01 21 07 C5 0B +; 3A 77 18 06 00 18 F2 00 00 00 78 B1 20 F1 21 07 +; C6 00 00 00 00 00 E5 D1 2A F5 00 00 00 00 F1 A7 +; 20 F6 12 1C 2A 20 FB 00 21 ED 49 01 6B 21 00 00 +; 00 00 CD 7B C6 CD 93 C6 21 F1 0B 01 AB E0 CD 7B +; C6 00 00 00 00 00 21 4E 01 2A 46 21 D1 C5 22 70 +; 23 80 CB BF 77 00 00 00 00 00 2E D0 11 08 C5 E5 +; 01 05 00 D5 CD 91 C6 D1 E1 D5 00 00 00 00 0E C8 +; CD 91 C6 E1 E5 E5 D1 2A FE FD 28 FB 12 00 00 00 +; 00 00 1C 2A 20 F6 E1 7E A7 28 BB E5 3C C0 F0 FE +; 18 04 00 00 00 00 C6 10 C3 00 01 11 94 C6 2A B8 +; 20 FC 7E B9 20 F8 00 00 00 00 2B 7D 12 13 7C 12 +; C9 3E 01 C3 93 C6 00 00 + + + ;JP: +; FD FD FD FD FD FF FF 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 A0 8F A1 AB 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +; 00 00 00 00 00 00 00 00 + ;INT: +; FD FD 8C 84 96 CA FF FF 00 00 00 00 00 00 00 00 ; FD FD FD FD FD CA FF FF 00 00 00 00 AF 21 99 D4 +; 00 00 00 00 00 00 8C 84 96 __ 00 00 00 00 00 00 ; 22 22 00 00 00 00 00 00 00 01 68 01 21 A0 C3 00 +; 00 A0 8F A1 AB __ 00 00 00 00 8C 84 96 __ 00 00 ; 00 00 00 00 00 3E 7F 22 0B 00 00 00 00 78 B1 20 +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8C 84 ; F4 21 ED 49 11 11 C6 01 6B 21 CD 79 C6 00 00 00 +; 96 __ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; 00 CD 10 C6 21 F1 0B 11 8E C6 01 AB E0 CD 79 C6 +; 00 00 8C 84 96 __ 00 00 00 00 00 00 00 00 00 00 ; 26 01 00 00 00 2E 4E 2A 46 21 D1 C5 22 70 23 80 +; 00 00 00 00 00 00 8C 84 96 __ 00 00 00 00 00 00 ; CB BF 77 21 D0 C5 00 00 00 11 0A C5 E5 D5 01 05 +; 00 00 00 00 00 00 00 00 00 00 8C 84 96 __ 00 00 ; 00 CD 8B C6 D1 E1 01 C8 00 C5 00 00 00 D5 CD 8B +; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8C 84 ; C6 E1 C1 23 E5 E5 E5 D1 2A FE FD 28 FB 12 00 00 +; 96 __ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; 00 13 0B 78 B1 2A C2 5C C6 E1 7E A7 28 B2 3C C0 +; 00 00 8C 84 96 __ 00 00 00 00 00 00 00 00 00 00 ; F0 FE 00 00 00 C6 10 C3 00 01 2A B8 20 FC 7E B9 +; 00 00 00 00 00 00 8C 84 96 __ 00 00 00 00 00 00 ; 20 F8 2B 7D 12 13 00 00 00 7C 12 C9 3E 01 C3 8B +; 00 00 00 00 00 00 00 00 ; C6 00 00 00 00 00 00 00 00 \ No newline at end of file diff --git a/tools/gb-payload-generator/src/payloads/universalPayloadGen2.asm b/tools/gb-payload-generator/src/payloads/universalPayloadGen2.asm new file mode 100644 index 0000000..0805bdd --- /dev/null +++ b/tools/gb-payload-generator/src/payloads/universalPayloadGen2.asm @@ -0,0 +1,198 @@ +INCLUDE "../../include/constants/charmap.asm" +INCLUDE "../../include/macros/const.asm" +INCLUDE "../../include/constants/serial_constants.asm" +INCLUDE "../../include/constants/pokemon_constants.asm" +INCLUDE "../../include/constants/symbols.asm" +INCLUDE "../../include/constants/hardware.inc" +INCLUDE "../../include/payload/payload.asm" +INCLUDE "../../include/payload/patches.asm" +INCLUDE "../../include/payload/settings.asm" + +SECTION "Payload", ROM0 +Payload: +LOAD "RNGSeed", WRAM0[wSerialOtherGameboyRandomNumberListBlock - 1] +RNGSeed: +.end +ds RNGSIZE_GEN2 - (RNGSeed.end - RNGSeed) - 7, 0 ; 7 bytes of preamble that need to be deducted. +ENDL + +PartyDataPreamble: + ds 6, SERIAL_PREAMBLE_BYTE +.end + +PartyData: + db RIVAL_NAME + ds 6 - STRLEN(RIVAL_NAME), '' ; This setup is universal, so take JP name size into account. + ds 5, '' ; on JP, this becomes part of party data. On other versions, this becomes part of the name. +.partyCount + db '' +.partyList + ds 7, '' +.tid + ds 2, '' +.partyData + db 1 + db '' + ds 171, '' + ds 34, 'A' + dw SerialPatchListPayload + 0x100 + db '' + ds 10, 'A' + dw SerialPatchListPayload + db 1 + db '@' + db '' + ds 69, '' + db '' + ds 14, 'A' + dw SerialPatchListKoreanPayload + db '@' +.end +ds LINKDATASIZE_GEN2 - (PartyData.end - PartyDataPreamble), 0 + +LOAD "serialPatch", WRAM0[wSerialEnemyMonsPatchList_GS] +SerialPatchPreamble: + ds 5, SERIAL_PREAMBLE_BYTE + ds 2, SERIAL_PATCH_LIST_PART_TERMINATOR +.end + +SerialPatchListKoreanPayload: + ds 3, 0 + call ClearScreen_KOR ; KOR has some weirdness in how stuff is displayed. This function provides a full reset of the screen. +.end + +SerialPatchListPayload: ; on GS: this gets loaded in 0xC5D0. On C: this gets loaded in 0xC6D0. Until we align, we can't rely on jp or call. + ds 3, 0 + di + call Bankswitch_GSC + 5 ; jump straight to a ret instruction. +.fetchPC + dec sp + dec sp + pop hl ; since interrupts are disabled, we can retrieve the return pointer of the previous call, effectively retrieving a relative address. + ei + ld bc, wTileMap - .fetchPC + push hl ; store relative address for later + add hl, bc ; if GS: hl = 0xC3A0. If C: hl = 0xC4A0. + ld bc, wSerialPartyMonsPatchList - wTileMap +.clearScreenLoop ; replace all tiles on screen with blank tiles. + ld a, 0x7F + ld [hli], a + dec bc + ld a, b + or c + jr nz, .clearScreenLoop + ld bc, wMusicFadeID - wSerialPartyMonsPatchList + add hl, bc ; if GS: hl = 0xC1A9. If C: hl = 0xC2A9. + xor a + ld [hld], a + ld [hld], a + inc a + ld [hl], a ; This disables music from playing + ld hl, PlaceWaitingText + rst FarCall ; call 01:4000 + pop hl + ld bc, .end - .fetchPC + add hl, bc ; hl now points to the first byte of SerialPatchListAligned + ld de, SerialPatchListAligned + ld bc, SerialPatchListAligned.end - SerialPatchListAligned + push de +.alignPayload ; copy remainder of payload to safer location, then jump towards it. + ld a, [hli] + ld [de], a + inc de + dec c + ret z + jr .alignPayload +.end +ENDL +LOAD "serialPatchAligned", WRAM0[SerialPatchAlignedAddress] +SerialPatchListAligned: + ld a, HIGH(SerialPatchListPayload.end) + sub a, h ; sneaky hack. If we're on GS, this will set the z flag, allowing us to easily determine which version we're running. + push af + ld hl, SerialInterrupt + 1 ; retrieve a pointer to Serial. + ld a, [hli] + ld h, [hl] + ld l, a + ld c, SerialOffset_GS ; if we're on GS, there is a 0x66 byte offset between Serial and Serial_ExchangeBytes. + jr z, .done + ld c, SerialOffset_C ; if we're on C, the offset is 0x70 bytes instead. +.done + add hl, bc + call .patchPointer +.sendChecksum + ld hl, 0x14E ; locate cartridge checksum + ld a, [hli] + ld b, [hl] + ld hl, SerialPatchPreamble + 0x102 ; prepare to send cartridge checksum + ld [hli], a + ld [hl], b + inc hl + add a, b + res 7, a + ld [hl], a ; place checksum + ld l, LOW(SerialPatchPreamble) ; send checksum data from this address + ld a, SERIAL_PREAMBLE_BYTE ; we can't be sure that the first two bytes contain a preamble, so manually add it. + ld [hli], a + ld [hld], a + ld de, SpecificPayloadAddress ; receive payload at this address + push hl + push de + ld bc, CHECKSUMPACKET_SIZE + call .callSerial_ExchangeBytes ; send checksum to PTGB, bc = 0000 on exit + pop de + pop hl + push de + ld c, PATCHLIST_SIZE ; serial patch list size + push bc + call .callSerial_ExchangeBytes ; receive specific payload from PTGB + pop bc + pop hl + push hl + push hl + pop de +.findNotPreamble ; we can't be sure if the payload arrived in the exact desired position. Because of this, let's align the payload. + ld a, [hli] + cp SERIAL_PREAMBLE_BYTE + jr z, .findNotPreamble +.alignPayload ; now that we have found the first non-preamble value, let's align it properly. + ld [de], a + inc de + dec c ; we're only aligning stuff within the 0xC500 space + ld a, [hli] + jr nz, .alignPayload + pop hl + ld a, [hl] ; check first non-preamble byte of payload. If 00, resend checksum (incorrect calculated checksum). If FF, an error has occured (correct calculated checksum, but the cartridge checksum is not recognized), so safely reset instead. If any other values, jump to new payload! + and a, a + jr z, .sendChecksum + push hl ; What I wouldn't give for a conditional jp hl + inc a + ret nz + pop af ; hCGB has a version-specific address, so retrieve the z flag we used earlier. + ldh a, [hCGB_GS] + jr z, .notCrystal + ldh a, [hCGB_C] +.notCrystal + add a, BOOTUP_A_CGB - 1 + rst NULL +.patchPointer ; searches for specific opcodes from a certain offset and places the resulting pointer at a specific location +; b = first opcode to search for +; c = second opcode to search for +; de = address to write pointer to +; hl = offset to start searching from +; return destination pointer in hl, made to minimize amount of M-cycles taken + ld de, .callPatchedPointer + 1 + ld a, l + ld [de], a + inc de + ld a, h + ld [de], a + ret +.callSerial_ExchangeBytes + ld a, IE_SERIAL + ldh [rIE], a +.callPatchedPointer + jp .callPatchedPointer +.end +ds PATCHLIST_GEN2 - (SerialPatchListAligned.end - SerialPatchListAligned) - (SerialPatchListPayload.end - SerialPatchListPayload) - (SerialPatchListKoreanPayload.end - SerialPatchListKoreanPayload) - (SerialPatchPreamble.end - SerialPatchPreamble), 0 +ENDL \ No newline at end of file diff --git a/tools/payload-generator/gb_gen1_payloads_RB.bin b/tools/payload-generator/gb_gen1_payloads_RB.bin new file mode 100644 index 0000000..2516a13 Binary files /dev/null and b/tools/payload-generator/gb_gen1_payloads_RB.bin differ diff --git a/tools/payload-generator/gb_gen1_payloads_Y.bin b/tools/payload-generator/gb_gen1_payloads_Y.bin new file mode 100644 index 0000000..2ef964f Binary files /dev/null and b/tools/payload-generator/gb_gen1_payloads_Y.bin differ diff --git a/tools/payload-generator/gb_gen2_payloads.bin b/tools/payload-generator/gb_gen2_payloads.bin new file mode 100644 index 0000000..7ece860 Binary files /dev/null and b/tools/payload-generator/gb_gen2_payloads.bin differ diff --git a/tools/text_helper/__pycache__/test_regression.cpython-312.pyc b/tools/text_helper/__pycache__/test_regression.cpython-312.pyc deleted file mode 100644 index 18cafc4..0000000 Binary files a/tools/text_helper/__pycache__/test_regression.cpython-312.pyc and /dev/null differ