From 19f346ba42ec4e14e5d3c08dfc0f334e980c9752 Mon Sep 17 00:00:00 2001 From: Starport75 Date: Fri, 9 Jun 2023 18:31:19 -0500 Subject: [PATCH] Back to TONC --- Makefile | 6 +- include/LinkSPI.h | 237 +++++++++++++++++++++++++++++++++++++++ include/gb_link.h | 81 ++++++++++++++ include/interrupt.h | 30 +++++ include/mirror.h | 2 +- source/debug.cpp | 2 +- source/gb_link.cpp | 264 ++++++++++++++++++++++++++++++++++++++++++++ source/main.cpp | 7 +- source/mirror.cpp | 4 +- 9 files changed, 625 insertions(+), 8 deletions(-) create mode 100644 include/LinkSPI.h create mode 100644 include/gb_link.h create mode 100644 include/interrupt.h create mode 100644 source/gb_link.cpp diff --git a/Makefile b/Makefile index 7b1dd24..365c28a 100644 --- a/Makefile +++ b/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 diff --git a/include/LinkSPI.h b/include/LinkSPI.h new file mode 100644 index 0000000..38e11a1 --- /dev/null +++ b/include/LinkSPI.h @@ -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 + +#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 + 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 + 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 \ No newline at end of file diff --git a/include/gb_link.h b/include/gb_link.h new file mode 100644 index 0000000..aa7078c --- /dev/null +++ b/include/gb_link.h @@ -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 + +void log(std::string text); +void wait(u32 verticalLines); +inline void VBLANK() {} +void init(); +int start_link(); + +#endif diff --git a/include/interrupt.h b/include/interrupt.h new file mode 100644 index 0000000..47c5b27 --- /dev/null +++ b/include/interrupt.h @@ -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 \ No newline at end of file diff --git a/include/mirror.h b/include/mirror.h index 539ada4..4f1df10 100644 --- a/include/mirror.h +++ b/include/mirror.h @@ -1,6 +1,6 @@ #ifndef MIRROR_H #define MIRROR_H -#include +#include #define MEM_CRAM 0x0E000000 //!< Cart RAM diff --git a/source/debug.cpp b/source/debug.cpp index 9ff5247..3040dc7 100644 --- a/source/debug.cpp +++ b/source/debug.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "mirror.h" #include "gba_flash.h" diff --git a/source/gb_link.cpp b/source/gb_link.cpp new file mode 100644 index 0000000..9fccf57 --- /dev/null +++ b/source/gb_link.cpp @@ -0,0 +1,264 @@ +#include +#include + +#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; + } + }; +} \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index d61e941..e7008f4 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,9 +1,12 @@ -#include +#include #include #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(); } diff --git a/source/mirror.cpp b/source/mirror.cpp index 8e5841c..70a01ad 100644 --- a/source/mirror.cpp +++ b/source/mirror.cpp @@ -1,4 +1,4 @@ -#include +#include #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];