mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-03-21 17:44:21 -05:00
Improving reliability of card transfers
This commit is contained in:
parent
3d4b5f934d
commit
a8ab944b58
|
|
@ -16,7 +16,8 @@ const data = {
|
|||
"MSG_TRANSFERRING": "TRANSFERRING",
|
||||
"MSG_CARD_SENT": "CARD SENT",
|
||||
"MSG_ERROR": "ERROR",
|
||||
"MSG_PRESS_B_CANCEL": "PRESS B TO CANCEL"
|
||||
"MSG_PRESS_B_CANCEL": "PRESS B TO CANCEL",
|
||||
"MSG_NUMBERS": "0123456789"
|
||||
};
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,14 @@ bool send(u16 data, CancelCallback cancel) {
|
|||
bool sendAndExpect(u16 data, u16 expect, CancelCallback cancel) {
|
||||
u16 received;
|
||||
do {
|
||||
if (!send(data, cancel))
|
||||
bool sent = false;
|
||||
for (u32 attempt = 0; attempt < 3; attempt++) {
|
||||
if (send(data, cancel)) {
|
||||
sent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sent)
|
||||
return false;
|
||||
|
||||
received = getDataFromPlayer0();
|
||||
|
|
|
|||
|
|
@ -3,8 +3,21 @@
|
|||
#include "link.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#ifdef REGION_JAP
|
||||
// Enable this to simulate failed scans with ⮜ and successful scans with ➤
|
||||
#define DEBUG_MODE 0
|
||||
|
||||
// Enable this to display error codes
|
||||
#define DISPLAY_ERROR_CODES 1
|
||||
|
||||
// Japanese strings are encoded as Shift-JIS byte arrays.
|
||||
#ifdef REGION_JAP
|
||||
#if DISPLAY_ERROR_CODES == 1
|
||||
/* "0123456789" */
|
||||
const u8 MSG_NUMBERS[] = {0x82, 0x4f, 0x82, 0x50, 0x82, 0x51, 0x82,
|
||||
0x52, 0x82, 0x53, 0x82, 0x54, 0x82, 0x55,
|
||||
0x82, 0x56, 0x82, 0x57, 0x82, 0x58, 0x00};
|
||||
#endif
|
||||
|
||||
#ifdef LANGUAGE_ENG
|
||||
const u8 MSG_WAITING_GAME[] = {
|
||||
0x82, 0x76, 0x82, 0x60, 0x82, 0x68, 0x82, 0x73, 0x82, 0x68, 0x82,
|
||||
|
|
@ -62,8 +75,42 @@ extern int __end[];
|
|||
ERAPI_HANDLE_REGION region;
|
||||
u8 card[CARD_BUFFER_SIZE];
|
||||
const u16 palette[] = {0x0000, 0xFFFF};
|
||||
u32 previousKeys = 0;
|
||||
|
||||
void print(const char* text);
|
||||
#if DISPLAY_ERROR_CODES == 1
|
||||
void codeToString(char* buf, int num) {
|
||||
#ifdef REGION_JAP
|
||||
const u8* digits = MSG_NUMBERS;
|
||||
int temp[5];
|
||||
int len = 0;
|
||||
do {
|
||||
temp[len++] = num % 10;
|
||||
num /= 10;
|
||||
} while (num && len < 5);
|
||||
|
||||
u8* p = (u8*)buf;
|
||||
for (int i = len - 1; i >= 0; --i) {
|
||||
int idx = temp[i] * 2;
|
||||
*p++ = digits[idx];
|
||||
*p++ = digits[idx + 1];
|
||||
}
|
||||
*p = 0;
|
||||
#else
|
||||
char temp[6];
|
||||
int pos = 0;
|
||||
do {
|
||||
temp[pos++] = '0' + (num % 10);
|
||||
num /= 10;
|
||||
} while (num && pos < 5);
|
||||
int j = 0;
|
||||
while (pos)
|
||||
buf[j++] = temp[--pos];
|
||||
buf[j] = '\0';
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void print(const char* text, bool canCancel);
|
||||
bool cancel();
|
||||
void reset();
|
||||
|
||||
|
|
@ -85,14 +132,13 @@ int main() {
|
|||
|
||||
// loop
|
||||
while (1) {
|
||||
if (cancel())
|
||||
break;
|
||||
u32 errorCode = 0;
|
||||
|
||||
// init loader
|
||||
reset();
|
||||
|
||||
// "Waiting for game..."
|
||||
print(MSG_WAITING_GAME);
|
||||
print(MSG_WAITING_GAME, false);
|
||||
|
||||
// handshake with game
|
||||
if (!sendAndExpect(HANDSHAKE_1, HANDSHAKE_1, cancel))
|
||||
|
|
@ -104,8 +150,10 @@ int main() {
|
|||
|
||||
// wait for card request
|
||||
u16 cardRequest = sendAndReceiveExcept(HANDSHAKE_3, HANDSHAKE_3, cancel);
|
||||
if (cardRequest != GAME_REQUEST)
|
||||
if (cardRequest != GAME_REQUEST) {
|
||||
errorCode = 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// confirm card request
|
||||
if (!sendAndExpect(GAME_ANIMATING, EREADER_ANIMATING, cancel))
|
||||
|
|
@ -113,45 +161,80 @@ int main() {
|
|||
if (!send(EREADER_ANIMATING, cancel))
|
||||
continue;
|
||||
|
||||
// "Scan a card!"
|
||||
print(MSG_SCAN_CARD);
|
||||
|
||||
// scan card
|
||||
if (cancel())
|
||||
goto abort;
|
||||
if (!sendAndExpect(EREADER_READY, GAME_READY, cancel))
|
||||
goto abort;
|
||||
|
||||
u32 resultCode = ERAPI_ScanDotCode((u32)card);
|
||||
if (resultCode != SCAN_SUCCESS)
|
||||
if (!sendAndExpect(EREADER_READY, GAME_READY, cancel)) {
|
||||
errorCode = 2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// "Scan a card!"
|
||||
print(MSG_SCAN_CARD, false);
|
||||
|
||||
#if DEBUG_MODE == 1
|
||||
u32 resultCode = 0;
|
||||
while (true) {
|
||||
u32 debugKeys = ERAPI_GetKeyStateRaw();
|
||||
if ((debugKeys & ERAPI_KEY_LEFT) != 0) {
|
||||
resultCode = SCAN_SUCCESS - 1;
|
||||
break;
|
||||
}
|
||||
if ((debugKeys & ERAPI_KEY_RIGHT) != 0) {
|
||||
resultCode = SCAN_SUCCESS;
|
||||
const char msg[] = "HelloWorld";
|
||||
const u32 msgLen = sizeof(msg) - 1;
|
||||
const u32 byteCount = CARD_BUFFER_SIZE - CARD_OFFSET;
|
||||
for (u32 i = 0; i < byteCount; i++)
|
||||
card[CARD_OFFSET + i] = i == byteCount - 1 ? '!' : msg[i % msgLen];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
u32 resultCode = ERAPI_ScanDotCode((u32)card);
|
||||
#endif
|
||||
|
||||
if (resultCode != SCAN_SUCCESS) {
|
||||
errorCode = 3;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// "Transferring..."
|
||||
print(MSG_TRANSFERRING);
|
||||
print(MSG_TRANSFERRING, true);
|
||||
|
||||
// transfer start
|
||||
if (!sendAndExpect(EREADER_SEND_READY, GAME_RECEIVE_READY, cancel))
|
||||
if (!sendAndExpect(EREADER_SEND_READY, GAME_RECEIVE_READY, cancel)) {
|
||||
errorCode = 4;
|
||||
goto error;
|
||||
if (!send(EREADER_SEND_START, cancel))
|
||||
}
|
||||
if (!send(EREADER_SEND_START, cancel)) {
|
||||
errorCode = 5;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// transfer
|
||||
u32 checksum = 0;
|
||||
for (u32 o = CARD_OFFSET; o < CARD_SIZE; o += 2) {
|
||||
u16 block = *(u16*)(card + o);
|
||||
if (!send(block, cancel))
|
||||
if (!send(block, cancel)) {
|
||||
errorCode = 6;
|
||||
goto error;
|
||||
}
|
||||
checksum += block;
|
||||
}
|
||||
if (!send(checksum & 0xffff, cancel))
|
||||
if (!send(checksum & 0xffff, cancel)) {
|
||||
errorCode = 7;
|
||||
goto error;
|
||||
if (!send(checksum >> 16, cancel))
|
||||
}
|
||||
if (!send(checksum >> 16, cancel)) {
|
||||
errorCode = 8;
|
||||
goto error;
|
||||
if (!send(EREADER_SEND_END, cancel))
|
||||
}
|
||||
if (!send(EREADER_SEND_END, cancel)) {
|
||||
errorCode = 9;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// "Card sent!"
|
||||
print(MSG_CARD_SENT);
|
||||
print(MSG_CARD_SENT, false);
|
||||
for (u32 i = 0; i < POST_TRANSFER_WAIT; i++)
|
||||
ERAPI_RenderFrame(1);
|
||||
|
||||
|
|
@ -168,7 +251,13 @@ int main() {
|
|||
// "Error!"
|
||||
ERAPI_ClearRegion(region);
|
||||
ERAPI_DrawText(region, 0, 0, MSG_ERROR);
|
||||
#if DISPLAY_ERROR_CODES == 1
|
||||
char errorCodeStr[11];
|
||||
codeToString(errorCodeStr, errorCode);
|
||||
ERAPI_DrawText(region, 0, 16, errorCodeStr);
|
||||
#else
|
||||
ERAPI_DrawText(region, 0, 16, MSG_WAITING_GAME);
|
||||
#endif
|
||||
ERAPI_RenderFrame(1);
|
||||
|
||||
send(EREADER_CANCEL, cancel);
|
||||
|
|
@ -183,16 +272,20 @@ int main() {
|
|||
return ERAPI_EXIT_TO_MENU;
|
||||
}
|
||||
|
||||
void print(const char* text) {
|
||||
void print(const char* text, bool canCancel) {
|
||||
ERAPI_ClearRegion(region);
|
||||
ERAPI_DrawText(region, 0, 0, text);
|
||||
ERAPI_DrawText(region, 0, 16, MSG_PRESS_B_CANCEL);
|
||||
if (canCancel)
|
||||
ERAPI_DrawText(region, 0, 16, MSG_PRESS_B_CANCEL);
|
||||
ERAPI_RenderFrame(1);
|
||||
}
|
||||
|
||||
bool cancel() {
|
||||
u32 keys = ERAPI_GetKeyStateRaw();
|
||||
return (keys & ERAPI_KEY_B) != 0;
|
||||
bool isPressed =
|
||||
(previousKeys & ERAPI_KEY_B) == 0 && (keys & ERAPI_KEY_B) != 0;
|
||||
previousKeys = keys;
|
||||
return isPressed;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -51,7 +51,7 @@ int main() {
|
|||
u32 initialVCount = REG_VCOUNT;
|
||||
auto device = linkCard->getConnectedDevice([&initialVCount]() {
|
||||
u32 elapsed = (REG_VCOUNT - initialVCount + 228) % 228;
|
||||
return elapsed > 30;
|
||||
return elapsed > 150;
|
||||
});
|
||||
|
||||
switch (device) {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class LinkCard {
|
|||
static constexpr int CMD_LINKCARD_RESET = 0;
|
||||
static constexpr int MODE_SWITCH_WAIT = 228;
|
||||
static constexpr int DEACTIVATION_WAIT = 50;
|
||||
static constexpr int PRE_TRANSFER_WAIT = 2 + 1;
|
||||
static constexpr int PRE_TRANSFER_WAIT = 4;
|
||||
|
||||
public:
|
||||
enum class ConnectedDevice {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user