mirror of
https://github.com/GearsProgress/Poke_Transporter_GB.git
synced 2026-07-15 07:44:11 -05:00
664 lines
19 KiB
C++
664 lines
19 KiB
C++
// Loosely based on code created by StevenChaulk
|
|
// Source: https://github.com/stevenchaulk/arduino-poke-gen2
|
|
|
|
#include <tonc.h>
|
|
#include <stdarg.h>
|
|
#include <inttypes.h>
|
|
#include "libraries/nanoprintf/nanoprintf.h"
|
|
#include "libstd_replacements.h"
|
|
#include "link_handler.h"
|
|
#include "script_array.h"
|
|
#include "dbg/debug_mode.h"
|
|
#include "interrupt.h"
|
|
#include "text_engine.h"
|
|
#include "global_frame_controller.h"
|
|
#include "background_engine.h"
|
|
#include "sprite_data.h"
|
|
#include "text_data_table.h"
|
|
#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;
|
|
|
|
// TODO get rid of this because it should not exist and should be done with math
|
|
byte tradePreambleBytes[] = {0x00, 0x00, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD};
|
|
|
|
// 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 ROM_DATA) == 160);
|
|
|
|
int link_cable_array_index = 0;
|
|
int link_cable_memory_section_index = 0;
|
|
|
|
void print(const char *format, ...)
|
|
{
|
|
// I don't think this function is called anymore...
|
|
va_list args;
|
|
va_start(args, format);
|
|
|
|
// 10 elements of 64 bytes, zero-initialized.
|
|
char spi_text_out_array[10][SPI_TEXT_OUT_ARRAY_ELEMENT_SIZE] = {
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0},
|
|
{0}};
|
|
|
|
for (int i = 10; i > 0; i--)
|
|
{
|
|
strncpy(spi_text_out_array[i], spi_text_out_array[i - 1], SPI_TEXT_OUT_ARRAY_ELEMENT_SIZE);
|
|
}
|
|
|
|
npf_vsnprintf(spi_text_out_array[0], SPI_TEXT_OUT_ARRAY_ELEMENT_SIZE, format, args);
|
|
va_end(args);
|
|
|
|
tte_erase_rect(0, 0, H_MAX, V_MAX);
|
|
|
|
for (int j = 0; j < 10; j++)
|
|
{
|
|
tte_erase_rect(0, 0, H_MAX, V_MAX);
|
|
tte_set_pos(0, 0);
|
|
ptgb_write_simple(reinterpret_cast<const byte *>("#{cx:0xE000}"), true);
|
|
ptgb_write_simple((byte *)(spi_text_out_array[j]), true);
|
|
}
|
|
}
|
|
|
|
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;
|
|
irq_enable(II_TIMER3);
|
|
|
|
linkSPI->activate(LinkSPI::Mode::MASTER_256KBPS);
|
|
linkSPI->setWaitModeActive(false);
|
|
|
|
currLinkState = new LinkState;
|
|
currLinkState->box_data_storage = box_data_storage;
|
|
currLinkState->curr_gb_rom = curr_rom;
|
|
currLinkState->box = box;
|
|
currLinkState->debug_charset = debug_charset;
|
|
currLinkState->cancel_connection = cancel_connection;
|
|
|
|
{
|
|
u8 general_text_table_buffer[2048];
|
|
text_data_table general_text(general_text_table_buffer);
|
|
|
|
general_text.decompress(get_compressed_text_table(GENERAL_INDEX));
|
|
ptgb_write_textbox(general_text.get_text_entry(GENERAL_connecting), true, false,
|
|
GENERAL_INDEX, GENERAL_connecting, false);
|
|
}
|
|
|
|
create_textbox(0, 0, 125, 128, false);
|
|
}
|
|
|
|
byte handleIncomingByte()
|
|
{
|
|
// TODO this should be moved outside of this function.
|
|
currLinkState->section_data_counter += 1;
|
|
switch (currLinkState->conState)
|
|
{
|
|
case CLOCK:
|
|
currLinkState->mosi_delay = 4;
|
|
if (currLinkState->in_data == 0xFE)
|
|
{
|
|
currLinkState->conState = MENU;
|
|
return 0x00;
|
|
}
|
|
return 0x01;
|
|
break;
|
|
/*
|
|
case ACK:
|
|
if (currLinkState->in_data == 0x61)
|
|
{
|
|
currLinkState->conState = MENU;
|
|
return 0x61;
|
|
}
|
|
else if (currLinkState->in_data == 0x00)
|
|
{
|
|
currLinkState->conState = MENU;
|
|
return 0x00;
|
|
}
|
|
break;
|
|
*/
|
|
case MENU:
|
|
if (currLinkState->in_data == 0xD0 || currLinkState->in_data == 0x61)
|
|
{
|
|
currLinkState->conState = WAIT_FOR_TRADE;
|
|
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;
|
|
}
|
|
}
|
|
else if (currLinkState->in_data == 0x02)
|
|
{
|
|
currLinkState->conState = CLOCK;
|
|
return 0x02;
|
|
}
|
|
else
|
|
{
|
|
return currLinkState->in_data;
|
|
}
|
|
break;
|
|
|
|
case WAIT_FOR_TRADE:
|
|
if (currLinkState->in_data == 0xFD)
|
|
{
|
|
REG_TM3D = -0x0040;
|
|
currLinkState->section_data_counter = 0;
|
|
currLinkState->conState = TRADE_PREAMBLE;
|
|
return 0x00;
|
|
}
|
|
return currLinkState->in_data;
|
|
break;
|
|
case TRADE_PREAMBLE:
|
|
if (currLinkState->section_data_counter >= 10)
|
|
{
|
|
currLinkState->section_data_counter = 0;
|
|
currLinkState->conState = TRADE;
|
|
return 0xFD;
|
|
};
|
|
return tradePreambleBytes[currLinkState->section_data_counter];
|
|
case TRADE:
|
|
if (currLinkState->section_data_counter >= currLinkState->curr_payload_size - 1)
|
|
{
|
|
if (currLinkState->gen == 2)
|
|
{
|
|
currLinkState->section_data_counter = 0;
|
|
currLinkState->conState = MAIL;
|
|
}
|
|
else
|
|
{
|
|
currLinkState->conState = END;
|
|
}
|
|
}
|
|
return currLinkState->curr_payload[currLinkState->section_data_counter];
|
|
break;
|
|
case MAIL:
|
|
if (currLinkState->section_data_counter >= 0x186)
|
|
{
|
|
currLinkState->conState = END;
|
|
}
|
|
case END:
|
|
currLinkState->irq_enabled = false;
|
|
break;
|
|
|
|
default:
|
|
return currLinkState->in_data;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
/*
|
|
case PARTY_PREAMBLE:
|
|
if (currLinkState->in_data != 0xfd)
|
|
{
|
|
currLinkState->conState = TRADE_DATA;
|
|
return exchange_parties(currLinkState->in_data, currLinkState->curr_payload);
|
|
}
|
|
return currLinkState->in_data;
|
|
break;
|
|
case TRADE_DATA:
|
|
if (currLinkState->section_data_counter >= currLinkState->curr_gb_rom->payload_size)
|
|
{
|
|
if (currLinkState->in_data == 0xFD)
|
|
{
|
|
currLinkState->conState = BOX_PREAMBLE;
|
|
currLinkState->init_packet = true;
|
|
}
|
|
else
|
|
{
|
|
return 0x00;
|
|
}
|
|
}
|
|
return exchange_parties(currLinkState->in_data, currLinkState->curr_payload);
|
|
break;
|
|
case BOX_PREAMBLE:
|
|
if (currLinkState->in_data != 0xFD)
|
|
{
|
|
currLinkState->conState = BOX_DATA;
|
|
return exchange_boxes(currLinkState->in_data, currLinkState->box_data_storage, currLinkState->curr_gb_rom, currLinkState->debug_charset);
|
|
}
|
|
return currLinkState->in_data;
|
|
break;
|
|
case BOX_DATA:
|
|
return exchange_boxes(currLinkState->in_data, currLinkState->box_data_storage, currLinkState->curr_gb_rom, currLinkState->debug_charset);
|
|
break;
|
|
case REBOOT:
|
|
currLinkState->section_data_counter = 0;
|
|
currLinkState->conState = REMOVE_ARRAY_PREAMBLE;
|
|
return 0xFD;
|
|
break;
|
|
|
|
case REMOVE_ARRAY_PREAMBLE:
|
|
if (currLinkState->in_data != 0xFD)
|
|
{
|
|
currLinkState->conState = SEND_REMOVE_ARRAY;
|
|
return exchange_remove_array(currLinkState->in_data, currLinkState->box, currLinkState->cancel_connection);
|
|
}
|
|
return currLinkState->in_data;
|
|
break;
|
|
|
|
case SEND_REMOVE_ARRAY:
|
|
if (currLinkState->section_data_counter >= 29) // This assumes the preamble does not count towards the number of bytes sent over the cable
|
|
{
|
|
currLinkState->conState = END2;
|
|
}
|
|
currLinkState->section_data_counter++;
|
|
return exchange_remove_array(currLinkState->in_data, currLinkState->box, currLinkState->cancel_connection);
|
|
break;
|
|
|
|
default:
|
|
return currLinkState->in_data;
|
|
break;
|
|
}
|
|
|
|
return 0; // This should never hit but the compiler likes this being here
|
|
}*/
|
|
/*
|
|
int loop(byte *box_data_storage, byte *curr_payload, GB_ROM *curr_gb_rom, PokeBox *box, const u16 *debug_charset, bool cancel_connection)
|
|
{
|
|
#define LINE_WIDTH 21
|
|
#define NUM_LINES 2
|
|
int counter = 0;
|
|
char stuff[NUM_LINES][LINE_WIDTH];
|
|
|
|
currLinkState->box_data_storage = box_data_storage;
|
|
currLinkState->curr_payload = curr_payload;
|
|
currLinkState->curr_gb_rom = curr_gb_rom;
|
|
currLinkState->box = box;
|
|
currLinkState->debug_charset = debug_charset;
|
|
currLinkState->cancel_connection = cancel_connection;
|
|
|
|
while (true)
|
|
{
|
|
if (g_debug_options.print_link_data && key_held(KEY_L))
|
|
{
|
|
while (!key_hit(KEY_R))
|
|
{
|
|
VBlankIntrWait();
|
|
}
|
|
VBlankIntrWait();
|
|
}
|
|
// TODO: Restore Errors
|
|
currLinkState->in_data = linkSPI->transfer(currLinkState->out_data);
|
|
|
|
if (g_debug_options.print_link_data && !key_held(KEY_DOWN))
|
|
{
|
|
for (int i = 0; i < NUM_LINES; i++)
|
|
{
|
|
for (int j = 0; j < LINE_WIDTH; j++)
|
|
{
|
|
stuff[i][j] = stuff[i + 1][j];
|
|
}
|
|
stuff[i][20] = '\n';
|
|
}
|
|
n2hexstr(&stuff[NUM_LINES - 1][0], counter & 0xFFFFFF, 6);
|
|
stuff[NUM_LINES - 1][6] = ':';
|
|
n2hexstr(&stuff[NUM_LINES - 1][7], currLinkState->data_counter & 0xFFFF, 4);
|
|
stuff[NUM_LINES - 1][11] = '|';
|
|
n2hexstr(&stuff[NUM_LINES - 1][12], currLinkState->conState & 0xFF, 2);
|
|
stuff[NUM_LINES - 1][14] = '|';
|
|
n2hexstr(&stuff[NUM_LINES - 1][15], currLinkState->in_data & 0xFF, 2);
|
|
stuff[NUM_LINES - 1][17] = '|';
|
|
n2hexstr(&stuff[NUM_LINES - 1][18], currLinkState->out_data & 0xFF, 2);
|
|
stuff[NUM_LINES - 1][20] = '\0';
|
|
|
|
create_textbox(0, 0, 125, 128, false);
|
|
ptgb_write_debug(debug_charset, *stuff, true);
|
|
}
|
|
else if (g_debug_options.write_cable_data_to_save)
|
|
{
|
|
global_memory_buffer[link_cable_array_index] = currLinkState->in_data;
|
|
link_cable_array_index++;
|
|
global_memory_buffer[link_cable_array_index] = currLinkState->out_data;
|
|
link_cable_array_index++;
|
|
if (link_cable_array_index >= 0x1000)
|
|
{
|
|
copy_ram_to_save(&global_memory_buffer[0], 0x1000 * link_cable_memory_section_index, 0x1000);
|
|
link_cable_memory_section_index++;
|
|
link_cable_array_index = link_cable_array_index % 0x1000;
|
|
}
|
|
}
|
|
|
|
currLinkState->out_data = handleIncomingByte();
|
|
|
|
if (currLinkState->FF_count > (15 * 60))
|
|
{
|
|
return COND_ERROR_DISCONNECT;
|
|
}
|
|
if (currLinkState->zero_count > (5 * 60))
|
|
{
|
|
// return COND_ERROR_COM_ENDED;
|
|
}
|
|
if (currLinkState->conState == COLOSSEUM)
|
|
{
|
|
return COND_ERROR_COLOSSEUM;
|
|
}
|
|
|
|
if (currLinkState->conState == END1)
|
|
{
|
|
currLinkState->conState = REBOOT;
|
|
if (g_debug_options.write_cable_data_to_save)
|
|
{
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
global_memory_buffer[(link_cable_array_index + i) % 0x1000] = 0xAA;
|
|
}
|
|
copy_ram_to_save(&global_memory_buffer[0], 0x1000 * link_cable_memory_section_index, 0x1000);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (currLinkState->conState == END2)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (key_held(KEY_SELECT)) // Forces a disconnect... not sure why it would need to be locked behind debug mode
|
|
{
|
|
return COND_ERROR_DISCONNECT;
|
|
}
|
|
|
|
if (currLinkState->conState != BOX_DATA)
|
|
{
|
|
currLinkState->FF_count = (currLinkState->in_data == 0xFF ? currLinkState->FF_count + currLinkState->mosi_delay : 0);
|
|
currLinkState->zero_count = (currLinkState->in_data == 0x00 ? currLinkState->zero_count + currLinkState->mosi_delay : 0);
|
|
}
|
|
|
|
counter++;
|
|
for (int i = 0; i < currLinkState->mosi_delay; i++)
|
|
{
|
|
VBlankIntrWait();
|
|
}
|
|
}
|
|
};
|
|
*/
|
|
|
|
#define LINE_WIDTH 21
|
|
#define NUM_LINES 8
|
|
char stuff[NUM_LINES][LINE_WIDTH];
|
|
char line[LINE_WIDTH] = "OUT";
|
|
ConnectionState prevConState;
|
|
|
|
void handshake()
|
|
{
|
|
if (g_debug_options.print_link_data && key_hit(KEY_LEFT))
|
|
{
|
|
currLinkState->irq_enabled = false;
|
|
}
|
|
|
|
else if (g_debug_options.print_link_data && key_hit(KEY_RIGHT))
|
|
{
|
|
currLinkState->irq_enabled = true;
|
|
}
|
|
|
|
if (!currLinkState->irq_enabled)
|
|
{
|
|
if (!(g_debug_options.print_link_data && key_hit(KEY_A)))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
prevConState = currLinkState->conState; // The con state can change in handleIncomingByte - we want to display what it was before running that function
|
|
|
|
int timeout_frames = 10;
|
|
currLinkState->in_data = linkSPI->transfer(currLinkState->out_data, [&timeout_frames]()
|
|
{
|
|
// In the mGBA Lua bridge, replies arrive via emulator callbacks between frames.
|
|
// Waiting here prevents valid bytes from being reported as timeouts.
|
|
global_next_frame();
|
|
return --timeout_frames <= 0; });
|
|
|
|
currLinkState->in_data = linkSPI->transfer(currLinkState->out_data);
|
|
|
|
currLinkState->out_data = handleIncomingByte();
|
|
|
|
if (g_debug_options.print_link_data && !key_held(KEY_DOWN))
|
|
{
|
|
n2hexstr(&line[0], currLinkState->global_data_counter & 0xFFFFFF, 6);
|
|
line[6] = ':';
|
|
n2hexstr(&line[7], currLinkState->section_data_counter & 0xFFFF, 4);
|
|
line[11] = '|';
|
|
n2hexstr(&line[12], prevConState & 0xFF, 2);
|
|
line[14] = '|';
|
|
n2hexstr(&line[15], currLinkState->in_data & 0xFF, 2);
|
|
line[17] = '|';
|
|
n2hexstr(&line[18], currLinkState->out_data & 0xFF, 2);
|
|
line[20] = '\0';
|
|
scroll_text(true, tte_get_context(), false, 8, 8, 127, 135);
|
|
ptgb_write_debug(currLinkState->debug_charset, line, true);
|
|
}
|
|
else if (g_debug_options.write_cable_data_to_save)
|
|
{
|
|
global_memory_buffer[link_cable_array_index] = currLinkState->in_data;
|
|
link_cable_array_index++;
|
|
global_memory_buffer[link_cable_array_index] = currLinkState->out_data;
|
|
link_cable_array_index++;
|
|
if (link_cable_array_index >= 0x1000)
|
|
{
|
|
copy_ram_to_save(&global_memory_buffer[0], 0x1000 * link_cable_memory_section_index, 0x1000);
|
|
link_cable_memory_section_index++;
|
|
link_cable_array_index = link_cable_array_index % 0x1000;
|
|
}
|
|
}
|
|
|
|
currLinkState->global_data_counter++;
|
|
}
|
|
|
|
byte exchange_parties(byte curr_in, byte *curr_payload)
|
|
{
|
|
int ret = curr_payload[currLinkState->section_data_counter];
|
|
currLinkState->section_data_counter += 1;
|
|
return ret;
|
|
};
|
|
|
|
byte exchange_boxes(byte curr_in, byte *box_data_storage, GB_ROM *curr_gb_rom, const u16 *debug_charset)
|
|
{
|
|
currLinkState->data_packet[currLinkState->packet_index] = curr_in;
|
|
if (currLinkState->packet_index == PACKET_SIZE - 1)
|
|
{
|
|
byte checksum = 0;
|
|
for (int i = 0; i < DATA_PER_PACKET; i++)
|
|
{
|
|
if (currLinkState->data_packet[PACKET_FLAG_AT(i)] == 1)
|
|
{
|
|
currLinkState->data_packet[PACKET_DATA_AT(i)] = 0xFE;
|
|
}
|
|
checksum += currLinkState->data_packet[PACKET_DATA_AT(i)];
|
|
}
|
|
checksum &= 0b01111111; // Reset the top bit so it matches the recieved range
|
|
if (!currLinkState->init_packet)
|
|
{
|
|
currLinkState->received_offset = (currLinkState->data_packet[PACKET_LOCATION_LOWER] | (currLinkState->data_packet[PACKET_LOCATION_UPPER] << 8)) - ((curr_gb_rom->wBoxDataStart & 0xFFFF) + DATA_PER_PACKET);
|
|
}
|
|
|
|
if (checksum == currLinkState->data_packet[PACKET_CHECKSUM] && !currLinkState->init_packet && !(currLinkState->test_packet_fail && currLinkState->received_offset == 128)) // Verify if the data matches the checksum
|
|
{
|
|
for (int i = 0; i < DATA_PER_PACKET; i++)
|
|
{
|
|
if (currLinkState->received_offset + i <= curr_gb_rom->box_data_size && currLinkState->received_offset + i >= 0)
|
|
{
|
|
box_data_storage[currLinkState->received_offset + i] = currLinkState->data_packet[PACKET_DATA_AT(i)];
|
|
}
|
|
}
|
|
}
|
|
else if (!currLinkState->init_packet)
|
|
{
|
|
currLinkState->failed_packet = true;
|
|
if (currLinkState->test_packet_fail)
|
|
{
|
|
currLinkState->test_packet_fail = false;
|
|
}
|
|
}
|
|
|
|
if (currLinkState->end_of_data)
|
|
{
|
|
currLinkState->conState = END1;
|
|
}
|
|
else
|
|
{
|
|
currLinkState->conState = BOX_PREAMBLE;
|
|
}
|
|
|
|
if (currLinkState->received_offset > curr_gb_rom->box_data_size + DATA_PER_PACKET)
|
|
{
|
|
currLinkState->end_of_data = true;
|
|
}
|
|
|
|
if (!currLinkState->init_packet)
|
|
{
|
|
if (currLinkState->failed_packet)
|
|
{
|
|
currLinkState->next_offset -= DATA_PER_PACKET;
|
|
if (currLinkState->next_offset < 0)
|
|
{
|
|
currLinkState->next_offset = 0;
|
|
}
|
|
currLinkState->failed_packet = false;
|
|
}
|
|
else
|
|
{
|
|
currLinkState->next_offset += DATA_PER_PACKET;
|
|
}
|
|
}
|
|
if (((currLinkState->next_offset + curr_gb_rom->wBoxDataStart) & 0xFF) == 0xFE)
|
|
{
|
|
currLinkState->next_offset -= 1; // Set back the offset if the byte sent would be 0xFE, since that would break the system
|
|
}
|
|
|
|
#define ROW_LENGTH 22
|
|
#define COLUMN_LENGTH 3 + DATA_PER_PACKET
|
|
if (SHOW_DATA_PACKETS)
|
|
{
|
|
char outArr[COLUMN_LENGTH][ROW_LENGTH];
|
|
for (int col = 0; col < COLUMN_LENGTH; col++)
|
|
{
|
|
for (int row = 0; row < ROW_LENGTH; row++)
|
|
{
|
|
if (row == ROW_LENGTH - 1 && col == COLUMN_LENGTH - 1)
|
|
{
|
|
outArr[col][row] = '\0';
|
|
}
|
|
else if (row == ROW_LENGTH - 1)
|
|
{
|
|
outArr[col][row] = '\n';
|
|
}
|
|
else
|
|
{
|
|
outArr[col][row] = ' ';
|
|
}
|
|
}
|
|
}
|
|
int currRow = 0;
|
|
|
|
strcpy(&outArr[currRow][0], "Checksum: ");
|
|
outArr[currRow][10] = ' ';
|
|
n2hexstr(&outArr[currRow][11], checksum, 2);
|
|
strcpy(&outArr[currRow][13], " = ");
|
|
n2hexstr(&outArr[currRow][16], currLinkState->data_packet[PACKET_CHECKSUM], 2);
|
|
outArr[currRow][18] = ' ';
|
|
currRow += 1;
|
|
|
|
for (int i = 0; i < DATA_PER_PACKET; i++)
|
|
{
|
|
outArr[currRow][0] = 'P';
|
|
n2hexstr(&outArr[currRow][1], i, 1);
|
|
strcpy(&outArr[currRow][2], ": ");
|
|
n2hexstr(&outArr[currRow][4], currLinkState->data_packet[PACKET_DATA_AT(i)], 2);
|
|
strcpy(&outArr[currRow][6], " (");
|
|
n2hexstr(&outArr[currRow][8], currLinkState->data_packet[PACKET_FLAG_AT(i)], 2);
|
|
outArr[currRow][10] = ')';
|
|
currRow += 1;
|
|
}
|
|
|
|
strcpy(&outArr[currRow][0], "RO: ");
|
|
n2hexstr(&outArr[currRow][4], currLinkState->received_offset, 4);
|
|
strcpy(&outArr[currRow][8], " FP: ");
|
|
n2hexstr(&outArr[currRow][14], currLinkState->failed_packet, 2);
|
|
outArr[currRow][16] = ' ';
|
|
currRow += 1;
|
|
|
|
strcpy(&outArr[currRow][0], "NO: ");
|
|
n2hexstr(&outArr[currRow][4], currLinkState->next_offset, 4);
|
|
strcpy(&outArr[currRow][8], " IP: ");
|
|
n2hexstr(&outArr[currRow][14], currLinkState->init_packet, 2);
|
|
outArr[currRow][16] = ' ';
|
|
|
|
// create_textbox(0, 0, 125, 110, false);
|
|
link_animation_state(0);
|
|
ptgb_write_debug(debug_charset, *outArr, true);
|
|
|
|
while (!key_held(KEY_A))
|
|
{
|
|
VBlankIntrWait();
|
|
}
|
|
VBlankIntrWait();
|
|
}
|
|
currLinkState->packet_index = 0;
|
|
currLinkState->init_packet = false;
|
|
}
|
|
currLinkState->packet_index += 1;
|
|
switch (currLinkState->packet_index)
|
|
{
|
|
case 3:
|
|
if (currLinkState->end_of_data)
|
|
{
|
|
return 0xFF;
|
|
}
|
|
return (curr_gb_rom->wBoxDataStart + currLinkState->next_offset) >> 8;
|
|
case 2:
|
|
return (curr_gb_rom->wBoxDataStart + currLinkState->next_offset) >> 0;
|
|
default:
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
byte exchange_remove_array(byte curr_in, PokeBox *box, bool cancel_connection)
|
|
{
|
|
for (int i = 29; i >= 0; i--)
|
|
{
|
|
if (box->getGen3Pokemon(i)->isValid && !cancel_connection)
|
|
{
|
|
box->removePokemon(i);
|
|
if (!(DONT_TRANSFER_POKEMON_AT_INDEX_X && i == POKEMON_INDEX_TO_SKIP))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
} |