mirror of
https://github.com/GearsProgress/Poke_Transporter_GB.git
synced 2026-03-21 17:34:42 -05:00
Back to TONC
This commit is contained in:
parent
973b24f538
commit
19f346ba42
6
Makefile
6
Makefile
|
|
@ -11,6 +11,8 @@ include $(DEVKITARM)/gba_rules
|
|||
#---------------------------------------------------------------------------------
|
||||
# the LIBGBA path is defined in gba_rules, but we have to define LIBTONC ourselves
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBTONC := $(DEVKITPRO)/libtonc
|
||||
LIBUGBA := $(DEVKITPRO)/libugba
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
|
|
@ -51,7 +53,7 @@ LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
|||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lmm -libgba
|
||||
LIBS := -ltonc -lugba
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
|
@ -59,7 +61,7 @@ LIBS := -lmm -libgba
|
|||
# include and lib.
|
||||
# the LIBGBA path should remain in this list if you want to use maxmod
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBGBA)
|
||||
LIBDIRS := $(LIBGBA) $(LIBTONC) $(LIBUGBA)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
|
|
|
|||
237
include/LinkSPI.h
Normal file
237
include/LinkSPI.h
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#ifndef LINK_SPI_H
|
||||
#define LINK_SPI_H
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// An SPI handler for the Link Port (Normal Mode, 32bits).
|
||||
// --------------------------------------------------------------------------
|
||||
// Usage:
|
||||
// - 1) Include this header in your main.cpp file and add:
|
||||
// LinkSPI* linkSPI = new LinkSPI();
|
||||
// - 2) (Optional) Add the interrupt service routines:
|
||||
// irq_init(NULL);
|
||||
// irq_add(II_SERIAL, LINK_SPI_ISR_SERIAL);
|
||||
// // (this is only required for `transferAsync`)
|
||||
// - 3) Initialize the library with:
|
||||
// linkSPI->activate(LinkSPI::Mode::MASTER_256KBPS);
|
||||
// // (use LinkSPI::Mode::SLAVE on the other end)
|
||||
// - 4) Exchange 32-bit data with the other end:
|
||||
// u8 data = linkSPI->transfer(0x1234);
|
||||
// // (this blocks the console indefinitely)
|
||||
// - 5) Exchange data with a cancellation callback:
|
||||
// u8 data = linkSPI->transfer(0x1234, []() {
|
||||
// u16 keys = ~REG_KEYS & KEY_ANY;
|
||||
// return keys & KEY_START;
|
||||
// });
|
||||
// - 6) Exchange data asynchronously:
|
||||
// linkSPI->transferAsync(0x1234);
|
||||
// // ...
|
||||
// if (linkSPI->getAsyncState() == LinkSPI::AsyncState::READY) {
|
||||
// u8 data = linkSPI->getAsyncData();
|
||||
// // ...
|
||||
// }
|
||||
// --------------------------------------------------------------------------
|
||||
// considerations:
|
||||
// - when using Normal Mode between two GBAs, use a GBC Link Cable!
|
||||
// - only use the 2Mbps mode with custom hardware (very short wires)!
|
||||
// - don't send 0xFFFFFFFF, it's reserved for errors!
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include <tonc_core.h>
|
||||
|
||||
#define LINK_SPI_NO_DATA 0xFF
|
||||
#define LINK_SPI_SIOCNT_NORMAL 0
|
||||
#define LINK_SPI_BIT_CLOCK 0
|
||||
#define LINK_SPI_BIT_CLOCK_SPEED 1
|
||||
#define LINK_SPI_BIT_SI 2
|
||||
#define LINK_SPI_BIT_SO 3
|
||||
#define LINK_SPI_BIT_START 7
|
||||
#define LINK_SPI_BIT_LENGTH 12
|
||||
#define LINK_SPI_BIT_IRQ 14
|
||||
#define LINK_SPI_BIT_GENERAL_PURPOSE_LOW 14
|
||||
#define LINK_SPI_BIT_GENERAL_PURPOSE_HIGH 15
|
||||
#define LINK_SPI_SET_HIGH(REG, BIT) REG |= 1 << BIT
|
||||
#define LINK_SPI_SET_LOW(REG, BIT) REG &= ~(1 << BIT)
|
||||
|
||||
static volatile char LINK_SPI_VERSION[] = "LinkSPI/v5.0.2";
|
||||
|
||||
class LinkSPI {
|
||||
public:
|
||||
enum Mode { SLAVE, MASTER_256KBPS, MASTER_2MBPS };
|
||||
enum AsyncState { IDLE, WAITING, READY };
|
||||
|
||||
bool isActive() { return isEnabled; }
|
||||
|
||||
void activate(Mode mode) {
|
||||
this->mode = mode;
|
||||
this->waitMode = false;
|
||||
this->asyncState = IDLE;
|
||||
this->asyncData = 0;
|
||||
|
||||
setNormalMode();
|
||||
set32BitPackets();
|
||||
setInterruptsOff();
|
||||
disableTransfer();
|
||||
|
||||
if (mode == SLAVE)
|
||||
setSlaveMode();
|
||||
else {
|
||||
setMasterMode();
|
||||
|
||||
if (mode == MASTER_256KBPS)
|
||||
set256KbpsSpeed();
|
||||
else if (mode == MASTER_2MBPS)
|
||||
set2MbpsSpeed();
|
||||
}
|
||||
|
||||
isEnabled = true;
|
||||
}
|
||||
|
||||
void deactivate() {
|
||||
isEnabled = false;
|
||||
stopTransfer();
|
||||
disableTransfer();
|
||||
setGeneralPurposeMode();
|
||||
|
||||
mode = SLAVE;
|
||||
waitMode = false;
|
||||
asyncState = IDLE;
|
||||
asyncData = 0;
|
||||
}
|
||||
|
||||
u8 transfer(u8 data) {
|
||||
return transfer(data, []() { return false; });
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
u8 transfer(u8 data,
|
||||
F cancel,
|
||||
bool _async = false,
|
||||
bool _customAck = false) {
|
||||
if (asyncState != IDLE)
|
||||
return LINK_SPI_NO_DATA;
|
||||
|
||||
setData(data);
|
||||
|
||||
if (_async) {
|
||||
asyncState = WAITING;
|
||||
setInterruptsOn();
|
||||
} else {
|
||||
setInterruptsOff();
|
||||
}
|
||||
|
||||
enableTransfer();
|
||||
|
||||
while (isMaster() && waitMode && !isSlaveReady())
|
||||
if (cancel()) {
|
||||
disableTransfer();
|
||||
setInterruptsOff();
|
||||
asyncState = IDLE;
|
||||
return LINK_SPI_NO_DATA;
|
||||
}
|
||||
|
||||
startTransfer();
|
||||
|
||||
if (_async)
|
||||
return LINK_SPI_NO_DATA;
|
||||
|
||||
while (!isReady())
|
||||
if (cancel()) {
|
||||
stopTransfer();
|
||||
disableTransfer();
|
||||
return LINK_SPI_NO_DATA;
|
||||
}
|
||||
|
||||
if (!_customAck)
|
||||
disableTransfer();
|
||||
|
||||
return getData();
|
||||
}
|
||||
|
||||
void transferAsync(u8 data) {
|
||||
transfer(
|
||||
data, []() { return false; }, true);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void transferAsync(u8 data, F cancel) {
|
||||
transfer(data, cancel, true);
|
||||
}
|
||||
|
||||
u8 getAsyncData() {
|
||||
if (asyncState != READY)
|
||||
return LINK_SPI_NO_DATA;
|
||||
|
||||
u8 data = asyncData;
|
||||
asyncState = IDLE;
|
||||
return data;
|
||||
}
|
||||
|
||||
Mode getMode() { return mode; }
|
||||
void setWaitModeActive(bool isActive) { waitMode = isActive; }
|
||||
bool isWaitModeActive() { return waitMode; }
|
||||
AsyncState getAsyncState() { return asyncState; }
|
||||
|
||||
void _onSerial(bool _customAck = false) {
|
||||
if (!isEnabled || asyncState != WAITING)
|
||||
return;
|
||||
|
||||
if (!_customAck)
|
||||
disableTransfer();
|
||||
|
||||
setInterruptsOff();
|
||||
asyncState = READY;
|
||||
asyncData = getData();
|
||||
}
|
||||
|
||||
void _setSOHigh() { setBitHigh(LINK_SPI_BIT_SO); }
|
||||
void _setSOLow() { setBitLow(LINK_SPI_BIT_SO); }
|
||||
bool _isSIHigh() { return isBitHigh(LINK_SPI_BIT_SI); }
|
||||
|
||||
private:
|
||||
Mode mode = Mode::SLAVE;
|
||||
bool waitMode = false;
|
||||
AsyncState asyncState = IDLE;
|
||||
u8 asyncData = 0;
|
||||
bool isEnabled = false;
|
||||
|
||||
void setNormalMode() {
|
||||
LINK_SPI_SET_LOW(REG_RCNT, LINK_SPI_BIT_GENERAL_PURPOSE_HIGH);
|
||||
REG_SIOCNT = LINK_SPI_SIOCNT_NORMAL;
|
||||
}
|
||||
|
||||
void setGeneralPurposeMode() {
|
||||
LINK_SPI_SET_LOW(REG_RCNT, LINK_SPI_BIT_GENERAL_PURPOSE_LOW);
|
||||
LINK_SPI_SET_HIGH(REG_RCNT, LINK_SPI_BIT_GENERAL_PURPOSE_HIGH);
|
||||
}
|
||||
|
||||
void setData(u8 data) { REG_SIODATA8 = data; }
|
||||
u8 getData() { return REG_SIODATA8; }
|
||||
|
||||
void enableTransfer() { _setSOLow(); }
|
||||
void disableTransfer() { _setSOHigh(); }
|
||||
void startTransfer() { setBitHigh(LINK_SPI_BIT_START); }
|
||||
void stopTransfer() { setBitLow(LINK_SPI_BIT_START); }
|
||||
bool isReady() { return !isBitHigh(LINK_SPI_BIT_START); }
|
||||
bool isSlaveReady() { return !_isSIHigh(); }
|
||||
|
||||
void set32BitPackets() { setBitLow(LINK_SPI_BIT_LENGTH); }
|
||||
void setMasterMode() { setBitHigh(LINK_SPI_BIT_CLOCK); }
|
||||
void setSlaveMode() { setBitLow(LINK_SPI_BIT_CLOCK); }
|
||||
void set256KbpsSpeed() { setBitLow(LINK_SPI_BIT_CLOCK_SPEED); }
|
||||
void set2MbpsSpeed() { setBitHigh(LINK_SPI_BIT_CLOCK_SPEED); }
|
||||
void setInterruptsOn() { setBitHigh(LINK_SPI_BIT_IRQ); }
|
||||
void setInterruptsOff() { setBitLow(LINK_SPI_BIT_IRQ); }
|
||||
|
||||
bool isMaster() { return mode != SLAVE; }
|
||||
bool isBitHigh(u8 bit) { return (REG_SIOCNT >> bit) & 1; }
|
||||
void setBitHigh(u8 bit) { LINK_SPI_SET_HIGH(REG_SIOCNT, bit); }
|
||||
void setBitLow(u8 bit) { LINK_SPI_SET_LOW(REG_SIOCNT, bit); }
|
||||
};
|
||||
|
||||
extern LinkSPI* linkSPI;
|
||||
|
||||
inline void LINK_SPI_ISR_SERIAL() {
|
||||
linkSPI->_onSerial();
|
||||
}
|
||||
|
||||
#endif // LINK_SPI_H
|
||||
81
include/gb_link.h
Normal file
81
include/gb_link.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#ifndef GB_LINK_H
|
||||
|
||||
/*
|
||||
typedef enum {
|
||||
FIRST_COMMUNICATION,
|
||||
POST_SAVE,
|
||||
SELECT_ROOM,
|
||||
TABLE_INTERACT,
|
||||
TEN_ZEROS_ONE,
|
||||
SEVENTY_SIX,
|
||||
TEN_ZEROS_TWO,
|
||||
FINAL_DESTINATION,
|
||||
SEND_POKEMON_DATA
|
||||
} connection_state;
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NOT_CONNECTED,
|
||||
CONNECTED,
|
||||
TRADE_CENTRE,
|
||||
COLOSSEUM
|
||||
} connection_state_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INIT,
|
||||
READY_TO_GO,
|
||||
SEEN_FIRST_WAIT,
|
||||
SENDING_RANDOM_DATA,
|
||||
WAITING_TO_SEND_DATA,
|
||||
SENDING_DATA,
|
||||
SENDING_PATCH_DATA,
|
||||
MIMIC,
|
||||
TRADE_PENDING,
|
||||
TRADE_CONFIRMATION,
|
||||
DONE
|
||||
} trade_centre_state_gen_II_t;
|
||||
|
||||
#define PKMN_BLANK 0x00
|
||||
|
||||
#define ITEM_1_HIGHLIGHTED 0xD0
|
||||
#define ITEM_2_HIGHLIGHTED 0xD1
|
||||
#define ITEM_3_HIGHLIGHTED 0xD2
|
||||
#define ITEM_1_SELECTED 0xD4
|
||||
#define ITEM_2_SELECTED 0xD5
|
||||
#define ITEM_2_SELECTED 0xD5
|
||||
#define ITEM_3_SELECTED 0xD6
|
||||
|
||||
#define GEN_II_CABLE_TRADE_CENTER 0xD1
|
||||
#define GEN_II_CABLE_CLUB_COLOSSEUM 0xD2
|
||||
|
||||
#define PKMN_MASTER 0x01
|
||||
#define PKMN_SLAVE 0x02
|
||||
#define PKMN_MASTER_GEN_III 0x8FFF //??
|
||||
#define PKMN_SLAVE_GEN_III 0xB9A0 //??
|
||||
#define PKMN_CONNECTED_I 0x60
|
||||
#define PKMN_CONNECTED_II 0x61
|
||||
#define PKMN_WAIT 0x7F
|
||||
|
||||
#define PKMN_ACTION 0x60
|
||||
|
||||
#define PKMN_TRADE_CENTRE ITEM_1_SELECTED
|
||||
#define PKMN_COLOSSEUM ITEM_2_SELECTED
|
||||
#define PKMN_BREAK_LINK ITEM_3_SELECTED
|
||||
|
||||
#define TRADE_CENTRE_WAIT 0xFD
|
||||
|
||||
#define PLAYER_LENGTH_GEN_II 444 //11+8+2+(48*6)+(11*6)+(11*6)+3
|
||||
|
||||
|
||||
#define GB_LINK_H
|
||||
#include <tonc.h>
|
||||
|
||||
void log(std::string text);
|
||||
void wait(u32 verticalLines);
|
||||
inline void VBLANK() {}
|
||||
void init();
|
||||
int start_link();
|
||||
|
||||
#endif
|
||||
30
include/interrupt.h
Normal file
30
include/interrupt.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef INTERRUPT_H
|
||||
#define INTERRUPT_H
|
||||
|
||||
typedef enum {
|
||||
INTR_VBLANK = 0,
|
||||
INTR_HBLANK = 1,
|
||||
INTR_VCOUNT = 2,
|
||||
INTR_TIMER0 = 3,
|
||||
INTR_TIMER1 = 4,
|
||||
INTR_TIMER2 = 5,
|
||||
INTR_TIMER3 = 6,
|
||||
INTR_SERIAL = 7,
|
||||
INTR_DMA0 = 8,
|
||||
INTR_DMA1 = 9,
|
||||
INTR_DMA2 = 10,
|
||||
INTR_DMA3 = 11,
|
||||
INTR_KEYPAD = 12,
|
||||
INTR_GAMEPAK = 13,
|
||||
INTR_NUMBER
|
||||
} interrupt_index;
|
||||
|
||||
typedef void (*interrupt_vector)(void);
|
||||
|
||||
void interrupt_init(void);
|
||||
void interrupt_set_handler(interrupt_index index, interrupt_vector function);
|
||||
void interrupt_enable(interrupt_index index);
|
||||
void interrupt_disable(interrupt_index index);
|
||||
void interrupt_set_reference_vcount(unsigned long y);
|
||||
|
||||
#endif // INTERRUPT_H
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef MIRROR_H
|
||||
#define MIRROR_H
|
||||
#include <gba.h>
|
||||
#include <tonc.h>
|
||||
|
||||
|
||||
#define MEM_CRAM 0x0E000000 //!< Cart RAM
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <gba.h>
|
||||
#include <tonc.h>
|
||||
#include <string>
|
||||
#include "mirror.h"
|
||||
#include "gba_flash.h"
|
||||
|
|
|
|||
264
source/gb_link.cpp
Normal file
264
source/gb_link.cpp
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
#include <string>
|
||||
#include <tonc.h>
|
||||
|
||||
#include "gb_link.h"
|
||||
#include "LinkSPI.h"
|
||||
#include "debug.h"
|
||||
|
||||
// (1) Create a LinkSPI instance
|
||||
LinkSPI *linkSPI = new LinkSPI();
|
||||
|
||||
vu32 trainerData[111] = {0x8A918892, 0x50505050, 0x50505006, 0x9B9B9B9B, 0x9B9BFF25, 0xDA9B0021, 0x2B000025, 0xDA000087, 0x00000000, 0x00000000, 0x00007221, 0x231E0000, 0x46008581, 0x05000000, 0x13001300, 0x0A000900, 0x0B000B00, 0x0A9B0021, 0x2B000025, 0xDA000087, 0x00000000, 0x00000000, 0x00007221, 0x231E0000, 0x46008581, 0x05000000, 0x13001300, 0x0A000900, 0x0B000B00, 0x0A9B0021, 0x2B000025, 0xDA000087, 0x00000000, 0x00000000, 0x00007221, 0x231E0000, 0x46008581, 0x05000000, 0x13001300, 0x0A000900, 0x0B000B00, 0x0A9B0021, 0x2B000025, 0xDA000087, 0x00000000, 0x00000000, 0x00007221, 0x231E0000, 0x46008581, 0x05000000, 0x13001300, 0x0A000900, 0x0B000B00, 0x0A9B0021, 0x2B000025, 0xDA000087, 0x00000000, 0x00000000, 0x00007221, 0x231E0000, 0x46008581, 0x05000000, 0x13001300, 0x0A000900, 0x0B000B00, 0x0A9B0021, 0x2B000025, 0xDA000087, 0x00000000, 0x00000000, 0x00007221, 0x231E0000, 0x46008581, 0x05000000, 0x13001300, 0x0A000900, 0x0B000B00, 0x0A8A9188, 0x92505050, 0x50505050, 0x8A918892, 0x50505050, 0x5050508A, 0x91889250, 0x50505050, 0x50508A91, 0x88925050, 0x50505050, 0x508A9188, 0x92505050, 0x50505050, 0x8A918892, 0x50505050, 0x50505082, 0x988D8380, 0x9094888B, 0x50508298, 0x8D838090, 0x94888B50, 0x5082988D, 0x83809094, 0x888B5050, 0x82988D83, 0x80909488, 0x8B505082, 0x988D8380, 0x9094888B, 0x50508298, 0x8D838090, 0x94888B50, 0x50000000};
|
||||
|
||||
void init()
|
||||
{
|
||||
REG_DISPCNT = DCNT_MODE0 | DCNT_BG0;
|
||||
tte_init_se_default(0, BG_CBB(0) | BG_SBB(31));
|
||||
|
||||
// (2) Add the interrupt service routines
|
||||
}
|
||||
|
||||
std::string convertToString(char *a, int size)
|
||||
{
|
||||
int i;
|
||||
std::string s = "";
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
s = s + a[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int start_link()
|
||||
{
|
||||
init();
|
||||
|
||||
u8 SPIout = 0x00; // What the GBA is sending out to the GBC
|
||||
u8 SPIin = 0x00; // What the GBA is receiving from the GBC
|
||||
std::string outputArr[16] = {};
|
||||
u32 mode = 0; // Trick game into entering trading room
|
||||
bool firstTransfer = false;
|
||||
u32 index = 0;
|
||||
std::string bigOut = "";
|
||||
// connection_state linkCable = POST_SAVE;
|
||||
|
||||
connection_state_t connection_state = NOT_CONNECTED;
|
||||
trade_centre_state_gen_II_t trade_centre_state_gen_II = INIT;
|
||||
int counter = 0;
|
||||
byte in;
|
||||
byte send = 0x16;
|
||||
const int MODE = 1; // mode=0 will transfer pokemon data from pokemon.h
|
||||
int trade_pokemon = -1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::string output = "";
|
||||
|
||||
u16 keys = ~REG_KEYS & KEY_ANY;
|
||||
|
||||
if (!linkSPI->isActive())
|
||||
{
|
||||
firstTransfer = true;
|
||||
linkSPI->activate(LinkSPI::Mode::SLAVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Title
|
||||
auto modeName =
|
||||
linkSPI->getMode() == LinkSPI::Mode::SLAVE ? "[slave]" : "[master]";
|
||||
output += std::string(modeName) + "\n";
|
||||
if (firstTransfer)
|
||||
{
|
||||
log(output + "Waiting for link cable...\nPress L and R to cancel");
|
||||
firstTransfer = false;
|
||||
}
|
||||
|
||||
// (4)/(5) Exchange 32-bit data with the other end
|
||||
SPIin = linkSPI->transfer(SPIout, []()
|
||||
{
|
||||
bool exit = false;
|
||||
u16 keys = ~REG_KEYS & KEY_ANY;
|
||||
if ((keys & KEY_L) && (keys & KEY_R)){
|
||||
exit = true;
|
||||
}
|
||||
return exit; });
|
||||
|
||||
in = SPIin;
|
||||
|
||||
byte send = 0x00;
|
||||
|
||||
switch(connection_state) {
|
||||
case NOT_CONNECTED:
|
||||
if(in == PKMN_MASTER)
|
||||
send = PKMN_SLAVE;
|
||||
else if(in == PKMN_BLANK)
|
||||
send = PKMN_BLANK;
|
||||
else if(in == PKMN_CONNECTED_II) {
|
||||
send = PKMN_CONNECTED_II;
|
||||
connection_state = CONNECTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTED:
|
||||
if(in == PKMN_CONNECTED_II) //acknowledge connection
|
||||
send = PKMN_CONNECTED_II;
|
||||
else if(in == GEN_II_CABLE_TRADE_CENTER){ //acknowledge trade center selection
|
||||
connection_state = TRADE_CENTRE;
|
||||
send = GEN_II_CABLE_TRADE_CENTER;
|
||||
}
|
||||
else if(in == GEN_II_CABLE_CLUB_COLOSSEUM){ //acknowledge colosseum selection
|
||||
connection_state = COLOSSEUM;
|
||||
send = GEN_II_CABLE_CLUB_COLOSSEUM;
|
||||
}
|
||||
else {
|
||||
send = in;
|
||||
}
|
||||
break;
|
||||
|
||||
case TRADE_CENTRE:
|
||||
if(trade_centre_state_gen_II == INIT && in == 0x00) {
|
||||
trade_centre_state_gen_II = READY_TO_GO;
|
||||
send = 0x00;
|
||||
} else if(trade_centre_state_gen_II == READY_TO_GO && in == 0xFD) {
|
||||
trade_centre_state_gen_II = SEEN_FIRST_WAIT;
|
||||
send = 0xFD;
|
||||
} else if(trade_centre_state_gen_II == SEEN_FIRST_WAIT && in != 0x70) {
|
||||
// random data of slave is ignored.
|
||||
send = in;
|
||||
trade_centre_state_gen_II = SENDING_RANDOM_DATA;
|
||||
} else if(trade_centre_state_gen_II == SENDING_RANDOM_DATA && in == 0xFD) {
|
||||
trade_centre_state_gen_II = WAITING_TO_SEND_DATA;
|
||||
send = 0xFD;
|
||||
} else if(trade_centre_state_gen_II == WAITING_TO_SEND_DATA && in != 0xFD) {
|
||||
counter = 0;
|
||||
// send first byte
|
||||
switch(MODE){
|
||||
case 0:
|
||||
//send = pgm_read_byte(&(DATA_BLOCK_GEN_II[counter]));
|
||||
//INPUT_BLOCK_GEN_II[counter] = in;
|
||||
break;
|
||||
case 1:
|
||||
send = in;
|
||||
break;
|
||||
default:
|
||||
send = in;
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
trade_centre_state_gen_II = SENDING_DATA;
|
||||
} else if(trade_centre_state_gen_II == SENDING_DATA) {
|
||||
switch(MODE){
|
||||
case 0:
|
||||
//send = pgm_read_byte(&(DATA_BLOCK_GEN_II[counter]));
|
||||
//INPUT_BLOCK_GEN_II[counter] = in;
|
||||
break;
|
||||
case 1:
|
||||
send = in;
|
||||
break;
|
||||
default:
|
||||
send = in;
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
if(counter == PLAYER_LENGTH_GEN_II) {
|
||||
trade_centre_state_gen_II = SENDING_PATCH_DATA;
|
||||
}
|
||||
} else if(trade_centre_state_gen_II == SENDING_PATCH_DATA && in == 0xFD) {
|
||||
counter = 0;
|
||||
send = 0xFD;
|
||||
} else if(trade_centre_state_gen_II == SENDING_PATCH_DATA && in != 0xFD) {
|
||||
send = in;
|
||||
trade_centre_state_gen_II = MIMIC;
|
||||
} else if(trade_centre_state_gen_II == MIMIC){
|
||||
send = in;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} else if(trade_centre_state_gen_II == TRADE_PENDING && (in & 0x60) == 0x60) {
|
||||
if (in == 0x6f) {
|
||||
trade_centre_state_gen_II = READY_TO_GO;
|
||||
send = 0x6f;
|
||||
} else {
|
||||
send = 0x60; // first pokemon
|
||||
trade_pokemon = in - 0x60;
|
||||
}
|
||||
} else if(trade_centre_state_gen_II == TRADE_PENDING && in == 0x00) {
|
||||
send = 0;
|
||||
trade_centre_state_gen_II = TRADE_CONFIRMATION;
|
||||
} else if(trade_centre_state_gen_II == TRADE_CONFIRMATION && (in & 0x60) == 0x60) {
|
||||
send = in;
|
||||
if (in == 0x61) {
|
||||
trade_pokemon = -1;
|
||||
trade_centre_state_gen_II = TRADE_PENDING;
|
||||
} else {
|
||||
trade_centre_state_gen_II = DONE;
|
||||
}
|
||||
} else if(trade_centre_state_gen_II == DONE && in == 0x00) {
|
||||
send = 0;
|
||||
trade_centre_state_gen_II = INIT;
|
||||
} else {
|
||||
send = in;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
send = in;
|
||||
break;
|
||||
}
|
||||
|
||||
SPIout = send;
|
||||
|
||||
for (int i = 7; i > 0; i--)
|
||||
{
|
||||
outputArr[i] = outputArr[i - 1];
|
||||
}
|
||||
outputArr[0] = "TS: " + std::to_string((int)trade_centre_state_gen_II) + " CS: " + std::to_string((int)connection_state) +
|
||||
" OUT: " + u8ToHexStr(SPIout) + " IN: " + u8ToHexStr(SPIin);
|
||||
|
||||
|
||||
// Cancel
|
||||
if ((keys & KEY_L) && (keys & KEY_R))
|
||||
{
|
||||
linkSPI->deactivate();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Print
|
||||
VBlankIntrWait();
|
||||
output = "";
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
output += (outputArr[i] + "\n");
|
||||
}
|
||||
|
||||
log(output);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void log(std::string text)
|
||||
{
|
||||
tte_erase_screen();
|
||||
tte_write("#{P:0,0}");
|
||||
tte_write(text.c_str());
|
||||
}
|
||||
|
||||
void wait(u32 verticalLines)
|
||||
{
|
||||
u32 count = 0;
|
||||
u32 vCount = REG_VCOUNT;
|
||||
|
||||
while (count < verticalLines)
|
||||
{
|
||||
if (REG_VCOUNT != vCount)
|
||||
{
|
||||
count++;
|
||||
vCount = REG_VCOUNT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
#include <gba.h>
|
||||
#include <tonc.h>
|
||||
#include <string>
|
||||
|
||||
#include "debug.h"
|
||||
#include "mirror.h"
|
||||
#include "gba_flash.h"
|
||||
#include "interrupt.h"
|
||||
#include "LinkSPI.h"
|
||||
#include "gb_link.h"
|
||||
|
||||
// This file is autogenerated from the file in the graphics folder
|
||||
#include "metr.h"
|
||||
|
|
@ -112,7 +115,7 @@ int main(void)
|
|||
}
|
||||
|
||||
if (key_released(KEY_START)){
|
||||
|
||||
start_link();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <gba.h>
|
||||
#include <tonc.h>
|
||||
#include "mirror.h"
|
||||
#include "gba_flash.h"
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ void initalize_memory_locations(){
|
|||
}
|
||||
|
||||
// Reverses the endian of the given array
|
||||
void reverse_endian(u8 *data, u8 size){
|
||||
void reverse_endian(u8 *data, size_t size){
|
||||
u8 temp;
|
||||
for (int i = 0; i < (size/2); i++){
|
||||
temp = data[i];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user