Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Gambatte serial hack
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