diff --git a/include/debug_mode.h b/include/debug_mode.h index 704bf49..5430df2 100644 --- a/include/debug_mode.h +++ b/include/debug_mode.h @@ -2,7 +2,7 @@ #define DEBUG_MODE_H #define DEBUG_MODE true -#define IGNORE_GAME_PAK true +#define IGNORE_GAME_PAK false #define IGNORE_LINK_CABLE false #define IGNORE_MG_E4_FLAGS true diff --git a/include/gameboy_colour.h b/include/gameboy_colour.h index 87536c1..204dcd9 100644 --- a/include/gameboy_colour.h +++ b/include/gameboy_colour.h @@ -31,11 +31,12 @@ #define SLOW_SPEED 1000 void setup(); -byte handleIncomingByte(byte in); +byte handleIncomingByte(byte in, byte* party_data); int transferBit(byte *party_data); int loop(byte *party_data); std::string outHexStr(vu8 inputNum); void updateFrames(); byte exchange_parties(byte); +byte exchange_boxes(byte curr_in, byte *party_data); #endif /* GAMEBOY_COLOUR_H_ */ diff --git a/include/payload.h b/include/payload.h index 7f6df3d..f7e8ef4 100644 --- a/include/payload.h +++ b/include/payload.h @@ -4,6 +4,7 @@ #include #include "output.h" +#define PAYLOAD_SIZE 637 extern byte gen1_eng_payload[637]; #endif \ No newline at end of file diff --git a/include/rom_values/rom_values_eng.h b/include/rom_values/rom_values_eng.h index 7d4a605..69c7d06 100644 --- a/include/rom_values/rom_values_eng.h +++ b/include/rom_values/rom_values_eng.h @@ -114,9 +114,117 @@ const struct ROM_DATA ENG_RUBY_v1 = { .test_map_id = 2, .test_npc_id = 3, }; -const struct ROM_DATA ENG_SAPPHIRE_v1 = {0}; -const struct ROM_DATA ENG_RUBY_v2 = {0}; -const struct ROM_DATA ENG_SAPPHIRE_v2 = {0}; +const struct ROM_DATA ENG_SAPPHIRE_v1 = { + .is_valid = true, + + .gamecode = SAPPHIRE_ID, + .version = VERS_1_1, + .language = LANG_ENG, + + .loc_copyMonToPC = 0x0803D998, // Known as "SendMonToPC" + .loc_gSpecialVar_0x8000 = 0x0202E8C4, + .loc_gSaveBlock1 = 0x02025734, + .loc_getSetPokedexFlag = 0x08090DB0, + .loc_gSaveDataBuffer = 0x02000000, // Known as "gSharedMem" in RS + .loc_readFlashSector = 0x08125C18, // Known as "DoReadFlashWholeSection" in RS + + // The following should be consistant across languages and revisions. + .offset_ramscript = 0x3690, // Ramscript offset as found within the SaveBlock1 struct in global.h + .offset_flags = 0x1220, // Flag offset as found within the SaveBlock1 struct in global.h + .offset_script = 0x0810, + .text_region = TEXT_HOENN, + + // PKHeX's list of flags is useful for making sure the detection is accurate: https://github.com/kwsch/PKHeX/blob/78a557c3cdaa6f48b42cc96df8ccb4d20b897937/PKHeX.Core/Resources/text/other/flags_rs.txt + .e4_flag = 0x800 + 0x04, // The flag that is set when you become champion. Often listed as "GAME_CLEAR" + .mg_flag = 0x800 + 0x4C, // The flag that is set when you enable Mystery Gift. Known as "EXDATA_ENABLE" in RS + .unused_flag_start = 0x21, // The start of the unused flags and must have 31 open flags in a row + + .map_bank = 20, + .map_id = 2, + .npc_id = 1, + + .def_map_bank = 8, + .def_map_id = 1, + .def_npc_id = 1, + + .test_map_bank = 2, + .test_map_id = 2, + .test_npc_id = 3, +}; +const struct ROM_DATA ENG_RUBY_v2 = { + .is_valid = true, + + .gamecode = RUBY_ID, + .version = VERS_1_2, + .language = LANG_ENG, + + .loc_copyMonToPC = 0x0803D998, // Known as "SendMonToPC" + .loc_gSpecialVar_0x8000 = 0x0202E8C4, + .loc_gSaveBlock1 = 0x02025734, + .loc_getSetPokedexFlag = 0x08090DB0, + .loc_gSaveDataBuffer = 0x02000000, // Known as "gSharedMem" in RS + .loc_readFlashSector = 0x08125C18, // Known as "DoReadFlashWholeSection" in RS + + // The following should be consistant across languages and revisions. + .offset_ramscript = 0x3690, // Ramscript offset as found within the SaveBlock1 struct in global.h + .offset_flags = 0x1220, // Flag offset as found within the SaveBlock1 struct in global.h + .offset_script = 0x0810, + .text_region = TEXT_HOENN, + + // PKHeX's list of flags is useful for making sure the detection is accurate: https://github.com/kwsch/PKHeX/blob/78a557c3cdaa6f48b42cc96df8ccb4d20b897937/PKHeX.Core/Resources/text/other/flags_rs.txt + .e4_flag = 0x800 + 0x04, // The flag that is set when you become champion. Often listed as "GAME_CLEAR" + .mg_flag = 0x800 + 0x4C, // The flag that is set when you enable Mystery Gift. Known as "EXDATA_ENABLE" in RS + .unused_flag_start = 0x21, // The start of the unused flags and must have 31 open flags in a row + + .map_bank = 20, + .map_id = 2, + .npc_id = 1, + + .def_map_bank = 8, + .def_map_id = 1, + .def_npc_id = 1, + + .test_map_bank = 2, + .test_map_id = 2, + .test_npc_id = 3, +}; +const struct ROM_DATA ENG_SAPPHIRE_v2 = { + .is_valid = true, + + .gamecode = RUBY_ID, + .version = VERS_1_2, + .language = LANG_ENG, + + .loc_copyMonToPC = 0x0803D998, // Known as "SendMonToPC" + .loc_gSpecialVar_0x8000 = 0x0202E8C4, + .loc_gSaveBlock1 = 0x02025734, + .loc_getSetPokedexFlag = 0x08090DB0, + .loc_gSaveDataBuffer = 0x02000000, // Known as "gSharedMem" in RS + .loc_readFlashSector = 0x08125C18, // Known as "DoReadFlashWholeSection" in RS + + // The following should be consistant across languages and revisions. + .offset_ramscript = 0x3690, // Ramscript offset as found within the SaveBlock1 struct in global.h + .offset_flags = 0x1220, // Flag offset as found within the SaveBlock1 struct in global.h + .offset_script = 0x0810, + .text_region = TEXT_HOENN, + + // PKHeX's list of flags is useful for making sure the detection is accurate: https://github.com/kwsch/PKHeX/blob/78a557c3cdaa6f48b42cc96df8ccb4d20b897937/PKHeX.Core/Resources/text/other/flags_rs.txt + .e4_flag = 0x800 + 0x04, // The flag that is set when you become champion. Often listed as "GAME_CLEAR" + .mg_flag = 0x800 + 0x4C, // The flag that is set when you enable Mystery Gift. Known as "EXDATA_ENABLE" in RS + .unused_flag_start = 0x21, // The start of the unused flags and must have 31 open flags in a row + + .map_bank = 20, + .map_id = 2, + .npc_id = 1, + + .def_map_bank = 8, + .def_map_id = 1, + .def_npc_id = 1, + + .test_map_bank = 2, + .test_map_id = 2, + .test_npc_id = 3, +}; const struct ROM_DATA ENG_FIRERED_v0 = { .is_valid = true, diff --git a/source/gameboy_colour.cpp b/source/gameboy_colour.cpp index 1205b02..91c41e6 100644 --- a/source/gameboy_colour.cpp +++ b/source/gameboy_colour.cpp @@ -1,4 +1,4 @@ -// Loosely based on code created by StevenChaulk +// Loosely based on code created by StevenChaulk // Source: https://github.com/stevenchaulk/arduino-poke-gen2 #include @@ -20,10 +20,13 @@ #define ack 1 #define menu 2 #define trade 3 -#define preamble 4 +#define party_preamble 4 #define colosseum 5 #define cancel 6 #define trade_data 7 +#define box_preamble 8 +#define box_data 9 +#define end 10 const int MODE = 1; // mode=0 will transfer pokemon data from pokemon.h // mode=1 will copy pokemon party data being received @@ -35,7 +38,6 @@ uint8_t out_data; uint frame; connection_state_t connection_state; -trade_centre_state_gen_II_t trade_centre_state_gen_II; int counter; int data_counter = 0; @@ -47,6 +49,7 @@ int FF_count; int zero_count; int state; +int mosi_delay = 3; // inital delay, speeds up once sending PKMN std::string out_array[10]; @@ -83,7 +86,6 @@ void setup() frame = 0; connection_state = NOT_CONNECTED; - trade_centre_state_gen_II = INIT; counter = 0; gen = 0; @@ -101,7 +103,7 @@ void setup() } } -byte handleIncomingByte(byte in) +byte handleIncomingByte(byte in, byte *box_data_storage) { if (state == hs) { @@ -138,12 +140,13 @@ byte handleIncomingByte(byte in) { if (in == 0xfd) { - state = preamble; + state = party_preamble; + mosi_delay = 0; } return in; } - else if (state == preamble) + else if (state == party_preamble) { if (in != 0xfd) { @@ -155,28 +158,55 @@ byte handleIncomingByte(byte in) else if (state == trade_data) { + if (data_counter >= PAYLOAD_SIZE && in == 0xFD) + { + state = box_preamble; + } return exchange_parties(in); } + else if (state == box_preamble) + { + if (in != 0xFD) + { + state = box_data; + data_counter = 0; + mosi_delay = 1; + return exchange_boxes(in, box_data_storage); + } + return in; + } + + else if (state == box_data) + { + if (data_counter >= BOX_DATA_ARRAY_SIZE) + { + state = end; + } + return exchange_boxes(in, box_data_storage); + } + return in; } -int loop(byte *party_data) +int loop(byte *box_data_storage) { int counter = 0; while (true) { + // TODO: Restore Errors in_data = linkSPI->transfer(out_data); - print( - std::to_string(counter) + ": [" + - std::to_string(data_counter) + "][" + - std::to_string(state) + "][" + - std::to_string(in_data) + "][" + - std::to_string(out_data) + "]\n"); - - out_data = handleIncomingByte(in_data); - party_data[counter] = in_data; + if (DEBUG_MODE) + { + print( + std::to_string(counter) + ": [" + + std::to_string(data_counter) + "][" + + std::to_string(state) + "][" + + std::to_string(in_data) + "][" + + std::to_string(out_data) + "]\n"); + } + out_data = handleIncomingByte(in_data, box_data_storage); if (FF_count > 25) { @@ -191,18 +221,25 @@ int loop(byte *party_data) return COND_ERROR_COLOSSEUM; } - if (trade_centre_state_gen_II == MIMIC) + if (state == end) { return 0; } + + if (DEBUG_MODE && key_hit(KEY_SELECT)){ + return COND_ERROR_DISCONNECT; + } + counter++; - for (int i = 0; i < 3; i++) + for (int i = 0; i < mosi_delay; i++) { + key_poll(); VBlankIntrWait(); } - if (counter > (60*10)){ - return COND_ERROR_TIMEOUT_ONE; + if (counter > (60 * 10)) + { + // return COND_ERROR_TIMEOUT_ONE; } } }; @@ -211,6 +248,12 @@ byte exchange_parties(byte curr_in) { int ret = gen1_eng_payload[data_counter]; data_counter += 1; - // return curr_in; return ret; }; + +byte exchange_boxes(byte curr_in, byte *box_data_storage) +{ + box_data_storage[data_counter] = curr_in; + data_counter += 1; + return curr_in; +}; diff --git a/source/main.cpp b/source/main.cpp index 9c1502c..2c83653 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -195,7 +195,7 @@ void first_load_message(void) { tte_set_pos(8, 0); tte_set_ink(10); - tte_write("#{cx:0xE000}Hello! Thank you for using\nPok@mon Mirror!\n\nJust as a word of caution- \nPok@mon Mirror WILL modify\nyour generation 3 save file.\nThe program is designed to\nnot corrupt anything, but if\nyou do not wish to modify\nyour save file, please turn\noff your Game Boy Advance.\n\nPlease note that Pok@mon\nMirror is still in beta, so\nsave file backups are HIGHLY\nrecommended before using.\nWith that all out of the\nway, please enjoy!\n\n -The Gears of Progress"); + tte_write("#{cx:0xE000}Hello! Thank you for using\nPok@ Transporter GB!\n\nJust as a word of caution- \nPok@ Transporter GB WILL modify\nyour generation 3 save file.\nThe program is designed to\nnot corrupt anything, but if\nyou do not wish to modify\nyour save file, please turn\noff your Game Boy Advance.\n\nPlease note that Pok@mon\nMirror is still in beta, so\nsave file backups are HIGHLY\nrecommended before using.\nWith that all out of the\nway, please enjoy!\n\n -The Gears of Progress"); key_poll(); while (!key_hit(KEY_A)) { @@ -229,7 +229,7 @@ int main(void) // Legal mumbo jumbo tte_set_pos(8, 0); - tte_write("#{cx:0xE000}\n\nPokemon Mirror was created\nout of love and appreciation\nfor the Pokemon franchise\nwith no profit in mind.\nIt will ALWAYS be free.\n\nPlease support the original developers-\nNintendo and GAME FREAK.\n\nAll Pokemon names, sprites, and music are owned by \nNintendo, Creatures Inc, and\nGAME FREAK Inc."); + tte_write("#{cx:0xE000}\n\nPok@ Transporter GB was made\nout of love and appreciation\nfor the Pokemon franchise\nwith no profit in mind.\nIt will ALWAYS be free.\n\nPlease support the original developers-\nNintendo and GAME FREAK.\n\nAll Pokemon names, sprites, and music are owned by \nNintendo, Creatures Inc, and\nGAME FREAK Inc."); tte_write("#{cx:0xF000}"); // Set the color to grey while (delay_counter < (15 * 60)) { diff --git a/source/mystery_gift_builder.cpp b/source/mystery_gift_builder.cpp index d02859c..040ec2f 100644 --- a/source/mystery_gift_builder.cpp +++ b/source/mystery_gift_builder.cpp @@ -160,44 +160,42 @@ void mystery_gift_script::build_script(Pokemon_Party &incoming_box_data) jumpLoop.set_start(); // Set the jump destination for the JUMP_LOOP call(ptr_call_check_flag); // Call the check flag ASM virtualgotoif(COND_FLAGFALSE, jumpPkmnCollected.add_reference(2)); // If the "pokemon collected" flag is false, jump to the end of the loop - call(ptr_callASM); // Call readFlash ASM - addvar(var_script_ptr_low, mainAsmStart.add_reference(3, &readFlashStart)); - - call(ptr_callASM); // Call SendMonToPC ASM - compare(var_box_return, 2); // Compare the resulting return to #2 - virtualgotoif(COND_EQUALS, jumpBoxFull.add_reference(2)); // If the return value was #2, jump to the box full message - addvar(var_script_ptr_low, dexAsmStart.add_reference(3, &mainAsmStart)); // add to the CallASM offset so that it points to PTR_DEX_START instead - setvar(var_dex_seen_caught, 2); // set the seen caught variable to 2, so that the Pokemon is set to "seen" - call(ptr_callASM); // call "PTR_DEX_START" - addvar(var_dex_seen_caught, 1); // add 1 to the seen caught variable so that the Pokemon will be "Caught" - call(ptr_callASM); // Call "PTR_DEX_START" again - subvar(var_script_ptr_low, dexAsmStart.add_reference(3, &mainAsmStart)); // subtract from the CallASM offset so that it points to CALL_ASM again - subvar(var_script_ptr_low, mainAsmStart.add_reference(3, &readFlashStart)); - jumpPkmnCollected.set_start(); // Set the jump destination for if the Pokemon has already been collected - addvar(var_pkmn_offset, POKEMON_SIZE); // Add the size of one Pokmeon to the Pokemon offset - addvar(var_index, 1); // Add one to the index - addvar(var_call_check_flag, rev_endian(1)); // Add one to the flag index - compare(var_index, MAX_PKMN_IN_BOX); // Compare the index to 30 - virtualgotoif(COND_LESSTHAN, jumpLoop.add_reference(2)); // if index is less than six, jump to the start of the loop - setflag(curr_rom.all_collected_flag); // Set the "all collected" flag - fanfare(0xA4); // Play the received fanfare - virtualmsgbox(textReceived.add_reference(1)); // Display the recieved text - waitfanfare(); // Wait for the fanfare - waitmsg(); // Wait for the text to finish - waitkeypress(); // Wait for the player to press A/B - jumpAllCollected.set_start(); // Set the destination for if all the Pokemon have already been collected - virtualmsgbox(textThank.add_reference(1)); // Display the thank test - waitmsg(); // Wait for the message - waitkeypress(); // Wait for the player to press A/B - release(); // Release the player - killscript(); // Erase RAMscript - jumpBoxFull.set_start(); // Set the destination for if the box is full - virtualmsgbox(textPCFull.add_reference(1)); // Display the full box message - waitmsg(); // Wait for the message - waitkeypress(); // Wait for the player to presse A/B - release(); // Release the player - end(); // End the script + addvar(var_script_ptr_low, mainAsmStart.add_reference(3, &readFlashStart)); // add to the CallASM offset so that it points to MAIN_ASM_START instead + call(ptr_callASM); // Call SendMonToPC ASM + compare(var_box_return, 2); // Compare the resulting return to #2 + virtualgotoif(COND_EQUALS, jumpBoxFull.add_reference(2)); // If the return value was #2, jump to the box full message + addvar(var_script_ptr_low, dexAsmStart.add_reference(3, &mainAsmStart)); // add to the CallASM offset so that it points to PTR_DEX_START instead + setvar(var_dex_seen_caught, 2); // set the seen caught variable to 2, so that the Pokemon is set to "seen" + call(ptr_callASM); // call "PTR_DEX_START" + addvar(var_dex_seen_caught, 1); // add 1 to the seen caught variable so that the Pokemon will be "Caught" + call(ptr_callASM); // Call "PTR_DEX_START" again + subvar(var_script_ptr_low, dexAsmStart.add_reference(3, &mainAsmStart)); // subtract from the CallASM offset so that it points to CALL_ASM again + subvar(var_script_ptr_low, mainAsmStart.add_reference(3, &readFlashStart)); // subtract from the CallASM offset so that it points to READ_FLASH + jumpPkmnCollected.set_start(); // Set the jump destination for if the Pokemon has already been collected + addvar(var_pkmn_offset, POKEMON_SIZE); // Add the size of one Pokmeon to the Pokemon offset + addvar(var_index, 1); // Add one to the index + addvar(var_call_check_flag, rev_endian(1)); // Add one to the flag index + compare(var_index, MAX_PKMN_IN_BOX); // Compare the index to 30 + virtualgotoif(COND_LESSTHAN, jumpLoop.add_reference(2)); // if index is less than six, jump to the start of the loop + setflag(curr_rom.all_collected_flag); // Set the "all collected" flag + fanfare(0xA4); // Play the received fanfare + virtualmsgbox(textReceived.add_reference(1)); // Display the recieved text + waitfanfare(); // Wait for the fanfare + waitmsg(); // Wait for the text to finish + waitkeypress(); // Wait for the player to press A/B + jumpAllCollected.set_start(); // Set the destination for if all the Pokemon have already been collected + virtualmsgbox(textThank.add_reference(1)); // Display the thank test + waitmsg(); // Wait for the message + waitkeypress(); // Wait for the player to press A/B + release(); // Release the player + killscript(); // Erase RAMscript + jumpBoxFull.set_start(); // Set the destination for if the box is full + virtualmsgbox(textPCFull.add_reference(1)); // Display the full box message + waitmsg(); // Wait for the message + waitkeypress(); // Wait for the player to presse A/B + release(); // Release the player + end(); // End the script textGreet.insert_text(mg_script); textThank.insert_text(mg_script); @@ -207,23 +205,23 @@ void mystery_gift_script::build_script(Pokemon_Party &incoming_box_data) four_align(); // Align the code so that it is byte aligned readFlashStart.set_start(); - push(rlist_lr); // save the load register to the stack - mov1(r0, 30); // set r0 to 30 (the sector ID for eReader data) - ldr3(r1, flashBuffer_ptr.add_reference()); - ldr3(r2, readFlashSector_ptr.add_reference()); // set r2 to the location of "readFlashSector" plus one, since it is thumb code - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, plus to tell the system to read as thumb code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (readFlashSector) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); - // - mainAsmStart.set_start(); // Set the memory pointer location for ASM start - push(rlist_lr); // save the load register to the stack - ldr3(r3, curr_pkmn_index_ptr.add_reference()); // set r3 to the pointer to the pokemon index variable - ldr1(r3, r3, 0); // set r3 to the value in memory r3 points to - add5(r0, pkmnStruct.add_reference()); // set r0 to a pointer to the start of the Pokemon struct. - ldr1(r0, r0, 0); + push(rlist_lr); // save the load register to the stack + mov1(r0, 30); // set r0 to 30 (the sector ID for eReader data) + ldr3(r1, flashBuffer_ptr.add_reference()); // set r1 to the location of "flashBuffer" plus one, since it is thumb code + ldr3(r2, readFlashSector_ptr.add_reference()); // set r2 to the location of "readFlashSector" plus one, since it is thumb code + mov3(r3, r15); // move r15 (the program counter) to r3 + add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, plus to tell the system to read as thumb code + mov3(r14, r3); // move r3 into r14 (the load register) + bx(r2); // jump to the pointer stored in r2 (readFlashSector) + pop(rlist_r0); // remove r0 from the stack and put it into r0 + bx(r0); // go to r0 + // + mainAsmStart.set_start(); // Set the memory pointer location for ASM start + push(rlist_lr); // save the load register to the stack + ldr3(r3, curr_pkmn_index_ptr.add_reference()); // set r3 to the pointer to the pokemon index variable + ldr1(r3, r3, 0); // set r3 to the value in memory r3 points to + add5(r0, pkmnStruct.add_reference()); // set r0 to a pointer to the start of the Pokemon struct. + ldr1(r0, r0, 0); // set r0 to the value in memory r0 points to add3(r0, r0, r3); // add r3 to r0, giving it the correct offset for the current index ldr3(r1, sendMonToPC_ptr.add_reference()); // set r1 to the location of "SendMonToPC" plus one, since it is thumb code mov3(r2, r15); // move r15 (the program counter) to r2 @@ -241,38 +239,37 @@ void mystery_gift_script::build_script(Pokemon_Party &incoming_box_data) ldr1(r0, r0, 0); // load the value at r0's pointer mov1(r3, 0xFF); // load 0xFF into r3 and1(r0, r3); // AND r0 and r3, which will give us just the least significant byte - - add5(r1, dexStruct.add_reference()); // set r1 to the value stored X bytes ahead - ldr1(r1, r1, 0); - add3(r0, r0, r1); // add r0 and r1, which is the current index and dex_struct respectivly - ldr1(r0, r0, 0); // load the value at the memory location stored in r0 - and1(r0, r3); // truncate to just the least significant byte, which is the current dex number - ldr3(r1, dexSeenCaught_ptr.add_reference()); // load the dex_seen_caught variable's pointer into r1 - ldr1(r1, r1, 0); // load the value of memory pointed at by r1 - and1(r1, r3); // AND r1 and r3, which will keep only the least significant byte - ldr3(r2, setPokedexFlag_ptr.add_reference()); // load the GetSetPokedexFlag function location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (GetSetPokedexFlag) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - - // - // - add_padding(); // add padding so that we are byte aligned again - add_word(sendMonToPC_ptr.place_word()); // the location of "SendMonToPC", plus one (so it is interpreted as thumb code) - add_word(returned_box_success_ptr.place_word()); // the location of variable "0x8006" (the return value) - add_word(curr_pkmn_index_ptr.place_word()); // the location of variable "0x8008" (the pokemon offset) - add_word(setPokedexFlag_ptr.place_word()); // the location of GetSetPokedexFlag, plus one (so it is interpreted as thumb code) - add_word(dexSeenCaught_ptr.place_word()); // the location of the DEX_SEEN_CAUGHT variable - add_word(currPkmnIndex_ptr.place_word()); // the location of the INDEX variable - add_word(flashBuffer_ptr.place_word()); - add_word(readFlashSector_ptr.place_word()); - add_word(pkmnStruct.place_word()); - add_word(dexStruct.place_word()); - - four_align(); // make the offset a multiple of 4 + // + add5(r1, dexStruct.add_reference()); // set r1 to the value stored X bytes ahead + ldr1(r1, r1, 0); // loda the value at the memory location stored in r1 + add3(r0, r0, r1); // add r0 and r1, which is the current index and dex_struct respectivly + ldr1(r0, r0, 0); // load the value at the memory location stored in r0 + and1(r0, r3); // truncate to just the least significant byte, which is the current dex number + ldr3(r1, dexSeenCaught_ptr.add_reference()); // load the dex_seen_caught variable's pointer into r1 + ldr1(r1, r1, 0); // load the value of memory pointed at by r1 + and1(r1, r3); // AND r1 and r3, which will keep only the least significant byte + ldr3(r2, setPokedexFlag_ptr.add_reference()); // load the GetSetPokedexFlag function location into r2 + mov3(r3, r15); // move r15 (the program counter) to r3 + add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code + mov3(r14, r3); // move r3 into r14 (the load register) + bx(r2); // jump to the pointer stored in r2 (GetSetPokedexFlag) + pop(rlist_r0); // remove r0 from the stack and put it into r0 + bx(r0); // jump to r0 (return to where the function was called) + // + // + add_padding(); // add padding so that we are byte aligned again + add_word(sendMonToPC_ptr.place_word()); // the location of "SendMonToPC", plus one (so it is interpreted as thumb code) + add_word(returned_box_success_ptr.place_word()); // the location of variable "0x8006" (the return value) + add_word(curr_pkmn_index_ptr.place_word()); // the location of variable "0x8008" (the pokemon offset) + add_word(setPokedexFlag_ptr.place_word()); // the location of GetSetPokedexFlag, plus one (so it is interpreted as thumb code) + add_word(dexSeenCaught_ptr.place_word()); // the location of the DEX_SEEN_CAUGHT variable + add_word(currPkmnIndex_ptr.place_word()); // the location of the INDEX variable + add_word(flashBuffer_ptr.place_word()); // the location of the FLASH_BUFFER variable + add_word(readFlashSector_ptr.place_word()); // the location of "readFlashSector", plus one (so it is interpreted as thumb code) + add_word(pkmnStruct.place_word()); // the location of the Pokemon Struct + add_word(dexStruct.place_word()); // the location of the dex struct + // + four_align(); // make the offset a multiple of 4 for (unsigned int i = 0; i < asm_variable_list.size(); i++) // Fill all the refrences for script variables { diff --git a/source/payload.cpp b/source/payload.cpp index 24134b7..399d987 100644 --- a/source/payload.cpp +++ b/source/payload.cpp @@ -2,7 +2,7 @@ #include "payload.h" -byte gen1_eng_payload[637] = { +byte gen1_eng_payload[PAYLOAD_SIZE] = { // RNG Seed 0, 0, 0, 0, 0, 0xCD, 0x87, 0xD8, 184, 165, @@ -10,12 +10,12 @@ byte gen1_eng_payload[637] = { 253, 253, 253, 253, 253, 253, 253, 253, // Party (bootstrap) - // Rival name + //// Rival name 248, 0, 54, 253, 1, 62, 88, 197, 195, 214, 197, - // # of Pokemon + // num of Pokemon 6, // Pokemon list - 21, 21, 21, 21, 21, 21, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 252, 227, 227, 255, + 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 252, 0xE3, 0xE3, 255, // Code 33, 160, 195, 1, 136, 1, 62, 0, 205, 224, 54, 17, 24, 218, 33, 89, 196, 205, 85, 25, 195, 21, 218, 139, 142, 128, 131, 136, 141, 134, 232, 232, 232, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 64, 0, 0, @@ -24,8 +24,73 @@ byte gen1_eng_payload[637] = { // Patchlist (code storage) // Test string: 62, 99, 245, 33, 160, 195, 1, 136, 1, 205, 224, 54, 17, 255, 197, 33, 87, 196, 205, 85, 25, 118, 118, 118, 118, 118, 118, 118, 241, 60, 14, 108, 185, 194, 216, 197, 62, 99, 195, 216, 197, 127, 0x8E, 0x8C, 0x86, 127, 0x92, 0x8E, 0x91, 0x80, 0xE6, 0xE7, 0xE6, 0xE7, 127, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 // The last two bites are not used + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + + + + + + // call ClearScreen + 0xCD, 0x0F, 0x19, + // hlcoord 2, 7 + 0x21, 0x2E, 0xC4, + // ld b, 3 [height] + 0x06, 0x03, + // ld c, 14 [width] + 0x0E, 0x0E, + // call CableClub_TextBoxBoarder + 0xCD, 0xB3, 0x5A, + // hlcoord 3, 8 + 0x21, 0x43, 0xC4, + // ld de, TransferWaitString + 0x11, 0x7A, 0xC6, + // call PlaceString + 0xCD, 0x55, 0x19, + + // ld hl, hSerialConnectionStatus + 0x21, 0xAA , 0xFF, + // ld [hl], 0x01 [Make sure GB is the slave] + 0x36, 0x01, + // ld hl, (wBoxDataStart - 1) [data to send] + 0x21, 0x7F, 0xDA, + // ld [hl], 0xFD [set the start of the data to 0xFD so Serial_ExchangeBytes is happy] + 0x36, 0xFD, + // ld de, (wBoxDataStart - 3) [location to put stored data] + 0x11, 0x7D, 0xDA, + // ld bc, (wBoxDataEnd - wBoxDataStart) + 2 + 0x01, 0x64, 0x04, + // call Serial_ExchangeBytes + 0xCD, 0x6F, 0x21, + + // ld hl, SaveSAVtoSRAM1 + 0x21, 0xE2, 0x77, + // ld b, 0x1C [memory bank of SaveSAVtoSRAM1] + 0x06, 0x1C, + // call Bankswitch + 0xCD, 0xD6, 0x35, + // jp SoftReset + 0xC3, 0x49, 0x1F, + + // TransferWaitString 0xC67A + // TRANSFERRING..\n + // PLEASE WAIT! + + 0x93, 0x91, 0x80, 0x8D, 0x92, 0x85, 0x84, 0x91, 0x91, 0x88, 0x8D, 0x86, 0xF2, 0xF2, 0x4E, + 0x7F, 0x8F, 0x8B, 0x84, 0x80, 0x92, 0x84, 0x7F, 0x96, 0x80, 0x88, 0x93, 0xE7, 0x7F, 0x50, + + //0x00, 0x00 // The last two bites are not used // This payload works by placing Pokemon ID 0xFC's name in the stack, and causing a return to CD8E, // which is part of the RNG seed. From there we can jump anywhere- and we choose to jump to D887, diff --git a/source/rom_data.cpp b/source/rom_data.cpp index 1a257d8..1e87716 100644 --- a/source/rom_data.cpp +++ b/source/rom_data.cpp @@ -64,10 +64,10 @@ void rom_data::fill_values(const ROM_DATA *rom_values) offset_script = rom_values->offset_script; text_region = rom_values->text_region; - e4_flag = rom_values->e4_flag; // The flag that is set when you become champion. Often listed as "GAME_CLEAR" - mg_flag = rom_values->mg_flag; // The flag that is set when you enable Mystery Gift. Known as "EXDATA_ENABLE" in RS - unused_flag_start = rom_values->unused_flag_start; // The start of the unused flags and must have 31 open flags in a row - all_collected_flag = rom_values->unused_flag_start; // The flag for if everything has been collected + e4_flag = rom_values->e4_flag; // The flag that is set when you become champion. Often listed as "GAME_CLEAR" + mg_flag = rom_values->mg_flag; // The flag that is set when you enable Mystery Gift. Known as "EXDATA_ENABLE" in RS + unused_flag_start = rom_values->unused_flag_start; // The start of the unused flags and must have 31 open flags in a row + all_collected_flag = rom_values->unused_flag_start; // The flag for if everything has been collected pkmn_collected_flag_start = rom_values->unused_flag_start + 1; // The beginning of the flags for each of the Pokemon map_bank = (DEBUG_MODE ? rom_values->test_map_bank : rom_values->map_bank); diff --git a/source/script_array.cpp b/source/script_array.cpp index 0440365..23df67e 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -119,7 +119,7 @@ bool run_conditional(int index) return read_flag(curr_rom.mg_flag) || IGNORE_MG_E4_FLAGS; case COND_TUTORIAL_COMPLETE: - return get_tutorial_flag(); + return get_tutorial_flag() || IGNORE_MG_E4_FLAGS; case COND_NEW_POKEMON: return party_data.get_has_new_pkmn();