Adding data packets to GSC

This commit is contained in:
The Gears of Progress 2024-10-31 10:59:36 -04:00
parent cd2a9971a5
commit 884ebc9216
8 changed files with 118 additions and 33 deletions

View File

@ -9,11 +9,11 @@
#define IGNORE_MG_E4_FLAGS true
#define IGNORE_UNRECEIVED_PKMN true
#define FORCE_TUTORIAL false
#define DONT_REMOVE_PKMN true
#define SHOW_INVALID_PKMN false
#define DONT_REMOVE_PKMN false
#define NO_INVALID_PKMN false
#define IGNORE_DEX_COMPLETION false
#define WRITE_CABLE_DATA_TO_SAVE true
#define SHOW_DATA_PACKETS false
#define WRITE_CABLE_DATA_TO_SAVE false
#define SHOW_DATA_PACKETS true
#define DEBUG_GAME EMERALD_ID
#define DEBUG_VERS VERS_1_0

View File

@ -50,11 +50,12 @@ public:
word wSerialOtherGameboyRandomNumberListBlock; // location of wSerialOtherGameboyRandomNumberListBlock in RAM
word wSerialEnemyDataBlock; // location of wSerialEnemyDataBlock in RAM
word wSerialEnemyMonsPatchList; // location of wSerialEnemyMonsPatchList in RAM
hword transferStringLocation; // location in VRAM to start writing the transfer string to
hword textBorderUppLeft; // location in VRAM to put the upper left corner of the border
byte textBorderWidth; // the width of the text box border
byte textBorderHeight; // the height of the text box border
word wEnemyMonSpecies; // location of wEnemyMonSpecies in RAM
hword transferStringLocation; // location in VRAM to start writing the transfer string to
hword textBorderUppLeft; // location in VRAM to put the upper left corner of the border
byte textBorderWidth; // the width of the text box border
byte textBorderHeight; // the height of the text box border
};
#endif

View File

@ -57,6 +57,7 @@ const struct GB_ROM ENG_RED = {
.wSerialOtherGameboyRandomNumberListBlock = 0xCD81,
.wSerialEnemyDataBlock = 0xD893,
.wSerialEnemyMonsPatchList = 0xC5D0,
.wEnemyMonSpecies = 0xCFE5,
.transferStringLocation = 0xC444,
.textBorderUppLeft = 0xC42F,
@ -96,6 +97,7 @@ const struct GB_ROM ENG_BLUE = {
.wSerialOtherGameboyRandomNumberListBlock = 0xCD81,
.wSerialEnemyDataBlock = 0xD893,
.wSerialEnemyMonsPatchList = 0xC5D0,
.wEnemyMonSpecies = 0xCFE5,
.transferStringLocation = 0xC444,
.textBorderUppLeft = 0xC42F,
@ -136,6 +138,7 @@ const struct GB_ROM ENG_YELLOW = {
.wSerialOtherGameboyRandomNumberListBlock = 0xCD81,
.wSerialEnemyDataBlock = 0xD893,
.wSerialEnemyMonsPatchList = 0xC5D0,
.wEnemyMonSpecies = 0xCFE4,
.transferStringLocation = 0xC444,
.textBorderUppLeft = 0xC42F,
@ -173,6 +176,7 @@ const struct GB_ROM ENG_GOLD = {
.wSerialOtherGameboyRandomNumberListBlock = 0xD0EF, // wOTLinkBattleRNData
.wSerialEnemyDataBlock = 0xDD40, // wOTPartyData
.wSerialEnemyMonsPatchList = 0xC5D0, // wOTPatchLists
.wEnemyMonSpecies = 0x01D0EF,
.transferStringLocation = 0xC444,
.textBorderUppLeft = 0xC42F,
@ -210,6 +214,7 @@ const struct GB_ROM ENG_SILVER = {
.wSerialOtherGameboyRandomNumberListBlock = 0xD0EF, // wOTLinkBattleRNData
.wSerialEnemyDataBlock = 0xDD40, // wOTPartyData
.wSerialEnemyMonsPatchList = 0xC5D0, // wOTPatchLists
.wEnemyMonSpecies = 0x01D0EF,
.transferStringLocation = 0xC444,
.textBorderUppLeft = 0xC42F,
@ -247,6 +252,7 @@ const struct GB_ROM ENG_CRYSTAL = {
.wSerialOtherGameboyRandomNumberListBlock = 0xD206, // wOTLinkBattleRNData
.wSerialEnemyDataBlock = 0xD26B, // wOTPartyData
.wSerialEnemyMonsPatchList = 0xC6D0, // wOTPatchLists
.wEnemyMonSpecies = 0x01D206,
.transferStringLocation = 0xC544,
.textBorderUppLeft = 0xC52F,

View File

@ -68,6 +68,8 @@ bool init_packet;
bool test_packet_fail = false;
bool end_of_data;
byte data_packet[13];
std::string spi_text_out_array[10];
@ -119,6 +121,7 @@ void setup()
failed_packet = false;
init_packet = true;
end_of_data = false;
if (DEBUG_MODE && false)
{
@ -421,7 +424,7 @@ byte exchange_boxes(byte curr_in, byte *box_data_storage, GB_ROM *curr_gb_rom)
}
if (!init_packet)
{
received_offset = (data_packet[12] | (data_packet[11] << 8)) - (curr_gb_rom->wBoxDataStart + 8);
received_offset = (data_packet[12] | (data_packet[11] << 8)) - ((curr_gb_rom->wBoxDataStart & 0xFFFF) + 8);
}
if (SHOW_DATA_PACKETS)
{
@ -455,7 +458,21 @@ byte exchange_boxes(byte curr_in, byte *box_data_storage, GB_ROM *curr_gb_rom)
test_packet_fail = false;
}
}
state = (received_offset > curr_gb_rom->box_data_size + 8 ? end1 : box_preamble);
if (end_of_data)
{
state = end1;
}
else
{
state = box_preamble;
}
if (received_offset > curr_gb_rom->box_data_size + 8)
{
end_of_data = true;
}
if (SHOW_DATA_PACKETS)
{
tte_write("\nNO: ");
@ -497,7 +514,7 @@ byte exchange_boxes(byte curr_in, byte *box_data_storage, GB_ROM *curr_gb_rom)
switch (packet_index)
{
case 3:
if (received_offset > 0x462)
if (end_of_data)
{
return 0xFF;
}

View File

@ -116,17 +116,20 @@ bool inject_mystery(Pokemon_Party &incoming_box_data)
update_memory_buffer_checksum(false);
erase_sector(0x1E000);
copy_ram_to_save(&global_memory_buffer[0], 0x1E000, 0x1000);
if (WRITE_CABLE_DATA_TO_SAVE)
{
for (int i = 0; i < 1122; i++)
{
global_memory_buffer[i] = incoming_box_data.box_data_array[i];
}
for (int i = 0; i < 0x1000 - 1122; i++){
for (int i = 0; i < 0x1000 - 1122; i++)
{
global_memory_buffer[i + 1122] = 0xAA;
}
copy_ram_to_save(&global_memory_buffer[0], 0x0000, 0x1000);
}
copy_ram_to_save(&global_memory_buffer[0], 0x0000, 0x1000);
// Set flags
int memory_section = 1 + ((curr_rom.offset_flags + (curr_rom.unused_flag_start / 8)) / 0xF80); // This sets the correct memory section, since flags stretch between section 1 and 2.

View File

@ -8,7 +8,7 @@
#include <fstream>
#include <iomanip>
#define DATA_LOC 0xCFD8 // 0xC454
#define DATA_LOC (SHOW_DATA_PACKETS ? curr_rom.transferStringLocation : curr_rom.wEnemyMonSpecies)
#define PACKET_SIZE (1 + 8 + 1 + 1 + 2) // 0xFD, 8 data bytes, the checksum, the flag bytes, and two location bytes
byte out_array[PAYLOAD_SIZE] = {};
@ -608,6 +608,9 @@ byte *generate_payload(GB_ROM curr_rom, int type, bool debug)
z80_jump remove_array_loop(&jump_vector);
z80_jump jump_to_party(&jump_vector);
z80_jump jump_to_payload(&jump_vector);
z80_jump packet_loop(&jump_vector);
z80_jump fe_bypass(&jump_vector);
z80_jump send_packet_loop(&jump_vector);
z80_variable array_counter(&var_vector, 1, 0x00); // 1 byte to store the current array counter
z80_variable removal_array(&var_vector); // 40 byte storage for list of Pokemon to remove, plus a permanent array terminator
@ -624,10 +627,8 @@ byte *generate_payload(GB_ROM curr_rom, int type, bool debug)
}
}
removal_array.load_data(41, removal_array_data);
z80_variable transfer_wait_string(&var_vector, 30, // 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);
z80_variable transfer_wait_string(&var_vector, 13, // SENDING DATA
0x92, 0x84, 0x8D, 0x83, 0x88, 0x8D, 0x86, 0x7F, 0x83, 0x80, 0x93, 0x80, 0x50);
z80_variable custom_name(&var_vector, 11, // FENNEL
0x85, 0x84, 0x8D, 0x8D, 0x84, 0x8B, 0x50, 0x50, 0x50, 0x50, 0x50);
@ -703,28 +704,84 @@ byte *generate_payload(GB_ROM curr_rom, int type, bool debug)
// call PlaceString
z80_patchlist.CALL(curr_rom.placeString | T_U16);
// Transfer box data:
z80_patchlist.LD(HL, curr_rom.hSerialConnectionStatus | T_U16); // Can be shortened since it is 0xFFxx
z80_patchlist.LD(HL_PTR, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug
// call OpenSRAM
z80_patchlist.LD(A, 0x01 | T_U8);
z80_patchlist.CALL(curr_rom.OpenSRAM | T_U16);
z80_patchlist.LD(HL, (curr_rom.wBoxDataStart - 1) | T_U16);
z80_patchlist.LD(HL_PTR, 0xFD | T_U8); // set the start of the data to 0xFD so Serial_ExchangeBytes is happy
z80_patchlist.LD(DE, (curr_rom.wBoxDataStart - (debug ? 2 : 3)) | T_U16); // location to put stored data
z80_patchlist.LD(BC, ((curr_rom.wBoxDataEnd - curr_rom.wBoxDataStart) + 2) | T_U16);
/* Build the packet */
// HL is the current data pointer
// DE is the destination pointer
// A is the checksum
// B is the 0xFE flag byte
// C is the counter
send_packet_loop.set_start(&z80_patchlist);
// Theoretically this could be changed to just take the direct address instead of adding the offset to it, if space is needed
z80_patchlist.LD(HL, (DATA_LOC + PACKET_SIZE + 3) | T_U16);
z80_patchlist.LD(E, HL_PTR);
z80_patchlist.INC(HL);
z80_patchlist.LD(D, HL_PTR);
z80_patchlist.LD(HL, curr_rom.wBoxDataStart | T_U16);
z80_patchlist.ADD(HL, DE);
z80_patchlist.LD(DE, (DATA_LOC + 1) | T_U16); // Enemy Pokemon data, should be unused
z80_patchlist.XOR(A, A); // Clear the register
z80_patchlist.LD(B, A); // Clear B as well
z80_patchlist.LD(C, A); // Clear C as well
z80_patchlist.PUSH(AF);
packet_loop.set_start(&z80_patchlist);
z80_patchlist.SLA(B); // Shift flag over
z80_patchlist.POP(AF);
z80_patchlist.ADD(A, HL_PTR); // Add the current data to the checksum
z80_patchlist.PUSH(AF);
z80_patchlist.LD(A, 0xFE);
z80_patchlist.CP(A, HL_PTR); // Compare the current data to 0xFE
z80_patchlist.LD(A, HLI_PTR); // Load HL's data into A for modification (if need be)
// If HL's data is 0xFE
z80_patchlist.JR(NZ_F, fe_bypass.place_relative_jump(&z80_patchlist) | T_I8);
z80_patchlist.DEC(A);
z80_patchlist.INC(B); // Set flag
fe_bypass.set_start(&z80_patchlist);
z80_patchlist.LD(DE_PTR, A);
z80_patchlist.INC(DE);
z80_patchlist.INC(C);
z80_patchlist.LD(A, 0x07);
z80_patchlist.CP(A, C);
z80_patchlist.JR(NC_F, packet_loop.place_relative_jump(&z80_patchlist) | T_I8);
z80_patchlist.POP(AF);
z80_patchlist.LD(DE_PTR, A);
z80_patchlist.INC(DE);
z80_patchlist.LD(A, B);
z80_patchlist.LD(DE_PTR, A);
z80_patchlist.INC(DE);
z80_patchlist.LD(A, H);
z80_patchlist.LD(DE_PTR, A);
z80_patchlist.INC(DE);
z80_patchlist.LD(A, L);
z80_patchlist.LD(DE_PTR, A);
/* Transfer box data packet: */
z80_patchlist.LD(HL, curr_rom.hSerialConnectionStatus | T_U16); // Can be shortened since it is 0xFFxx
z80_patchlist.LD(HL_PTR, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug
z80_patchlist.LD(HL, DATA_LOC | T_U16);
z80_patchlist.LD(HL_PTR, 0xFD | T_U8); // set the start of the data to 0xFD so Serial_ExchangeBytes is happy
z80_patchlist.LD(DE, (DATA_LOC + PACKET_SIZE) | T_U16); // location to put stored data
z80_patchlist.LD(BC, PACKET_SIZE | T_U16);
if (debug) // Don't call serialExchangeBytes if debug is enabled
{
z80_patchlist.index += 3;
}
else
{
// call Serial_ExchangeBytes [Send the box data]
z80_patchlist.CALL(curr_rom.Serial_ExchangeBytes | T_U16);
}
z80_patchlist.LD(A, (DATA_LOC + PACKET_SIZE + 3 + 1) | T_U16);
z80_patchlist.CP(A, 0xFF);
z80_patchlist.JR(NZ_F, send_packet_loop.place_relative_jump(&z80_patchlist) | T_I8);
// Recieve the Pokemon to remove
z80_patchlist.LD(HL, curr_rom.hSerialConnectionStatus | T_U16); // This can also be shortened
z80_patchlist.LD(HL_PTR, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug
@ -776,7 +833,7 @@ byte *generate_payload(GB_ROM curr_rom, int type, bool debug)
z80_patchlist.JP(jump_to_party.place_direct_jump(&z80_patchlist) | T_U16); // jp pkmn list (because saving the box overwrites the data)
array_counter.insert_variable(&z80_patchlist);
removal_array.insert_variable(&z80_patchlist);
removal_array.insert_variable(&z80_payload);
transfer_wait_string.insert_variable(&z80_patchlist);
// This payload works by placing Pokemon ID 0xFC's name in the stack, and causing a return to CD8E,
@ -817,7 +874,7 @@ int test_main() // Rename to "main" to send the payload to test_payload.txt
{
freopen("test_payload.txt", "w", stdout);
std::cout << std::endl;
byte *payload = generate_payload(ENG_RED, TRANSFER, true);
byte *payload = generate_payload(ENG_GOLD, TRANSFER, true);
if (true)
{
for (int i = 0; i < 0x2A0; i++)

View File

@ -158,13 +158,14 @@ void Pokemon::convert_to_gen_three(bool simplified, bool stabilize_mythical)
species_index_struct = gen_1_index_array[species_index_struct];
}
if (species_index_struct > 251 || // Checks if the Pokemon is beyond Celebi
if (index_in_box % 4 == 0 ||
species_index_struct > 251 || // Checks if the Pokemon is beyond Celebi
species_index_struct == 0 || // Checks that the Pokemon isn't a blank party space
species_index_struct != species_index_party || // Checks that the Pokemon isn't a hybrid or an egg
index_in_box >= num_in_box || // Checks that we're not reading beyond the Pokemon in the box
item != 0) // Checks that the Pokemon doesn't have an item
{
if (!SHOW_INVALID_PKMN)
if (!NO_INVALID_PKMN)
{
is_valid = false;
return;

View File

@ -350,7 +350,7 @@ void load_temp_box_sprites(Pokemon_Party party_data)
u32 curr_tile_id = global_tile_id_end;
for (int i = 0; i < 30; i++)
{
if (party_data.get_simple_pkmn(i).is_valid || SHOW_INVALID_PKMN)
if (party_data.get_simple_pkmn(i).is_valid || NO_INVALID_PKMN)
{
Simplified_Pokemon curr_pkmn = party_data.get_simple_pkmn(i);
int dex_num = curr_pkmn.dex_number;