Created
July 13, 2016 13:56
-
-
Save pepijndevos/801b676be479cd2df4b8b4d236220b4e to your computer and use it in GitHub Desktop.
Gambatte serial hack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From dfb2f47da8e1d8f810a7efb8409d18b80532be5e Mon Sep 17 00:00:00 2001 | |
From: Pepijn de Vos <pepijndevos@gmail.com> | |
Date: Wed, 13 Jul 2016 15:54:19 +0200 | |
Subject: [PATCH] hacketyhack | |
--- | |
libgambatte/SConstruct | 1 + | |
libgambatte/src/memory.cpp | 14 +++++- | |
libgambatte/src/pokemon.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++++ | |
libgambatte/src/pokemon.h | 54 ++++++++++++++++++++++ | |
4 files changed, 177 insertions(+), 1 deletion(-) | |
create mode 100644 libgambatte/src/pokemon.cpp | |
create mode 100644 libgambatte/src/pokemon.h | |
diff --git a/libgambatte/SConstruct b/libgambatte/SConstruct | |
index e882514..66fa83a 100644 | |
--- a/libgambatte/SConstruct | |
+++ b/libgambatte/SConstruct | |
@@ -40,6 +40,7 @@ sourceFiles = Split(''' | |
src/video/next_m0_time.cpp | |
src/video/ppu.cpp | |
src/video/sprite_mapper.cpp | |
+ src/pokemon.cpp | |
''') | |
conf = env.Configure() | |
diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp | |
index 2c1844e..6f65c0b 100644 | |
--- a/libgambatte/src/memory.cpp | |
+++ b/libgambatte/src/memory.cpp | |
@@ -23,6 +23,13 @@ | |
#include "video.h" | |
#include <cstring> | |
+// Serial hack | |
+#include "pokemon.h" | |
+ | |
+//debug | |
+#include <iostream> | |
+#include <bitset> | |
+ | |
namespace gambatte { | |
Memory::Memory(Interrupter const &interrupter) | |
@@ -128,19 +135,24 @@ void Memory::setEndtime(unsigned long cc, unsigned long inc) { | |
} | |
void Memory::updateSerial(unsigned long const cc) { | |
+ std::cout << std::hex << (int)ioamhram_[0x101] << ">"; | |
if (intreq_.eventTime(intevent_serial) != disabled_time) { | |
if (intreq_.eventTime(intevent_serial) <= cc) { | |
- ioamhram_[0x101] = (((ioamhram_[0x101] + 1) << serialCnt_) - 1) & 0xFF; | |
+ std::cout << "c>"; | |
+ //ioamhram_[0x101] = (((ioamhram_[0x101] + 1) << serialCnt_) - 1) & 0xFF; | |
+ ioamhram_[0x101] = handleSerialByte(ioamhram_[0x101]); | |
ioamhram_[0x102] &= 0x7F; | |
intreq_.setEventTime<intevent_serial>(disabled_time); | |
intreq_.flagIrq(8); | |
} else { | |
+ std::cout << "n>"; | |
int const targetCnt = serialCntFrom(intreq_.eventTime(intevent_serial) - cc, | |
ioamhram_[0x102] & isCgb() * 2); | |
ioamhram_[0x101] = (((ioamhram_[0x101] + 1) << (serialCnt_ - targetCnt)) - 1) & 0xFF; | |
serialCnt_ = targetCnt; | |
} | |
} | |
+ std::cout << std::hex << (int)ioamhram_[0x101] << "\n"; | |
} | |
void Memory::updateTimaIrq(unsigned long cc) { | |
diff --git a/libgambatte/src/pokemon.cpp b/libgambatte/src/pokemon.cpp | |
new file mode 100644 | |
index 0000000..a5da7b3 | |
--- /dev/null | |
+++ b/libgambatte/src/pokemon.cpp | |
@@ -0,0 +1,109 @@ | |
+#include "pokemon.h" | |
+ | |
+connection_state_t connection_state = NOT_CONNECTED; | |
+trade_centre_state_t trade_centre_state = INIT; | |
+int counter = 0; | |
+ | |
+int trade_pokemon = -1; | |
+ | |
+unsigned char handleSerialByte(unsigned char in) { | |
+ unsigned char 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) { | |
+ send = PKMN_CONNECTED; | |
+ connection_state = CONNECTED; | |
+ } | |
+ break; | |
+ | |
+ case CONNECTED: | |
+ if(in == PKMN_CONNECTED) | |
+ send = PKMN_CONNECTED; | |
+ else if(in == PKMN_TRADE_CENTRE) | |
+ connection_state = TRADE_CENTRE; | |
+ else if(in == PKMN_COLOSSEUM) | |
+ connection_state = COLOSSEUM; | |
+ else if(in == PKMN_BREAK_LINK || in == PKMN_MASTER) { | |
+ connection_state = NOT_CONNECTED; | |
+ send = PKMN_BREAK_LINK; | |
+ } else { | |
+ send = in; | |
+ } | |
+ break; | |
+ | |
+ case TRADE_CENTRE: | |
+ if(trade_centre_state == INIT && in == 0x00) { | |
+ trade_centre_state = READY_TO_GO; | |
+ send = 0x00; | |
+ } else if(trade_centre_state == READY_TO_GO && in == 0xFD) { | |
+ trade_centre_state = SEEN_FIRST_WAIT; | |
+ send = 0xFD; | |
+ } else if(trade_centre_state == SEEN_FIRST_WAIT && in != 0xFD) { | |
+ // random data of slave is ignored. | |
+ send = in; | |
+ trade_centre_state = SENDING_RANDOM_DATA; | |
+ } else if(trade_centre_state == SENDING_RANDOM_DATA && in == 0xFD) { | |
+ trade_centre_state = WAITING_TO_SEND_DATA; | |
+ send = 0xFD; | |
+ } else if(trade_centre_state == WAITING_TO_SEND_DATA && in != 0xFD) { | |
+ counter = 0; | |
+ // send first byte | |
+ send = in; | |
+ trade_centre_state = SENDING_DATA; | |
+ counter++; | |
+ } else if(trade_centre_state == SENDING_DATA) { | |
+ // if EEPROM is not initialised, please use the pgm data only. | |
+ send = in; | |
+ counter++; | |
+ if(counter == PLAYER_LENGTH) { | |
+ trade_centre_state = SENDING_PATCH_DATA; | |
+ } | |
+ } else if(trade_centre_state == SENDING_PATCH_DATA && in == 0xFD) { | |
+ counter = 0; | |
+ send = 0xFD; | |
+ } else if(trade_centre_state == SENDING_PATCH_DATA && in != 0xFD) { | |
+ send = in; | |
+ counter++; | |
+ if(counter == 197) { | |
+ trade_centre_state = TRADE_PENDING; | |
+ } | |
+ } else if(trade_centre_state == TRADE_PENDING && (in & 0x60) == 0x60) { | |
+ if (in == 0x6f) { | |
+ trade_centre_state = READY_TO_GO; | |
+ send = 0x6f; | |
+ } else { | |
+ send = 0x60; // first pokemon | |
+ trade_pokemon = in - 0x60; | |
+ } | |
+ } else if(trade_centre_state == TRADE_PENDING && in == 0x00) { | |
+ send = 0; | |
+ trade_centre_state = TRADE_CONFIRMATION; | |
+ } else if(trade_centre_state == TRADE_CONFIRMATION && (in & 0x60) == 0x60) { | |
+ send = in; | |
+ if (in == 0x61) { | |
+ trade_pokemon = -1; | |
+ trade_centre_state = TRADE_PENDING; | |
+ } else { | |
+ trade_centre_state = DONE; | |
+ } | |
+ } else if(trade_centre_state == DONE && in == 0x00) { | |
+ send = 0; | |
+ trade_centre_state = INIT; | |
+ } else { | |
+ send = in; | |
+ } | |
+ break; | |
+ | |
+ default: | |
+ send = in; | |
+ break; | |
+ } | |
+ | |
+ return send; | |
+} | |
+ | |
diff --git a/libgambatte/src/pokemon.h b/libgambatte/src/pokemon.h | |
new file mode 100644 | |
index 0000000..177456e | |
--- /dev/null | |
+++ b/libgambatte/src/pokemon.h | |
@@ -0,0 +1,54 @@ | |
+#ifndef POKEMON_H_ | |
+#define POKEMON_H_ | |
+ | |
+#define PLAYER_LENGTH 418 | |
+ | |
+unsigned char handleSerialByte(unsigned char in); | |
+ | |
+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, | |
+ START_SENDING_DATA, | |
+ SENDING_DATA, | |
+ SENDING_PATCH_DATA, | |
+ TRADE_PENDING, | |
+ TRADE_CONFIRMATION, | |
+ DONE | |
+} trade_centre_state_t; | |
+ | |
+typedef unsigned char byte; | |
+ | |
+#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_3_SELECTED 0xD6 | |
+ | |
+#define PKMN_MASTER 0x01 | |
+#define PKMN_SLAVE 0x02 | |
+#define PKMN_CONNECTED 0x60 | |
+#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 | |
+ | |
+#endif /* POKEMON_H_ */ | |
+ | |
-- | |
1.9.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment