Implementing internal payload builder

This commit is contained in:
Remnants of Forgotten Disney 2024-04-21 21:44:14 -05:00
parent 2e3f5e8266
commit 888c257e49
17 changed files with 588 additions and 120 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ build/
*.elf
*.zip
.vscode/
source/payload_builder.exe

View File

@ -3,8 +3,9 @@
#define DEBUG_MODE true
#define IGNORE_GAME_PAK true
#define IGNORE_LINK_CABLE true
#define IGNORE_LINK_CABLE false
#define IGNORE_MG_E4_FLAGS true
#define DONT_REMOVE_PKMN false
#define DEBUG_GAME LEAFGREEN_ID
#define DEBUG_VERS VERS_1_1

View File

@ -32,9 +32,9 @@
#define SLOW_SPEED 1000
void setup();
byte handleIncomingByte(byte in, byte *box_data_storage, PAYLOAD *curr_payload, Simplified_Pokemon *curr_simple_array);
int loop(byte *box_data_storage, PAYLOAD *curr_payload, Simplified_Pokemon *curr_simple_array);
byte exchange_parties(byte curr_in, PAYLOAD *curr_payload);
byte handleIncomingByte(byte in, byte *box_data_storage, byte *curr_payload, Simplified_Pokemon *curr_simple_array);
int loop(byte *box_data_storage, byte *curr_payload, Simplified_Pokemon *curr_simple_array);
byte exchange_parties(byte curr_in, byte *curr_payload);
byte exchange_boxes(byte curr_in, byte *party_data);
byte exchange_remove_array(byte curr_in, Simplified_Pokemon *curr_simple_array);

View File

@ -0,0 +1,62 @@
#ifndef PAYLOAD_H
#define PAYLOAD_H
// Redefine these because C++ doesn't like TONC
typedef unsigned char u8, byte, uchar, echar;
typedef unsigned short u16, hword, ushort, eshort;
typedef unsigned int u32, word, uint, eint;
typedef unsigned long long u64;
#define PAYLOAD_SIZE 637
#define NUM_PAYLOADS 1
#define GB_TILE_WIDTH 20
struct GB_ROM
{
public:
int language;
int version;
byte payload_array[PAYLOAD_SIZE];
hword print_string_start;
hword stack_overwrite_location;
byte short_pkmn_name; // The name of the Pokemon that moves us through RAM
byte pointer_pkmn_name; // The name of the Pokemon that corrupts the stack
byte custom_name[11];
// This can be a few different places:
// wSerialOtherGameboyRandomNumberListBlock:
// 0xCD81 to 0xCD8A
// wLinkEnemyTrainerName:
// 0xD887 to 0xDA2F
// wSerialEnemyMonsPatchList:
// 0xC5D0 to 0xC6E8
byte enter_vector_destination;
hword enter_vector_location;
hword clearScreen;
hword textBoarderUppLeft;
byte textBoarderWidth;
byte textBoarderHeight;
hword CableClub_TextBoxBoarder;
hword transferWaitString;
hword transferStringLocation;
hword placeString;
hword hSerialConnectionStatus;
hword wBoxDataStart;
hword wBoxDataEnd;
hword Serial_ExchangeBytes;
hword garbageDataLocation;
hword pkmnTransferArray;
hword wRemoveMonFromBox;
hword arrayCounter;
hword wBoxCount;
hword wWhichPokemon;
hword _RemovePokemon;
hword SaveSAVtoSRAM1;
byte SaveSAVtoSRAM1_memBank;
hword Bankswitch;
hword SoftReset;
byte transferString[30];
};
#endif

View File

@ -1,9 +1,25 @@
#include <tonc.h>
#ifndef ENG_GB_ROM_VALUES_H
#define ENG_GB_ROM_VALUES_H
#include "payloads/base_payload_struct.h"
#include "pokemon_data.h"
// These are redefined because C++ doesn't like compiling TONC
#define JPN_ID 1
#define ENG_ID 2
#define FRE_ID 3
#define ITA_ID 4
#define GER_ID 5
#define SPA_ID 7
#define KOR_ID 8
const struct PAYLOAD ENG_RED_BLUE = {
#define RED_GREEN_ID 0
#define RED_BLUE_ID 1
#define BLUE_ID 2
#define YELLOW_ID 3
#define GOLD_SILVER_ID 4
#define CRYSTAL_ID 5
#include "gb_rom_values/base_gb_rom_struct.h"
const struct GB_ROM ENG_RED_BLUE = {
.language = ENG_ID,
.version = RED_BLUE_ID,
.payload_array = {
@ -158,4 +174,42 @@ const struct PAYLOAD ENG_RED_BLUE = {
// which is part of the RNG seed. From there we can jump anywhere- and we choose to jump to D887,
// which is the rival's name. This code fixes the stack and jumps to the patchlist, which is where
// our final code is.
}};
},
.print_string_start = 0xC456,
.stack_overwrite_location = 0xDFDD,
.short_pkmn_name = 0xE3,
.pointer_pkmn_name = 0xFC,
.custom_name = {0x85, 0x84, 0x8D, 0x8D, 0x84, 0x8B, 0x50, 0x50, 0x50, 0x50, 0x50},
.enter_vector_destination = 0x05,
.enter_vector_location = 0xC5D6,
.clearScreen = 0x190F,
.textBoarderUppLeft = 0xC42E,
.textBoarderWidth = 3,
.textBoarderHeight = 14,
.CableClub_TextBoxBoarder = 0x5AB3,
.transferWaitString = 0xC67A,
.transferStringLocation = 0xC443,
.placeString = 0x1955,
.hSerialConnectionStatus = 0xFFAA,
.wBoxDataStart = 0xDA80,
.wBoxDataEnd = 0xDEE2,
.Serial_ExchangeBytes = 0x216F,
.garbageDataLocation = 0x0316, // Starts with 0xFD
.pkmnTransferArray = 0xC651,
.wRemoveMonFromBox = 0xCF95,
.arrayCounter = 0xC650,
.wBoxCount = 0xDA80,
.wWhichPokemon = 0xCF92,
._RemovePokemon = 0x7B68,
.SaveSAVtoSRAM1 = 0x77E2,
.SaveSAVtoSRAM1_memBank = 0x1C,
.Bankswitch = 0x35D6,
.SoftReset = 0x1F49,
.transferString = { // 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}
};
#endif

View File

@ -1,5 +1,5 @@
#ifndef BASE_ROM_STRUCT_H
#define BASE_ROM_STRUCT_H
#ifndef BASE_GBA_ROM_STRUCT_H
#define BASE_GBA_ROM_STRUCT_H
#include <tonc.h>

View File

@ -1,7 +1,7 @@
#ifndef ROM_VALUES_ENG_H
#define ROM_VALUES_ENG_H
#include "rom_values/base_rom_struct.h"
#include "gba_rom_values/base_gba_rom_struct.h"
const struct ROM_DATA ENG_RUBY_v0 = {
.is_valid = true,

View File

@ -1,72 +0,0 @@
//Created by StevenChaulk https://github.com/stevenchaulk/arduino-poke-gen2
#include <stdint.h>
#define PLAYER_LENGTH_GEN_I 418 //11+8+(44*6)+(11*6)+(11*6)
#define PLAYER_LENGTH_GEN_II 444 //11+8+2+(48*6)+(11*6)+(11*6)+3
#define PATCH_LIST_LEN_GEN_I 196
//uint8_t INPUT_BLOCK_GEN_I[PLAYER_LENGTH_GEN_I];
//uint8_t INPUT_BLOCK_GEN_II[PLAYER_LENGTH_GEN_II];
/* const uint8_t DATA_BLOCK[PLAYER_LENGTH] PROGMEM = {
0x80, 0x91, 0x83, 0x94, 0x88, 0x8D, 0x8E, 0x50, 0x00, 0x00, 0x00, // name
0x1, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // number of pokemon in party (0x00), pokemon ID (0x01 - 0x06), stop byte (0x07)
// 6 pokemon
//spc curr HP lvl sts typ1 typ2 cr mv1 mv2 mv3 mv4 OT experience HP EV att EV def EV speed EV Speci EV IV mvPP mvPP mvPP mvPP Lvl max HP attack defense speed special
0x24, 0x0, 0xD, 0x2, 0x0, 0x0, 0x2, 0xFF, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46, 0x21, 0x23, 0x0, 0x0, 0x0, 0x2, 0x0, 0xD, 0x0, 0x6, 0x0, 0x6, 0x0, 0x7, 0x0, 0x6,
0x85, 0x0, 0x1, 0x5, 0x1, 0x15, 0x15, 0xFF, 0x96, 0x0, 0x0, 0x0, 0x8, 0x87, 0x0, 0x0, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2D, 0x24, 0x28, 0x0, 0x0, 0x0, 0x5, 0x0, 0x11, 0x0, 0x6, 0x0, 0xB, 0x0, 0xD, 0x0, 0x7,
0x85, 0x0, 0x1, 0x5, 0x1, 0x15, 0x15, 0xFF, 0x96, 0x0, 0x0, 0x0, 0x8, 0x87, 0x0, 0x0, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2D, 0x24, 0x28, 0x0, 0x0, 0x0, 0x5, 0x0, 0x11, 0x0, 0x6, 0x0, 0xB, 0x0, 0xD, 0x0, 0x7,
0x85, 0x0, 0x1, 0x5, 0x1, 0x15, 0x15, 0xFF, 0x96, 0x0, 0x0, 0x0, 0x8, 0x87, 0x0, 0x0, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2D, 0x24, 0x28, 0x0, 0x0, 0x0, 0x5, 0x0, 0x11, 0x0, 0x6, 0x0, 0xB, 0x0, 0xD, 0x0, 0x7,
0x85, 0x0, 0x1, 0x5, 0x1, 0x15, 0x15, 0xFF, 0x96, 0x0, 0x0, 0x0, 0x8, 0x87, 0x0, 0x0, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2D, 0x24, 0x28, 0x0, 0x0, 0x0, 0x5, 0x0, 0x11, 0x0, 0x6, 0x0, 0xB, 0x0, 0xD, 0x0, 0x7,
0x85, 0x0, 0x1, 0x5, 0x1, 0x15, 0x15, 0xFF, 0x96, 0x0, 0x0, 0x0, 0x8, 0x87, 0x0, 0x0, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2D, 0x24, 0x28, 0x0, 0x0, 0x0, 0x5, 0x0, 0x11, 0x0, 0x6, 0x0, 0xB, 0x0, 0xD, 0x0, 0x7,
// 6 trainer names
0x87, 0x80, 0x82, 0x8A, 0x84, 0x91, 0x50, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
// 6 nicknames
0x8F, 0x88, 0x83, 0x86, 0x84, 0x98, 0x50, 0x50, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
// 2 useless bytes??
0x00, 0x00, 0x00}; */
/*
const uint8_t DATA_BLOCK_GEN_II[PLAYER_LENGTH_GEN_II] = {
0x80, 0x91, 0x83, 0x94, 0x88, 0x8D, 0x8E, 0x50, 0x00, 0x00, 0x00, // name
0x1, 0x5C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // number of pokemon in party (0x00), pokemon ID (0x01 - 0x06), stop byte (0x07)
0xA9, 0xC8, //trainer ID
// 6 pokemon
//spc Held mv1 mv2 mv3 mv4 OT ID exp. HP_EV Attack_EV Def_EV Speed_EV Special_EV IV_Data m1pp m2pp m3pp m4pp frnd virus cght_data lvl sat. N/A curr_HP max_HP attack defence speed spcl_att spcl_def
0x5C, 0x00 ,0x5F, 0x7A, 0xAE, 0xD4, 0x8E, 0x47, 0x00 ,0x16, 0xDA, 0x07 ,0xB4, 0x08, 0x5F, 0x07, 0x8F, 0x09, 0xDF, 0x08, 0x6A, 0x88, 0x51, 0x14 ,0x1E, 0xA , 0x05, 0x9F, 0x00, 0xC3, 0x87, 0x14, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x18, 0x00, 0x16, 0x00, 0x29, 0x00, 0x2F, 0x00, 0x15,
0x46, 0x1A, 0x21, 0x00, 0x00, 0x00, 0xA9, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x1E, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xC5, 0x81, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15,
0x46, 0x1A, 0x21, 0x00, 0x00, 0x00, 0xA9, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x1E, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xC5, 0x81, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15,
0x46, 0x1A, 0x21, 0x00, 0x00, 0x00, 0xA9, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x1E, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xC5, 0x81, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15,
0x46, 0x1A, 0x21, 0x00, 0x00, 0x00, 0xA9, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x1E, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xC5, 0x81, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15,
0x46, 0x1A, 0x21, 0x00, 0x00, 0x00, 0xA9, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x1E, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xC5, 0x81, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15,
// 6 trainer names
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x50, 0x00, 0x00, 0x00,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
0xFF, 0x84, 0x83, 0x50, 0x80, 0x92, 0x87, 0x50, 0x89, 0x80, 0x82,
// 6 nicknames
0x8F, 0x88, 0x83, 0x86, 0x84, 0x98, 0x50, 0x50, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
0x8C, 0x80, 0x86, 0x88, 0x8A, 0x80, 0x91, 0x8F, 0x50, 0x50, 0x50,
// 2 useless bytes??
0x00, 0x00, 0x00};
*/

View File

@ -0,0 +1,8 @@
#ifndef PAYLOAD_BUILDER_H
#define PAYLOAD_BUILDER_H
#include "gb_rom_values/base_gb_rom_struct.h"
byte *generate_payload(GB_ROM curr_rom, bool debug);
#endif

View File

@ -1,18 +0,0 @@
#ifndef PAYLOAD_H
#define PAYLOAD_H
#include <tonc.h>
#include "output.h"
#define PAYLOAD_SIZE 637
#define NUM_PAYLOADS 1
struct PAYLOAD
{
public:
int language;
int version;
byte payload_array[PAYLOAD_SIZE];
};
#endif

View File

@ -3,7 +3,7 @@
#include <tonc.h>
#include "pokemon.h"
#include "payloads/eng_payloads.h"
#include "gb_rom_values/eng_gb_rom_values.h"
#define BOX_DATA_ARRAY_SIZE 0x462
@ -20,7 +20,7 @@ public:
void set_lang(int nLang);
int get_lang();
bool load_payload();
PAYLOAD curr_payload;
GB_ROM curr_rom;
void show_sprites();
Simplified_Pokemon simple_pkmn_array[30];
Simplified_Pokemon get_simple_pkmn(int index);

View File

@ -2,7 +2,7 @@
#define ROM_POINTERS_H
#include <tonc.h>
#include "rom_values/base_rom_struct.h"
#include "gba_rom_values/base_gba_rom_struct.h"
#define RUBY_ID 0x415856 // AXV
#define SAPPHIRE_ID 0x415850 // AXP

View File

@ -5,13 +5,12 @@
#include <string>
#include "gameboy_colour.h"
#include "pokemon_trade.h"
#include "output.h"
#include "script_array.h"
#include "debug_mode.h"
#include "interrupt.h"
#include "text_engine.h"
#include "global_frame_controller.h"
#include "payloads/base_payload_struct.h"
#include "gb_rom_values/eng_gb_rom_values.h"
#define TIMEOUT 2
#define TIMEOUT_ONE_LENGTH 1000000 // Maybe keep a 10:1 ratio between ONE and TWO?
@ -109,7 +108,7 @@ void setup()
}
}
byte handleIncomingByte(byte in, byte *box_data_storage, PAYLOAD *curr_payload, Simplified_Pokemon *curr_simple_array)
byte handleIncomingByte(byte in, byte *box_data_storage, byte *curr_payload, Simplified_Pokemon *curr_simple_array)
{
// TODO: Change to a switch statement
if (state == hs)
@ -234,7 +233,7 @@ byte handleIncomingByte(byte in, byte *box_data_storage, PAYLOAD *curr_payload,
else if (state == send_remove_array)
{
if (data_counter >= 39)
if (data_counter >= 29) // This assumes the preamble does not count towards the number of bytes sent over the cable
{
state = end2;
}
@ -245,7 +244,7 @@ byte handleIncomingByte(byte in, byte *box_data_storage, PAYLOAD *curr_payload,
return in;
}
int loop(byte *box_data_storage, PAYLOAD *curr_payload, Simplified_Pokemon *curr_simple_array)
int loop(byte *box_data_storage, byte *curr_payload, Simplified_Pokemon *curr_simple_array)
{
int counter = 0;
while (true)
@ -306,9 +305,9 @@ int loop(byte *box_data_storage, PAYLOAD *curr_payload, Simplified_Pokemon *curr
}
};
byte exchange_parties(byte curr_in, PAYLOAD *curr_payload)
byte exchange_parties(byte curr_in, byte *curr_payload)
{
int ret = curr_payload->payload_array[data_counter];
int ret = curr_payload[data_counter];
data_counter += 1;
return ret;
};

352
source/payload_builder.cpp Normal file
View File

@ -0,0 +1,352 @@
#include "payload_builder.h"
#include "gb_rom_values/base_gb_rom_struct.h"
#include "gb_rom_values/eng_gb_rom_values.h"
#include "debug_mode.h"
#include <iostream>
#include <fstream>
#include <iomanip>
byte payload_storage[674] = {};
byte *generate_payload(GB_ROM curr_rom, bool debug)
{
/* 10 RNG bytes
8 Preamble bytes
418 / 441 Party bytes
7 Preamble bytes
194 Patch list bytes (last 2 are unused)
637 / 662 total bytes
*/
// RNG Seed:
// at 0x00, 0x0A in length
// Does not need to be set
// Preamble
// At 0x0A, 0x08 in length
// Must be filled with 0xFD
for (int i = 0; i < 8; i++)
{
payload_storage[0x0A + i] = 0xFD;
}
// Rival name
// At 0x12, 0x0B in length
// Set to stored name
for (int i = 0; i < 11; i++)
{
payload_storage[0x12 + i] = curr_rom.custom_name[i];
}
// Number of Pokemon
// At 0x1D, 0x01 in length
// Does not need to be set
payload_storage[0x1D] = 0x06;
// Pokemon list
// At 0x1E, can be up to 0x1A2 / 0x1B9 bytes in length.
// Calculate the number of Pokemon names that need to be printed,
// and add them to the list. Then terminate the list.
int distance = curr_rom.stack_overwrite_location - curr_rom.print_string_start;
distance /= 20; // Automatically truncated, so it won't overshoot
for (int i = 0; i < distance; i++)
{
payload_storage[0x1E + i] = curr_rom.short_pkmn_name;
}
payload_storage[0x1E + distance] = curr_rom.pointer_pkmn_name;
payload_storage[0x1E + distance + 1] = 0xFF;
// Patchlist preamble
// At 0x1B4 / 0x1D7, 0x07 in length
// Set as five 0xFD and two 0xFF
for (int i = 0; i < 7; i++)
{
payload_storage[0x1B4 + i] = (i < 5 ? 0xFD : 0xFF);
}
// Set the entrance vector
payload_storage[curr_rom.enter_vector_destination] = 0xC3;
payload_storage[curr_rom.enter_vector_destination + 1] = curr_rom.enter_vector_location & 0xFF;
payload_storage[curr_rom.enter_vector_destination + 2] = (curr_rom.enter_vector_location >> 8) & 0xFF;
// Patchlist
// At 0x1BB / 0x1DE, 0xC2 in length (0xC4, but the last 2 are unused)
// Fill with custom code
int offset = 0x1BB;
/* Write transferring message to screen: */
// call ClearScreen
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom.clearScreen >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.clearScreen >> 8) & 0xFF;
// ld hl, [upper left textbox corner in VRAM]
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.textBoarderUppLeft >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.textBoarderUppLeft >> 8) & 0xFF;
// ld b, 3 [height]
payload_storage[offset++] = 0x06;
payload_storage[offset++] = (curr_rom.textBoarderWidth >> 0) & 0xFF;
// ld c, 14 [width]
payload_storage[offset++] = 0x0E;
payload_storage[offset++] = (curr_rom.textBoarderHeight >> 0) & 0xFF;
// call CableClub_TextBoxBoarder
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom.CableClub_TextBoxBoarder >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.CableClub_TextBoxBoarder >> 8) & 0xFF;
// ld hl, [transfer string location]
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.transferStringLocation >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.transferStringLocation >> 8) & 0xFF;
// ld de, TransferWaitString
payload_storage[offset++] = 0x11;
payload_storage[offset++] = (curr_rom.transferWaitString >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.transferWaitString >> 8) & 0xFF;
// call PlaceString
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom.placeString >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.placeString >> 8) & 0xFF;
/* Transfer box data: */
// ld hl, hSerialConnectionStatus
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.hSerialConnectionStatus >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.hSerialConnectionStatus >> 8) & 0xFF;
// ld [hl], 0x01 [Make sure GB is the slave, master if debug]
payload_storage[offset++] = 0x36;
payload_storage[offset++] = (debug ? 0x02 : 0x01);
// ld hl, (wBoxDataStart - 1) [data to send]
payload_storage[offset++] = 0x21;
payload_storage[offset++] = ((curr_rom.wBoxDataStart - 1) >> 0) & 0xFF;
payload_storage[offset++] = ((curr_rom.wBoxDataStart - 1) >> 8) & 0xFF;
// ld [hl], 0xFD [set the start of the data to 0xFD so Serial_ExchangeBytes is happy]
payload_storage[offset++] = 0x36;
payload_storage[offset++] = 0xFD;
// ld de, (wBoxDataStart - 3) [location to put stored data]
payload_storage[offset++] = 0x11;
payload_storage[offset++] = ((curr_rom.wBoxDataStart - (debug ? 2 : 3)) >> 0) & 0xFF;
payload_storage[offset++] = ((curr_rom.wBoxDataStart - (debug ? 2 : 3)) >> 8) & 0xFF;
// ld bc, (wBoxDataEnd - wBoxDataStart) + 2
payload_storage[offset++] = 0x01;
payload_storage[offset++] = (((curr_rom.wBoxDataEnd - curr_rom.wBoxDataStart) + 2) >> 0) & 0xFF;
payload_storage[offset++] = (((curr_rom.wBoxDataEnd - curr_rom.wBoxDataStart) + 2) >> 8) & 0xFF;
// call Serial_ExchangeBytes [Send the box data]
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom.Serial_ExchangeBytes >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.Serial_ExchangeBytes >> 8) & 0xFF;
/* Recieve the Pokemon to remove */
// ld hl, hSerialConnectionStatus
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.hSerialConnectionStatus >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.hSerialConnectionStatus >> 8) & 0xFF;
// ld [hl], 0x01 [Make sure GB is the slave, master if debug]
payload_storage[offset++] = 0x36;
payload_storage[offset++] = (debug ? 0x02 : 0x01);
// ld hl, 0xC613 [data to send, garbage data]
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.garbageDataLocation >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.garbageDataLocation >> 8) & 0xFF;
// ld de, 0xC651 [data to recieve]
payload_storage[offset++] = 0x11;
payload_storage[offset++] = (curr_rom.pkmnTransferArray >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.pkmnTransferArray >> 8) & 0xFF;
// ld bc, 0x0028 [size of data]
payload_storage[offset++] = 0x01;
payload_storage[offset++] = 0x28;
payload_storage[offset++] = 0x00;
// call Serial_ExchangeBytes [Recieve the removal array]
if (debug)
{
offset += 3; // Don't add in the Serial_ExchangeBytes call if in debug
}
else
{
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom.Serial_ExchangeBytes >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.Serial_ExchangeBytes >> 8) & 0xFF;
}
/* Remove the transfered Pokemon */
// ld hl, wRemoveMonFromBox
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.wRemoveMonFromBox >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.wRemoveMonFromBox >> 8) & 0xFF;
// ld [hl], [!= 0x00 specifies the current box]
payload_storage[offset++] = 0x36;
payload_storage[offset++] = 0x01;
// ld a, [arrayCounter]
payload_storage[offset++] = 0xFA;
payload_storage[offset++] = (curr_rom.arrayCounter >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.arrayCounter >> 8) & 0xFF;
// ld e, a
payload_storage[offset++] = 0x5F;
// ld d, 0x00
payload_storage[offset++] = 0x16;
payload_storage[offset++] = 0x00;
// ld hl, [removalArray]
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.pkmnTransferArray >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.pkmnTransferArray >> 8) & 0xFF;
// add hl, de
payload_storage[offset++] = 0x19;
// inc a
payload_storage[offset++] = 0x3C;
// ld [arrayCounter], a
payload_storage[offset++] = 0xEA;
payload_storage[offset++] = (curr_rom.arrayCounter >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.arrayCounter >> 8) & 0xFF;
// ld a, [wBoxCount]
payload_storage[offset++] = 0xFA;
payload_storage[offset++] = (curr_rom.wBoxCount >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.wBoxCount >> 8) & 0xFF;
// ld b, a
payload_storage[offset++] = 0x47;
// ld a, [hl]
payload_storage[offset++] = 0x2A;
// cp a, 0xFF
payload_storage[offset++] = 0xFE;
payload_storage[offset++] = 0xFF;
// jr z, 12
payload_storage[offset++] = 0x28;
payload_storage[offset++] = 0x0C;
// cp a, b
payload_storage[offset++] = 0xB8;
// jr nc, -26
payload_storage[offset++] = 0x30;
payload_storage[offset++] = 0xE6;
// ld hl, wWhichPokemon
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.wWhichPokemon >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.wWhichPokemon >> 8) & 0xFF;
// ld [hl], a
payload_storage[offset++] = 0x77;
// call _RemovePokemon
if (DONT_REMOVE_PKMN)
{
offset += 3;
}
else
{
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom._RemovePokemon >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom._RemovePokemon >> 8) & 0xFF;
}
// jr, -35
payload_storage[offset++] = 0x18;
payload_storage[offset++] = 0xDD;
/* Save the current box */
// ld hl, SaveSAVtoSRAM1
payload_storage[offset++] = 0x21;
payload_storage[offset++] = (curr_rom.SaveSAVtoSRAM1 >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.SaveSAVtoSRAM1 >> 8) & 0xFF;
// ld b, 0x1C [memory bank of SaveSAVtoSRAM1]
payload_storage[offset++] = 0x06;
payload_storage[offset++] = (curr_rom.SaveSAVtoSRAM1_memBank >> 0) & 0xFF;
// call Bankswitch [which will jump to what's loaded in HL]
payload_storage[offset++] = 0xCD;
payload_storage[offset++] = (curr_rom.Bankswitch >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.Bankswitch >> 8) & 0xFF;
// jp SoftReset
payload_storage[offset++] = 0xC3;
payload_storage[offset++] = (curr_rom.SoftReset >> 0) & 0xFF;
payload_storage[offset++] = (curr_rom.SoftReset >> 8) & 0xFF;
// 1 byte to store the current array counter
// $C650
offset = 0x1BB + (0xC650 - curr_rom.enter_vector_location);
payload_storage[offset++] = 0x00;
// 40 byte storage for list of Pokemon to remove
// $C651
for (int i = 0; i < 40; i++)
{
if (debug)
{
payload_storage[offset++] = (i < 30 ? (29 - i) : 0xFF);
}
else
{
payload_storage[offset++] = (i < 30 ? 0xFD : 0xFF);
}
}
// permanent array terminator, just in case
// $C679
payload_storage[offset++] = 0xFF;
// TransferWaitString
// $C67A
for (int i = 0; i < 30; i++)
{
payload_storage[offset++] = curr_rom.transferString[i];
}
// 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,
// which is the rival's name. This code fixes the stack and jumps to the patchlist, which is where
// our final code is.
return payload_storage;
};
int main()
{
freopen("test_payload.txt", "w", stdout);
std::cout << std::endl;
byte *payload = generate_payload(ENG_RED_BLUE, true);
for (int i = 0; i < 637; i++)
{
std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned int)payload[i] << ", ";
if (i % 0x10 == 0xF)
{
std::cout << std::endl
<< "# 0x" << std::hex << i + 1 << std::endl;
}
}
return 0;
}

View File

@ -4,11 +4,12 @@
#include "flash_mem.h"
#include "debug_mode.h"
#include "mystery_gift_injector.h"
#include "payloads/base_payload_struct.h"
#include "gb_rom_values/base_gb_rom_struct.h"
#include "sprite_data.h"
#include "box_menu.h"
#include "payload_builder.h"
const PAYLOAD *list_of_payloads[NUM_PAYLOADS] = {
const GB_ROM *list_of_gb_roms[NUM_PAYLOADS] = {
&ENG_RED_BLUE
};
@ -98,13 +99,13 @@ void Pokemon_Party::start_link()
else
{
setup();
last_error = loop(&box_data_array[0], &curr_payload, simple_pkmn_array);
last_error = loop(&box_data_array[0], generate_payload(curr_rom, false), simple_pkmn_array);
}
}
void Pokemon_Party::continue_link(){
if (!IGNORE_LINK_CABLE){
last_error = loop(&box_data_array[0], &curr_payload, simple_pkmn_array);
last_error = loop(&box_data_array[0], generate_payload(curr_rom, false), simple_pkmn_array);
}
}
@ -154,10 +155,10 @@ int Pokemon_Party::get_lang(){
bool Pokemon_Party::load_payload(){
for (int i = 0; i < NUM_PAYLOADS; i++)
{
if (lang == list_of_payloads[i]->language &&
game == list_of_payloads[i]->version)
if (lang == list_of_gb_roms[i]->language &&
game == list_of_gb_roms[i]->version)
{
curr_payload = *list_of_payloads[i];
curr_rom = *list_of_gb_roms[i];
return true;
}
}

View File

@ -2,7 +2,7 @@
#include "mystery_gift_builder.h"
#include "pokemon_party.h"
#include "pokemon_data.h"
#include "rom_values/eng_rom_values.h"
#include "gba_rom_values/eng_gba_rom_values.h"
rom_data::rom_data() {}
bool rom_data::load_rom()

80
source/test_payload.txt Normal file
View File

@ -0,0 +1,80 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xD6, 0xC5, 0x00, 0x00, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
# 0x10
0xFD, 0xFD, 0x85, 0x84, 0x8D, 0x8D, 0x84, 0x8B, 0x50, 0x50, 0x50, 0x50, 0x50, 0x06, 0xE3, 0xE3,
# 0x20
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x30
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x40
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x50
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x60
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x70
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x80
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x90
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0xA0
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0xB0
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0xC0
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0xD0
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0xE0
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0xF0
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x100
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x110
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x120
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x130
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x140
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x150
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x160
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
# 0x170
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xFC, 0xFF,
# 0x180
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
# 0x190
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
# 0x1A0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
# 0x1B0
0x00, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFF, 0xFF, 0xCD, 0x0F, 0x19, 0x21, 0x2E,
# 0x1C0
0xC4, 0x06, 0x03, 0x0E, 0x0E, 0xCD, 0xB3, 0x5A, 0x21, 0x43, 0xC4, 0x11, 0x7A, 0xC6, 0xCD, 0x55,
# 0x1D0
0x19, 0x21, 0xAA, 0xFF, 0x36, 0x02, 0x21, 0x7F, 0xDA, 0x36, 0xFD, 0x11, 0x7E, 0xDA, 0x01, 0x64,
# 0x1E0
0x04, 0xCD, 0x6F, 0x21, 0x21, 0xAA, 0xFF, 0x36, 0x02, 0x21, 0x16, 0x03, 0x11, 0x51, 0xC6, 0x01,
# 0x1F0
0x1E, 0x00, 0x00, 0x00, 0x00, 0x21, 0x95, 0xCF, 0x36, 0x01, 0xFA, 0x50, 0xC6, 0x5F, 0x16, 0x00,
# 0x200
0x21, 0x51, 0xC6, 0x19, 0x3C, 0xEA, 0x50, 0xC6, 0xFA, 0x80, 0xDA, 0x47, 0x2A, 0xFE, 0xFF, 0x28,
# 0x210
0x0C, 0xB8, 0x30, 0xE6, 0x21, 0x92, 0xCF, 0x77, 0xCD, 0x68, 0x7B, 0x18, 0xDD, 0x21, 0xE2, 0x77,
# 0x220
0x06, 0x1C, 0xCD, 0xD6, 0x35, 0xC3, 0x49, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
# 0x230
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14,
# 0x240
0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
# 0x250
0x03, 0x02, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x93,
# 0x260
0x91, 0x80, 0x8D, 0x92, 0x85, 0x84, 0x91, 0x91, 0x88, 0x8D, 0x86, 0xF2, 0xF2, 0x4E, 0x7F, 0x8F,
# 0x270
0x8B, 0x84, 0x80, 0x92, 0x84, 0x7F, 0x96, 0x80, 0x88, 0x93, 0xE7, 0x7F, 0x50,