mirror of
https://github.com/GearsProgress/Poke_Transporter_GB.git
synced 2026-10-23 07:53:18 -05:00
497 lines
17 KiB
C++
497 lines
17 KiB
C++
#ifndef LINK_HANDLER_H_
|
|
#define LINK_HANDLER_H_
|
|
|
|
#include "GB_Payloads.h"
|
|
#include "gb_rom_values/base_gb_rom_struct.h"
|
|
#include "libraries/gba-link-connection/include/LinkSPI.hpp"
|
|
#include "typeDefs.h"
|
|
#include <tonc.h>
|
|
|
|
#define SPI_TEXT_OUT_ARRAY_ELEMENT_SIZE 64
|
|
|
|
enum GameBoyROM
|
|
{
|
|
RED_JP_v0,
|
|
RED_JP_v1,
|
|
RED_EN,
|
|
RED_FR,
|
|
RED_IT,
|
|
RED_DE,
|
|
RED_SP,
|
|
GREEN_JP_v0,
|
|
GREEN_JP_v1,
|
|
BLUE_JP,
|
|
BLUE_EN,
|
|
BLUE_FR,
|
|
BLUE_IT,
|
|
BLUE_DE,
|
|
BLUE_SP,
|
|
YELLOW_JP_v0,
|
|
YELLOW_JP_v1,
|
|
YELLOW_JP_v2,
|
|
YELLOW_JP_v3,
|
|
YELLOW_EN,
|
|
YELLOW_FR,
|
|
YELLOW_IT,
|
|
YELLOW_DE,
|
|
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_v0,
|
|
CRYSTAL_EN_v1,
|
|
CRYSTAL_EN_vA,
|
|
CRYSTAL_FR,
|
|
CRYSTAL_IT,
|
|
CRYSTAL_DE,
|
|
CRYSTAL_SP,
|
|
|
|
NO_GB_ROM,
|
|
GB_ROM_ERROR,
|
|
};
|
|
|
|
const GB_PayloadsFiles GameBoyROMPayloads[] = {
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_R, // RED_JP_v0
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_R11, // RED_JP_v1
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_EN_R, // RED_EN
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_FR_R, // RED_FR
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_IT_R, // RED_IT
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_DE_R, // RED_DE
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_SP_R, // RED_SP
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_GR, // GREEN_JP_v0
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_GR11, // GREEN_JP_v1
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_B, // BLUE_JP
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_EN_B, // BLUE_EN
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_FR_B, // BLUE_FR
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_IT_B, // BLUE_IT
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_DE_B, // BLUE_DE
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_SP_B, // BLUE_SP
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_Y, // YELLOW_JP_v0
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_Y11, // YELLOW_JP_v1
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_Y12, // YELLOW_JP_v2
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_JP_Y13, // YELLOW_JP_v3
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_EN_Y, // YELLOW_EN
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_FR_Y, // YELLOW_FR
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_IT_Y, // YELLOW_IT
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_DE_Y, // YELLOW_DE
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN1_SP_Y, // YELLOW_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_v0
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN2_EN_C11, // CRYSTAL_EN_v1
|
|
GB_PayloadsFiles::SPECIFICPAYLOADGEN2_EN_CAU, // CRYSTAL_EN_vA
|
|
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[] = {
|
|
JAPANESE, // RED_JP_v0
|
|
JAPANESE, // RED_JP_v1
|
|
ENGLISH, // RED_EN
|
|
FRENCH, // RED_FR
|
|
ITALIAN, // RED_IT
|
|
GERMAN, // RED_DE
|
|
SPANISH, // RED_SP
|
|
JAPANESE, // GREEN_JP_v0
|
|
JAPANESE, // GREEN_JP_v1
|
|
JAPANESE, // BLUE_JP
|
|
ENGLISH, // BLUE_EN
|
|
FRENCH, // BLUE_FR
|
|
ITALIAN, // BLUE_IT
|
|
GERMAN, // BLUE_DE
|
|
SPANISH, // BLUE_SP
|
|
JAPANESE, // YELLOW_JP_v0
|
|
JAPANESE, // YELLOW_JP_v1
|
|
JAPANESE, // YELLOW_JP_v2
|
|
JAPANESE, // YELLOW_JP_v3
|
|
ENGLISH, // YELLOW_EN
|
|
FRENCH, // YELLOW_FR
|
|
ITALIAN, // YELLOW_IT
|
|
GERMAN, // YELLOW_DE
|
|
SPANISH, // YELLOW_SP
|
|
JAPANESE, // GOLD_JP_v0
|
|
JAPANESE, // GOLD_JP_v1
|
|
ENGLISH, // GOLD_EN
|
|
FRENCH, // GOLD_FR
|
|
ITALIAN, // GOLD_IT
|
|
GERMAN, // GOLD_DE
|
|
SPANISH, // GOLD_SP
|
|
KOREAN, // GOLD_KOR
|
|
JAPANESE, // SILVER_JP_v0
|
|
JAPANESE, // SILVER_JP_v1
|
|
ENGLISH, // SILVER_EN
|
|
FRENCH, // SILVER_FR
|
|
ITALIAN, // SILVER_IT
|
|
GERMAN, // SILVER_DE
|
|
SPANISH, // SILVER_SP
|
|
KOREAN, // SILVER_KOR
|
|
JAPANESE, // CRYSTAL_JP
|
|
ENGLISH, // CRYSTAL_EN_v0
|
|
ENGLISH, // CRYSTAL_EN_v1
|
|
ENGLISH, // CRYSTAL_EN_vA
|
|
FRENCH, // CRYSTAL_FR
|
|
ITALIAN, // CRYSTAL_IT
|
|
GERMAN, // CRYSTAL_DE
|
|
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_v0
|
|
CRYSTAL, // CRYSTAL_EN_v1
|
|
CRYSTAL, // CRYSTAL_EN_vA
|
|
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},
|
|
{0x31, 0xB8, 0x66, RED_JP_v1},
|
|
{0x20, 0x91, 0xE6, RED_EN},
|
|
{0x18, 0x7A, 0xFC, RED_FR},
|
|
{0x18, 0x89, 0xD2, RED_IT},
|
|
{0x18, 0x5C, 0xDC, RED_DE},
|
|
{0x18, 0x38, 0x4A, RED_SP},
|
|
{0x9C, 0xDD, 0xD5, GREEN_JP_v0},
|
|
{0x9B, 0xF5, 0x47, GREEN_JP_v1},
|
|
{0xE5, 0xDC, 0x36, BLUE_JP},
|
|
{0xD3, 0x9D, 0x0A, BLUE_EN},
|
|
{0xCB, 0x56, 0xA4, BLUE_FR},
|
|
{0xCB, 0x5E, 0x9C, BLUE_IT},
|
|
{0xCB, 0x2E, 0xBC, BLUE_DE},
|
|
{0xCB, 0x14, 0xD7, BLUE_SP},
|
|
{0x20, 0x9C, 0x29, YELLOW_JP_v0},
|
|
{0x1F, 0x88, 0x58, YELLOW_JP_v1},
|
|
{0x1E, 0xED, 0xD9, YELLOW_JP_v2},
|
|
{0x1D, 0xD9, 0x84, YELLOW_JP_v3},
|
|
{0x97, 0x04, 0x7C, YELLOW_EN},
|
|
{0x5F, 0xB7, 0xC1, YELLOW_FR},
|
|
{0x5C, 0x4E, 0x8F, YELLOW_IT},
|
|
{0x61, 0x66, 0xFB, YELLOW_DE},
|
|
{0x52, 0x56, 0x37, YELLOW_SP},
|
|
{0x48, 0x8A, 0x70, GOLD_JP_v0},
|
|
{0x47, 0x84, 0x60, GOLD_JP_v1},
|
|
{0x4B, 0x68, 0x2D, GOLD_EN},
|
|
{0x4A, 0x6F, 0xC6, GOLD_FR},
|
|
{0x47, 0xCE, 0x0C, GOLD_IT},
|
|
{0x4C, 0xDC, 0x97, GOLD_DE},
|
|
{0x3D, 0x93, 0x53, GOLD_SP},
|
|
{0x08, 0x77, 0x8A, GOLD_KOR},
|
|
{0x27, 0x76, 0x91, SILVER_JP_v0},
|
|
{0x26, 0x1D, 0x34, SILVER_JP_v1},
|
|
{0x2A, 0x0D, 0xAE, SILVER_EN},
|
|
{0x29, 0xFB, 0x8C, SILVER_FR},
|
|
{0x26, 0x73, 0x50, SILVER_IT},
|
|
{0x2B, 0xCD, 0x6E, SILVER_DE},
|
|
{0x1C, 0x06, 0x4B, SILVER_SP},
|
|
{0xE7, 0x98, 0x5B, SILVER_KOR},
|
|
{0x22, 0x9A, 0x40, CRYSTAL_JP},
|
|
{0x27, 0x12, 0x9F, CRYSTAL_EN_v0},
|
|
{0x26, 0x18, 0xD2, CRYSTAL_EN_v1},
|
|
{0x17, 0xAF, 0x7C, CRYSTAL_EN_vA},
|
|
{0x26, 0xF2, 0xE2, CRYSTAL_FR},
|
|
{0x23, 0xDB, 0xBA, CRYSTAL_IT},
|
|
{0x28, 0x49, 0x82, CRYSTAL_DE},
|
|
{0x19, 0x42, 0xF4, CRYSTAL_SP},
|
|
};
|
|
|
|
enum LinkState
|
|
{
|
|
INITIAL_CONNECTION = 0x00,
|
|
DISCOVERY_RESET,
|
|
CLOCK_ACQUIRE,
|
|
CLOCK_CONFIRM,
|
|
SAVE_SUCCESS,
|
|
MENU_OPEN,
|
|
MENU_SUCCESS,
|
|
WAIT_FOR_TRADE,
|
|
TRADE_PREAMBLE,
|
|
TRADE,
|
|
MAIL,
|
|
WAIT_FOR_CHECKSUM_PAYLOAD,
|
|
GET_CHECKSUM,
|
|
WAIT_FOR_SECOND_PAYLOAD,
|
|
SEND_SPECIFIC_PAYLOAD,
|
|
SEND_FIRST_PACKET,
|
|
|
|
PACKET_EXCHANGE = 0x10,
|
|
STANDARD_PACKET_EXCHANGE,
|
|
RUNNING_CODE_DELAY,
|
|
SECONDARY_PACKET_EXCHANGE,
|
|
PROCESS_PACKET,
|
|
LOAD_NEXT_PACKET,
|
|
|
|
END = 0xFF,
|
|
};
|
|
|
|
enum LinkConnectionError
|
|
{
|
|
NO_ERROR,
|
|
PACKET_TIMED_OUT,
|
|
CHECKSUM_MISMATCH,
|
|
ECHO_MISMATCH,
|
|
ERROR_FLAG,
|
|
|
|
PACKET_SUCCESS,
|
|
PACKET_READ,
|
|
};
|
|
|
|
enum PayloadCommand
|
|
{
|
|
CMD_NONE = 0x7F, // Using 0x7F instead of -1, since that ends up being 0xFE.
|
|
CMD_ReloadCurrentBox = 0, // no arguments used. Reloads the current box from SRAM. Use this as
|
|
// the first command byte before performing other commands.
|
|
CMD_TransferPokemon, // 1st argument = secondary payload size, 2nd argument = box that should be
|
|
// transferred from. This command uses a secondary payload. The size of
|
|
// this secondary payload needs to be declared beforehand. Prior to
|
|
// requesting a secondary payload, the program will use the second argument
|
|
// to load a specific box from SRAM. Box numbers are 0-indexed and range
|
|
// from 0x00 (box 1) to 0x0B(box 12). This load procedure currently cannot
|
|
// be skipped. Once the secondary payload arrives, the program will verify
|
|
// its integrity and align the payload. Afterwards, it will use the
|
|
// information within this payload to remove pokémon from the current box.
|
|
// Once all transferred pokémon have been removed, the program will save
|
|
// the current box.
|
|
CMD_SoftReset, // no arguments used. Instantly soft resets the game.
|
|
CMD_ModifySRAMAccess, // 1st argument = SRAM dis/enable. set to 0x0A to open access, set to 0x00
|
|
// to close access. Second argument = SRAM bank. When closing SRAM access,
|
|
// set to 0x00. SRAM remains open until closed by this command or until
|
|
// closed by CMD_TransferPokemon/CMD_ReloadCurrentBox.
|
|
CMD_RunSecondaryPayload, // 1st argument = secondary payload size. This command uses a secondary
|
|
// payload. The size of this secondary payload needs to be declared
|
|
// beforehand. Once the secondary payload arrives, the program will
|
|
// verify its integrity and align the payload. Afterwards, it will jump
|
|
// to the secondary payload and execute it. IMPORTANT: if you want to
|
|
// report an error when executing this secondary payload, return with
|
|
// carry flag set. IMPORTANT: if you want to report that the payload
|
|
// was executed safely, return with carry flag reset.*/
|
|
CMD_ReadDataRequest, // a request to read data starting from the address defined by the 16-bit
|
|
// pointer.
|
|
CMD_SecondaryPayload = 0xFF, // Used whenever a packet is for a secondary payload.
|
|
};
|
|
|
|
#define OUTP_PREAMBLE_INDEX 0
|
|
#define OUTP_COUNTER_INDEX 1
|
|
#define OUTP_COMMAND_INDEX 2
|
|
#define OUTP_ARGS_INDEX 3
|
|
#define OUTP_POINTER_INDEX 5
|
|
#define OUTP_FILLER_INDEX 7
|
|
#define OUTP_LENGTH 12
|
|
|
|
#define INP_COUNTER_INDEX (0 + INP_DELAY_FROM_OUTP)
|
|
#define INP_LSB_INDEX (1 + INP_DELAY_FROM_OUTP)
|
|
#define INP_CHECKSUM_INDEX (3 + INP_DELAY_FROM_OUTP)
|
|
#define INP_DATA_INDEX (4 + INP_DELAY_FROM_OUTP)
|
|
#define INP_LENGTH (12 + INP_DELAY_FROM_OUTP)
|
|
|
|
#define INP_DELAY_FROM_OUTP 3
|
|
#define TOTAL_PACKET_LENGTH (OUTP_LENGTH + INP_DELAY_FROM_OUTP)
|
|
|
|
struct LinkPacket
|
|
{
|
|
bool inUse = false;
|
|
|
|
// Out packet parameters
|
|
PayloadCommand command = CMD_NONE;
|
|
byte argument[2] = {0x00, 0x00};
|
|
u16 pointer = 0xC6DC;
|
|
byte packetID = 0x7F;
|
|
|
|
// Incoming data
|
|
LinkConnectionError latestError = NO_ERROR;
|
|
byte recievedData[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
// Secondary payload
|
|
byte *secondaryPayloadData = nullptr;
|
|
int secondaryPayloadDataSize = 0;
|
|
byte secondaryPayloadSizeChecksum = 0;
|
|
#define SECONDARY_PAYLOAD_HEADER_SIZE \
|
|
4 // The size of a secondary packet, not including the data bytes or checksum
|
|
|
|
LinkPacket() {};
|
|
LinkPacket(PayloadCommand cmd, byte arg1, byte arg2, u16 addr);
|
|
void loadSecondaryPayload(byte *payload, int paylHeoadSize);
|
|
};
|
|
|
|
class LinkConnection
|
|
{
|
|
public:
|
|
LinkState enterState;
|
|
LinkState exitState;
|
|
bool subStateChanged = false;
|
|
|
|
LinkConnectionError lastError = NO_ERROR;
|
|
|
|
uint8_t inData = 0xFF;
|
|
uint8_t outData = 0xFF;
|
|
uint8_t nextOutData = 0xFF;
|
|
|
|
int globalStateCounter = 0; // The counter for the total number of bytes sent
|
|
int subStateCounter = 0; // The counter for the total number of bytes sent in this substate
|
|
|
|
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
|
|
|
|
byte payloadBuffer[0x2A0];
|
|
int curr_payload_size = 0;
|
|
#define DATA_OUT_BUFFER_SIZE 16
|
|
byte dataOutBuffer[DATA_OUT_BUFFER_SIZE];
|
|
int dataOutBufferCurrIndex = 0;
|
|
|
|
// This MUST be a power of 2!
|
|
#define LINK_PACKET_ARRAY_SIZE 4
|
|
|
|
// This is lower than the max 0x7F so we can save that value for dummy packets
|
|
#define LINK_PACKET_INDEX_MASK 0x3F
|
|
|
|
LinkPacket linkPacketArr[LINK_PACKET_ARRAY_SIZE];
|
|
LinkPacket *currOutgoingPacket;
|
|
LinkPacket *currIncomingPacket;
|
|
LinkPacket dummyPacket = LinkPacket();
|
|
byte linkPacketArrIndex = LINK_PACKET_ARRAY_SIZE; // We want to avoid starting at zero, since
|
|
// that is a common value sent back in error.
|
|
u16 linkPacketDataAddr = 0;
|
|
u16 linkPacketDataStart = 0;
|
|
int linkPacketDataSize = 0;
|
|
byte *outDataArrayPtr;
|
|
|
|
bool pauseOnByte = false; // Used for pausing and sending one byte at a time
|
|
bool pauseOnPacket = false; // Used for pausing and sending one packet at a time
|
|
bool skipPrint = false; // Skips printing to the screen
|
|
|
|
void setup(const u16 *debug_charset);
|
|
void startConnection(LinkState startState);
|
|
bool earlyExit();
|
|
void exchangeBytes();
|
|
void printData();
|
|
void writeData();
|
|
void handleStateLogic();
|
|
void prepareForNextCycle();
|
|
void resetLinkPackets();
|
|
|
|
// These are all the Link Commands
|
|
bool LinkCommand_InitalizeConnection(bool waitForCompletion = true);
|
|
bool LinkCommand_ReloadCurrentBox(bool waitForCompletion = true);
|
|
bool LinkCommand_TransferPokemon(
|
|
int boxNumber, byte removalArray[], int removalArrayLength, bool waitForCompletion = true);
|
|
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(
|
|
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.
|
|
void handleCartIO();
|
|
|
|
private:
|
|
void loadPayload(GB_PayloadsFiles payload);
|
|
void loadPayloadByROM(GameBoyROM rom);
|
|
void loadCurrGameFromChecksum();
|
|
bool allPacketsProcessed();
|
|
bool processPacket();
|
|
void consumePacket();
|
|
bool prepareNextPacket();
|
|
void waitForEnd();
|
|
|
|
// Used for debug features
|
|
#define LINE_WIDTH 24
|
|
#define NUM_LINES 8
|
|
char stuff[NUM_LINES][LINE_WIDTH];
|
|
char line[LINE_WIDTH] = "OUT";
|
|
unsigned link_cable_memory_section_index;
|
|
unsigned link_cable_array_index;
|
|
const u16 *debug_charset;
|
|
unsigned writeBufferOffset;
|
|
};
|
|
|
|
extern LinkConnection globalLinkCable;
|
|
void linkCableIRQ();
|
|
|
|
#endif /* LINK_HANDLER_H_ */
|