From c454b2a6e23ca5e4f0226522d37febfe9a153e45 Mon Sep 17 00:00:00 2001 From: GearsProgress Date: Sat, 22 Aug 2026 16:28:29 -0400 Subject: [PATCH] Adding in support for all latin languages and versions --- PCCS | 2 +- container/GB_Payloads.containerdef | 22 +++++ include/dbg/debug_mode.h | 2 +- include/gb_rom_values/base_gb_rom_struct.h | 1 + include/link_handler.h | 102 ++++++++++++++++----- source/link_handler.cpp | 79 ++++++++++++++-- source/script_array.cpp | 27 ++++-- 7 files changed, 195 insertions(+), 40 deletions(-) diff --git a/PCCS b/PCCS index 31ec2e6..ca9ab8c 160000 --- a/PCCS +++ b/PCCS @@ -1 +1 @@ -Subproject commit 31ec2e656888d7a99e99f67972b2516fa2ed126c +Subproject commit ca9ab8c6ab569cd962074487e5702b989430003b diff --git a/container/GB_Payloads.containerdef b/container/GB_Payloads.containerdef index 8a45c43..62cc30c 100644 --- a/container/GB_Payloads.containerdef +++ b/container/GB_Payloads.containerdef @@ -22,5 +22,27 @@ tools/gb-payload-generator/build/specificPayloadGen1/specificPayloadGen1_fr_y.bi tools/gb-payload-generator/build/specificPayloadGen1/specificPayloadGen1_it_y.bin tools/gb-payload-generator/build/specificPayloadGen1/specificPayloadGen1_de_y.bin tools/gb-payload-generator/build/specificPayloadGen1/specificPayloadGen1_sp_y.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_jp_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_jp_g11.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_en_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_fr_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_it_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_de_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_sp_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_kor_g.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_jp_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_jp_s11.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_en_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_fr_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_it_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_de_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_sp_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_kor_s.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_jp_c.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_en_c.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_fr_c.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_it_c.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_de_c.bin +tools/gb-payload-generator/build/specificPayloadGen2/specificPayloadGen2_sp_c.bin tools/gb-payload-generator/build/universalPayloadGen1/universalPayloadGen1.bin tools/gb-payload-generator/build/universalPayloadGen2/universalPayloadGen2.bin diff --git a/include/dbg/debug_mode.h b/include/dbg/debug_mode.h index 5c2fcc8..e1f9e6e 100644 --- a/include/dbg/debug_mode.h +++ b/include/dbg/debug_mode.h @@ -130,7 +130,7 @@ extern debug_options g_debug_options; #define POKEMON_INDEX_TO_SKIP 5 // not sure if we want these in the debug menu. -#define DEBUG_GAME EMERALD_ID +#define DEBUG_GAME RUBY_ID #define DEBUG_VERS VERS_1_0 #define DEBUG_LANG LANG_ENG diff --git a/include/gb_rom_values/base_gb_rom_struct.h b/include/gb_rom_values/base_gb_rom_struct.h index 7d381d3..3763390 100644 --- a/include/gb_rom_values/base_gb_rom_struct.h +++ b/include/gb_rom_values/base_gb_rom_struct.h @@ -88,6 +88,7 @@ public: u32 garbageDataLocation; // location of random data starting with 0xFD in the ROM u32 wRemoveMonFromBox; // location of wRemoveMonFromBox in RAM + u32 wCurrentBoxNum; // location of wCurrentBoxNum in RAM u32 wBoxCount; // location of wBoxCount in RAM u32 wWhichPokemon; // location of wWhichPokemon in RAM u32 wBoxDataStart; // location of wBoxDataStart in RAM diff --git a/include/link_handler.h b/include/link_handler.h index 490ae31..93e1fa5 100644 --- a/include/link_handler.h +++ b/include/link_handler.h @@ -5,6 +5,7 @@ #include "libraries/gba-link-connection/LinkSPI.hpp" #include "GB_Payloads.h" #include "typeDefs.h" +#include "gb_rom_values/base_gb_rom_struct.h" #define SPI_TEXT_OUT_ARRAY_ELEMENT_SIZE 64 @@ -87,28 +88,28 @@ const GB_PayloadsFiles GameBoyROMPayloads[] = GB_PayloadsFiles::SPECIFICPAYLOADGEN1_IT_Y, // YELLOW_IT GB_PayloadsFiles::SPECIFICPAYLOADGEN1_DE_Y, // YELLOW_DE GB_PayloadsFiles::SPECIFICPAYLOADGEN1_SP_Y, // YELLOW_SP - // GOLD_JP_v0 - // GOLD_JP_v1 - // GOLD_EN - // GOLD_FR - // GOLD_IT - // GOLD_DE - // GOLD_SP - // GOLD_KOR - // SILVER_JP_v0 - // SILVER_JP_v1 - // SILVER_EN - // SILVER_FR - // SILVER_IT - // SILVER_DE - // SILVER_SP - // SILVER_KOR - // CRYSTAL_JP - // CRYSTAL_EN - // CRYSTAL_FR - // CRYSTAL_IT - // CRYSTAL_DE - // CRYSTAL_SP + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_JP_G, // GOLD_JP_v0 + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_JP_G11, // GOLD_JP_v1 + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_EN_G, // GOLD_EN + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_FR_G, // GOLD_FR + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_IT_G, // GOLD_IT + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_DE_G, // GOLD_DE + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_SP_G, // GOLD_SP + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_KOR_G, // GOLD_KOR + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_JP_S, // SILVER_JP_v0 + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_JP_S11, // SILVER_JP_v1 + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_EN_S, // SILVER_EN + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_FR_S, // SILVER_FR + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_IT_S, // SILVER_IT + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_DE_S, // SILVER_DE + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_SP_S, // SILVER_SP + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_KOR_S, // SILVER_KOR + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_JP_C, // CRYSTAL_JP + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_EN_C, // CRYSTAL_EN + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_FR_C, // CRYSTAL_FR + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_IT_C, // CRYSTAL_IT + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_DE_C, // CRYSTAL_DE + GB_PayloadsFiles::SPECIFICPAYLOADGEN2_SP_C, // CRYSTAL_SP }; const Language GameBoyROMLanguages[] = @@ -161,6 +162,57 @@ const Language GameBoyROMLanguages[] = SPANISH, // CRYSTAL_SP }; +// This would probably make more sense as a "greater than less than" check. +const Version GameBoyROMVersions[] = + { + RED, // RED_JP_v0 + RED, // RED_JP_v1 + RED, // RED_EN + RED, // RED_FR + RED, // RED_IT + RED, // RED_DE + RED, // RED_SP + GREEN, // GREEN_JP_v0 + GREEN, // GREEN_JP_v1 + BLUE, // BLUE_JP + BLUE, // BLUE_EN + BLUE, // BLUE_FR + BLUE, // BLUE_IT + BLUE, // BLUE_DE + BLUE, // BLUE_SP + YELLOW, // YELLOW_JP_v0 + YELLOW, // YELLOW_JP_v1 + YELLOW, // YELLOW_JP_v2 + YELLOW, // YELLOW_JP_v3 + YELLOW, // YELLOW_EN + YELLOW, // YELLOW_FR + YELLOW, // YELLOW_IT + YELLOW, // YELLOW_DE + YELLOW, // YELLOW_SP + GOLD, // GOLD_JP_v0 + GOLD, // GOLD_JP_v1 + GOLD, // GOLD_EN + GOLD, // GOLD_FR + GOLD, // GOLD_IT + GOLD, // GOLD_DE + GOLD, // GOLD_SP + GOLD, // GOLD_KOR + SILVER, // SILVER_JP_v0 + SILVER, // SILVER_JP_v1 + SILVER, // SILVER_EN + SILVER, // SILVER_FR + SILVER, // SILVER_IT + SILVER, // SILVER_DE + SILVER, // SILVER_SP + SILVER, // SILVER_KOR + CRYSTAL, // CRYSTAL_JP + CRYSTAL, // CRYSTAL_EN + CRYSTAL, // CRYSTAL_FR + CRYSTAL, // CRYSTAL_IT + CRYSTAL, // CRYSTAL_DE + CRYSTAL, // CRYSTAL_SP +}; + // This table has the 3 checksums, followed by the enum value const u8 GameBoyROMChecksumTable[][4]{ {0x32, 0xA2, 0xC1, RED_JP_v0}, @@ -244,6 +296,7 @@ enum LinkConnectionError PACKET_TIMED_OUT, CHECKSUM_MISMATCH, ECHO_MISMATCH, + ERROR_FLAG, PACKET_SUCCESS, PACKET_READ, @@ -321,7 +374,10 @@ public: int gen = 0; // The generation we are trading with Language lang = LANGUAGE_UNKNOWN; // The language we are trading with + Version vers = VERSION_UNKNOWN; // The version we are trading with GameBoyROM currROM = NO_GB_ROM; // The GameBoy ROM we're communicating with + const GB_ROM *pccsROMptr = nullptr; // A pointer to the ROM data for the game we're communicating with + byte boxNum = 0; // The current box the user has selected int FF_count = 0; // The number of 0xFF bytes that have been in a row int zero_count = 0; // The number of 0x00 bytes that have been in a row @@ -368,7 +424,7 @@ public: bool LinkCommand_SoftReset(bool waitForCompletion = true); bool LinkCommand_ModifySRAMAccess(bool enableSRAM, byte SRAMbank, bool waitForCompletion = true); bool LinkCommand_RunSecondaryPayload(byte payload[], int payloadLength, bool waitForCompletion = true); - bool LinkCommand_ReadMemorySection(u16 dataPointer, byte outArray[], int outArraySize, bool waitForCompletion = true); + bool LinkCommand_ReadMemorySection(u32 dataPointer, byte outArray[], int outArraySize, bool waitForCompletion = true); // Some operations are too long to be done within the IRQ. // So we need to handle them in the main loop instead to avoid data corruption. diff --git a/source/link_handler.cpp b/source/link_handler.cpp index 69cb5ed..d739129 100644 --- a/source/link_handler.cpp +++ b/source/link_handler.cpp @@ -18,11 +18,23 @@ #include "text_tables.h" #include "translated_text.h" #include "gb_rom_values/base_gb_rom_struct.h" +#include "gb_rom_values/gb_rom_values.h" +#include "gb_rom_values_jpn_lz10_bin.h" +#include "gb_rom_values_eng_lz10_bin.h" +#include "gb_rom_values_fre_lz10_bin.h" +#include "gb_rom_values_ger_lz10_bin.h" +#include "gb_rom_values_ita_lz10_bin.h" +#include "gb_rom_values_spa_lz10_bin.h" +#include "gb_rom_values_kor_lz10_bin.h" #include "GB_Payloads_chunk0_lz10_bin.h" #include "GB_Payloads_chunk1_lz10_bin.h" #include "GB_Payloads_chunk2_lz10_bin.h" #include "GB_Payloads_chunk3_lz10_bin.h" +#include "GB_Payloads_chunk4_lz10_bin.h" +#include "GB_Payloads_chunk5_lz10_bin.h" +#include "GB_Payloads_chunk6_lz10_bin.h" + #include "GB_Payloads.h" LinkSPI linkSPIInstance; @@ -30,7 +42,7 @@ LinkSPI *linkSPI = &linkSPIInstance; // Here's a compilation check to ensure that the size of these structs match our expectations. // Just update it if you changed the struct members. The data-generator process prints their actual sizes. -static_assert(sizeof(struct GB_ROM) == 136); +static_assert(sizeof(struct GB_ROM) == 140); static_assert(sizeof(struct ROM_DATA) == 160); LinkConnection globalLinkCable; @@ -142,8 +154,11 @@ void LinkConnection::loadPayload(GB_PayloadsFiles payload) (const u8 *)GB_Payloads_chunk1_lz10_bin, (const u8 *)GB_Payloads_chunk2_lz10_bin, (const u8 *)GB_Payloads_chunk3_lz10_bin, + (const u8 *)GB_Payloads_chunk4_lz10_bin, + (const u8 *)GB_Payloads_chunk5_lz10_bin, + (const u8 *)GB_Payloads_chunk6_lz10_bin, }; - FileContainerReader reader(chunkList, 4); + FileContainerReader reader(chunkList, 7); const u32 fileIndex = (u32)payload; reader.init(decompressionBuffer, sizeof(decompressionBuffer)); @@ -158,6 +173,38 @@ void LinkConnection::loadPayloadByROM(GameBoyROM rom) { loadPayload(GameBoyROMPayloads[rom]); lang = GameBoyROMLanguages[rom]; + vers = GameBoyROMVersions[rom]; + + static GB_ROM gb_rom_values_buffer[7]; + const u8 *compressed_rom_values; + + switch (lang){ + case JAPANESE: + compressed_rom_values = gb_rom_values_jpn_lz10_bin; + break; + default: + case ENGLISH: + compressed_rom_values = gb_rom_values_eng_lz10_bin; + break; + case FRENCH: + compressed_rom_values = gb_rom_values_fre_lz10_bin; + break; + case ITALIAN: + compressed_rom_values = gb_rom_values_ita_lz10_bin; + break; + case GERMAN: + compressed_rom_values = gb_rom_values_ger_lz10_bin; + break; + case SPANISH: + compressed_rom_values = gb_rom_values_spa_lz10_bin; + break; + case KOREAN: + compressed_rom_values = gb_rom_values_kor_lz10_bin; + break; + } + + LZ77UnCompWram(compressed_rom_values, gb_rom_values_buffer); + pccsROMptr = &gb_rom_values_buffer[vers - 1]; } void LinkConnection::loadCurrGameFromChecksum() @@ -204,7 +251,7 @@ void LinkConnection::exchangeBytes() case WRITE_CABLE_DATA_MODE_OFF: // Normal transfer :-) inData = linkSPI->transfer(outData); - PTGB_MGBA_INFO("in: %X, out: %X", inData, outData); + // PTGB_MGBA_INFO("in: %X, out: %X", inData, outData); break; case WRITE_CABLE_DATA_MODE_SRAM: // Pretend transfer, by loading the bytes from SRAM (where we stored them with writeData() in a previous transfer) @@ -960,11 +1007,13 @@ bool LinkConnection::processPacket() if ((currIncomingPacket->command != CMD_ReadDataRequest) && (dataOutBuffer[INP_DATA_INDEX] & 0x80)) { + currIncomingPacket->latestError = ERROR_FLAG; PTGB_MGBA_INFO("Packet reports GB command failure: packet=%u cmd=%d encodedFirstData=%X decodedFirstData=%X", currIncomingPacket->packetID, currIncomingPacket->command, dataOutBuffer[INP_DATA_INDEX], currIncomingPacket->recievedData[0]); + return false; } if (currIncomingPacket->command != CMD_ReadDataRequest) @@ -1294,26 +1343,39 @@ bool LinkConnection::LinkCommand_RunSecondaryPayload(byte payload[], int payload return true; }; -bool LinkConnection::LinkCommand_ReadMemorySection(u16 dataPointer, byte outArray[], int outArraySize, bool waitForCompletion) +bool LinkConnection::LinkCommand_ReadMemorySection(u32 dataPointer, byte outArray[], int outArraySize, bool waitForCompletion) { if (g_debug_options.ignore_link_cable) { return true; } + if (dataPointer > 0xFFFF) + { + waitForCompletion = true; // We have to wait for completion with the SRAM bank loading, so we can close it + LinkCommand_ModifySRAMAccess(true, dataPointer >> 16); + } + PTGB_MGBA_INFO("Running command: ReadMemorySection"); resetLinkPackets(); linkPacketDataStart = dataPointer; linkPacketDataSize = outArraySize; - linkPacketDataAddr = dataPointer; + linkPacketDataAddr = dataPointer & 0xFFFF; outDataArrayPtr = outArray; for (int i = 0; i < LINK_PACKET_ARRAY_SIZE; i++) { - linkPacketArr[i] = LinkPacket(CMD_ReadDataRequest, 0x00, 0x00, linkPacketDataAddr); - linkPacketDataAddr += 8; + if ((i * 8) < linkPacketDataSize) + { + linkPacketArr[i] = LinkPacket(CMD_ReadDataRequest, 0x00, 0x00, linkPacketDataAddr); + linkPacketDataAddr += 8; + } + else + { + linkPacketArr[i] = dummyPacket; + } } globalLinkCable.startConnection(PACKET_EXCHANGE); @@ -1321,5 +1383,8 @@ bool LinkConnection::LinkCommand_ReadMemorySection(u16 dataPointer, byte outArra { waitForEnd(); } + + LinkCommand_ModifySRAMAccess(false, dataPointer >> 16); + return true; } \ No newline at end of file diff --git a/source/script_array.cpp b/source/script_array.cpp index 66de159..39e1258 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -706,16 +706,26 @@ bool run_conditional(int index) load_select_sprites(globalLinkCable.currROM); + obj_unhide(gba_cart, 0); + obj_set_pos(gba_cart, 17 * 8, 14 * 8); + + obj_unhide(cart_shell, 0); + obj_set_pos(cart_shell, (8 * 8), (11 * 8) + 11); + + obj_unhide(cart_label, 0); + obj_set_pos(cart_label, (8 * 8) + 8, (11 * 8) + 11 + 13); + + obj_unhide(gba_flag, 0); + obj_set_pos(gba_flag, 23 * 8, 14 * 8); + obj_unhide(gb_flag, 0); obj_set_pos(gb_flag, 1.5 * 8, 14 * 8); + + globalLinkCable.LinkCommand_ReadMemorySection(globalLinkCable.pccsROMptr->wCurrentBoxNum, &globalLinkCable.boxNum, 1); - globalLinkCable.skipPrint = false; - globalLinkCable.pauseOnPacket = true; - - byte boxDataArray[1122]; - - globalLinkCable.LinkCommand_ReadMemorySection(0xDA80, - boxDataArray, 1122); + byte boxDataArray[globalLinkCable.pccsROMptr->box_data_size]; + globalLinkCable.LinkCommand_ReadMemorySection(globalLinkCable.pccsROMptr->wBoxDataStart, + boxDataArray, globalLinkCable.pccsROMptr->box_data_size); box.loadData(globalLinkCable.gen, globalLinkCable.lang, boxDataArray); @@ -753,6 +763,7 @@ bool run_conditional(int index) { set_missingno(false); } + globalLinkCable.LinkCommand_SoftReset(); return true; case CMD_LANG_MENU: @@ -804,7 +815,7 @@ bool run_conditional(int index) } boxRemovalPayload[arrayIndex] = 0xFF; arrayIndex++; - globalLinkCable.LinkCommand_TransferPokemon(2, boxRemovalPayload, arrayIndex); + globalLinkCable.LinkCommand_TransferPokemon(globalLinkCable.boxNum, boxRemovalPayload, arrayIndex); } return true;