Implement & link JoyBoot.c

This commit is contained in:
Cuyler36
2023-06-01 17:20:41 -04:00
parent 7294ce4220
commit 5ff38da9d4
20 changed files with 2277 additions and 1 deletions
+7 -1
View File
@@ -341,6 +341,11 @@ BOOT_CFLAGS = CFLAGS + [
"-sdata 0",
"-sdata2 0"
] + DOL_DEFINES
DOL_CFLAGS_NO_SDATA = CFLAGS + [
"-inline on",
"-sdata 0",
"-sdata2 0"
] + DOL_DEFINES
DVDERR_CFLAGS = CFLAGS + [
"-inline on",
"-sdata 0",
@@ -395,8 +400,9 @@ JSYSTEM_BASE = [
JSYSTEM_CFLAGS = ' '.join(JSYSTEM_BASE + LOCAL_CFLAGS)
DOL_CFLAGS = ' '.join(BASE_DOL_CFLAGS + LOCAL_CFLAGS)
DOL_BOOT_CFLAGS = ' '.join(BOOT_CFLAGS + LOCAL_CFLAGS) # TODO: this uses C++ but there's some issues with ppcdis, real flags: ' '.join(CPLFLAGS + BOOT_CFLAGS + LOCAL_CFLAGS);
DOL_BOOT_CFLAGS = ' '.join(BOOT_CFLAGS + LOCAL_CFLAGS)
DOL_DVDERR_CFLAGS = ' '.join(DVDERR_CFLAGS + LOCAL_CFLAGS)
DOL_CFLAGS_SDATA0_CFLAGS = ' '.join(DOL_CFLAGS_NO_SDATA + LOCAL_CFLAGS)
SDK_FLAGS = ' '.join(SDK_CFLAG + LOCAL_CFLAGS)
ALIGN16 = ' '.join(BASE_DOL_CFLAGS + LOCAL_CFLAGS + ALIGN16_CFLAG)
DOL_CPPFLAGS = ' '.join(CPLFLAGS + BASE_DOL_CFLAGS + LOCAL_CFLAGS)
+2
View File
@@ -3,3 +3,5 @@ trim_ctors: true
symbol_aligns:
0x80207458: 8 # align RunQueue to 0x001251d8
0x800b9140: 32 # align gam_win_moji1_tex to 32 bytes
0x801f71c0: 32 # align texture_buffer_data to 32 bytes
0x800daaa0: 32 # align texture_cache_data_func to 32 bytes
+4
View File
@@ -41,6 +41,10 @@ jaudio_NES/dummyprobe.c:
#jaudio_NES/verysimple.c:
# .text: [0x80008400, 0x80008480]
# .sdata: [0x80217b80, 0x80217b88]
GBA2/JoyBoot.c:
.text: [0x80049788, 0x8004ae00]
.data: [0x800daa08, 0x800daaa0]
.bss: [0x801f7180, 0x801f71c0]
libforest/osreport.c:
.text: [0x8005a654, 0x8005a92c]
.data: [0x800dc6d8, 0x800dc738]
+4
View File
@@ -631,6 +631,10 @@ class CSource(Source):
self.cflags = c.JSYSTEM_CFLAGS
self.cc = c.CC
self.frank = False
elif path.startswith("src/GBA2/"):
self.cflags = c.DOL_CFLAGS_SDATA0_CFLAGS
self.cc = c.CC
self.frank = False
elif path.startswith("src/bootdata/") or path == "src/boot.c" or path == "src/initial_menu.c":
self.cflags = c.DOL_BOOT_CFLAGS
self.cc = c.CC
+80
View File
@@ -0,0 +1,80 @@
#ifndef GBAPRIV
#define GBAPRIV
#include "types.h"
#include "GBA/gba.h"
#include "dolphin/os.h"
#include "dolphin/dsp.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*GBATransferCallback)(s32 chan);
typedef struct GBASecParam {
u8 readbuf[4];
s32 paletteColor;
s32 paletteSpeed;
s32 length;
u32* out;
u8 _padding0[12];
u32 keyA;
s32 keyB;
u8 _padding1[24];
} GBASecParam;
typedef struct GBABootInfo {
s32 paletteColor;
s32 paletteSpeed;
u8* programp;
s32 length;
u8* status;
GBACallback callback;
u8 readbuf[4];
u8 writebuf[4];
int i;
OSTick start;
OSTime begin;
int firstXfer;
int curOffset;
u32 crc;
u32 dummyWord[7];
u32 keyA;
s32 keyB;
u32 initialCode;
int realLength;
} GBABootInfo;
typedef struct GBAControl {
u8 output[5];
u8 input[5];
s32 outputBytes;
s32 inputBytes;
u8* status;
u8* ptr;
GBACallback callback;
s32 ret;
OSThreadQueue threadQueue;
OSTime delay;
GBATransferCallback proc;
GBABootInfo bootInfo;
DSPTaskInfo task;
GBASecParam* param;
} GBAControl;
extern GBAControl __GBA[4];
extern BOOL __GBAReset;
void __GBAHandler(s32 chan, u32 error, OSContext* context);
void __GBASyncCallback(s32 chan, s32 ret);
s32 __GBASync(s32 chan);
OSTime __GBASetDelay(s32 chan, OSTime delay);
s32 __GBATransfer(s32 chan, s32 w1, s32 w2, GBATransferCallback callback);
#ifdef __cplusplus
}
#endif
#endif
+65
View File
@@ -0,0 +1,65 @@
#ifndef GBA
#define GBA
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GBA_CHAN0 0
#define GBA_CHAN1 1
#define GBA_CHAN2 2
#define GBA_CHAN3 3
#define GBA_MAX_CHAN 4
#define GBA_ALL_KEY_MASK 0x03ff
#define GBA_A_BUTTON 0x0001
#define GBA_B_BUTTON 0x0002
#define GBA_SELECT_BUTTON 0x0004
#define GBA_START_BUTTON 0x0008
#define GBA_R_KEY 0x0010
#define GBA_L_KEY 0x0020
#define GBA_U_KEY 0x0040
#define GBA_D_KEY 0x0080
#define GBA_R_BUTTON 0x0100
#define GBA_L_BUTTON 0x0200
#define GBA_JSTAT_MASK 0x3a
#define GBA_JSTAT_FLAGS_SHIFT 4
#define GBA_JSTAT_FLAGS_MASK 0x30
#define GBA_JSTAT_PSF1 0x20
#define GBA_JSTAT_PSF0 0x10
#define GBA_JSTAT_SEND 0x08
#define GBA_JSTAT_RECV 0x02
#define GBA_READY 0
#define GBA_NOT_READY 1
#define GBA_BUSY 2
#define GBA_JOYBOOT_UNKNOWN_STATE 3
#define GBA_JOYBOOT_ERR_INVALID 4
#define GBA_JOYBOOT_PROGRAM_SIZE_MAX 0x40000
#define GBA_JOYBOOT_BOOTPARAM_OFFSET 0xc8
#define GBA_JOYBOOT_BOOTPARAM_SIZE 0x18
typedef void (*GBACallback)(s32 chan, s32 ret);
void GBAInit(void);
s32 GBAGetStatus(s32 chan, u8* status);
s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback);
s32 GBAReset(s32 chan, u8* status);
s32 GBAResetAsync(s32 chan, u8* status, GBACallback callback);
s32 GBAGetProcessStatus(s32 chan, u8* percentp);
s32 GBARead(s32 chan, u8* dst, u8* status);
s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback);
s32 GBAWrite(s32 chan, u8* src, u8* status);
s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback);
s32 GBAJoyBoot(s32 chan, s32 palette_color, s32 palette_speed, u8* programp, s32 length,
u8* status);
s32 GBAJoyBootAsync(s32 chan, s32 palette_color, s32 palette_speed, u8* programp, s32 length,
u8* status, GBACallback callback);
#ifdef __cplusplus
}
#endif
#endif
+126
View File
@@ -0,0 +1,126 @@
#ifndef GBA2_H
#define GBA2_H
#include "types.h"
#include "GBA/gba.h"
#ifdef __cplusplus
extern "C" {
#endif
#define EAPPLI_LOAD_PROG_MAGIC 'PSAE'
#define EAPPLI_PROGRAM_CHECK_MAGIC_GC 'GAFJ'
#define EAPPLI_PROGRAM_CHECK_MAGIC_GBA 'AAFJ'
#define GBA2_GBA_STATE_ERROR -1
#define GBA2_GBA_STATE_ALREADY_EXIST 0
#define GBA2_GBA_STATE_SUCCESS 1
#define GBA2_GBA_STATE_TRANSMITTING 9
#define GBA2_EAPPLI_TRANSMITTING -1
#define GBA2_EAPPLI_SUCCESS 0
#define GBA2_EAPPLI_FAILURE_XFER_ERROR 1
#define GBA2_EAPPLI_FAILURE_NO_GBA 2
#define GBA2_SEND_RECV_TRIES 7
#define GBA2_CONNECTED_TRIES 45
#define GBA2_DEFAULT_TRIES 120
#define GBA2_READ_TRIES 1200
enum eappli_type {
GBA2_EAPPLI_TYPE_NEEDLEWORK, /* Able Sisters' design program */
GBA2_EAPPLI_TYPE_MUSICSCORE, /* Town tune editor program */
GBA2_EAPPLI_TYPE_PTERMINAL, /* e-Card scanning program */
GBA2_EAPPLI_TYPE_NUM
};
enum send_eappli_state {
SEND_EAPPLI_STATE_WAIT_FOR_GBA, /* GC awaits load magic (PSAE) from GBA */
SEND_EAPPLI_STATE_GC_ACKNOWLEDGE_TO_GBA, /* GC sends load magic (PSAE) back to GBA to acknowledge it is there */
SEND_EAPPLI_STATE_2, /* skipped/unused state */
SEND_EAPPLI_STATE_GC_SEND_EAPPLI_SIZE_TO_GBA, /* GC sends eAppli program data size to GBA */
SEND_EAPPLI_STATE_WAIT_FOR_GBA_ACKNOWLEDGED_EAPPLI_SIZE, /* GC awaits GBA is ready for eAppli data */
SEND_EAPPLI_STATE_GC_SEND_EAPPLI_DATA_TO_GBA, /* GC sends eAppli data to GBA */
SEND_EAPPLI_STATE_GC_OPEN_JOY_SIO_CONNECTION, /* GC attempts to open connection with GBA eAppli program */
SEND_EAPPLI_STATE_JOY_SIO_CONNECTION_OPEN /* GC <-> GBA connection is open */
};
enum send_eappli_status {
SEND_EAPPLI_STATUS_SUCCESS, /* Program successfully sent & loaded */
SEND_EAPPLI_STATUS_FAILED_GBA_NOT_DETECTED, /* GBA was not detected during first stage */
SEND_EAPPLI_STATUS_FAILED_TRANSMISSION_ERROR, /* Transmission error occurred */
SEND_EAPPLI_STATUS_SENDING /* Transmission is in progress */
};
#define GBA2_MAKE_ACKNOWLEDGE_CODE(dev, state) (0xFFFE0000 | ((dev) << 8) | (state))
enum gba_gc_device {
GBA2_DEVICE_NONE,
GBA2_DEVICE_GC,
GBA2_DEVICE_GBA
};
enum gba_gc_command {
GBA2_CMD_CHECK_STATE = 1,
GBA2_CMD_WRITE = 2,
GBA2_CMD_START_RECV = 4,
GBA2_CMD_VALID_CHKSUM = 6,
GBA2_CMD_INVALID_CHKSUM = 7,
GBA2_CMD_READY_FOR_XFER = 8,
GBA2_CMD_XFER_START = 9,
GBA2_CMD_XFER_FINISHED = 10,
};
typedef struct gba2_joywork_s {
int unused0;
u32 packet_block_checksum;
u32 total_xfer_checksum;
int packets_processed;
int readwrite_ofs;
int unused14;
int cmd_attempts;
u8 unused1C;
u8 checksum_valid;
u8 checksum_invalid;
u8 unused1F;
u8 status;
u8 cmd_stage;
u8 recv_state;
u8 send_state;
u8 port_connection_states[GBA_MAX_CHAN];
u8 scan_state;
u8 gba_awaiting_ack;
int recv_wait;
} Joy_wrk_c;
extern int Port;
extern void mGcgba_Init();
extern void mGcgba_InitVar();
extern void mGcgba_EndComm();
extern int mGcgba_ConnectEnabled();
extern int mGcgba_Boot(u8* data_buf, size_t buf_size);
extern int mGcgba_IsEditor();
extern int mGcgba_IsIsland();
extern int mGcgba_Recv(u8* recv_bufp, size_t recv_buf_size);
extern int mGcgba_Read(u8* read_buf, size_t read_buf_size, u8 prog_type);
extern int mGcgba_CheckRecv(u8* recv_bufp, size_t recv_buf_size);
extern int mGcgba_Send(u8* send_bufp, size_t send_buf_size);
extern int mGcgba_send_eAppri(u8* eappli_p, size_t eappli_size);
#ifdef __cplusplus
}
#endif
#endif
+70
View File
@@ -0,0 +1,70 @@
#ifndef DSP_H
#define DSP_H
#include "types.h"
#include "dolphin/os/OSTime.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DSP_TASK_FLAG_CLEARALL 0x00000000
#define DSP_TASK_FLAG_ATTACHED 0x00000001
#define DSP_TASK_FLAG_CANCEL 0x00000002
#define DSP_TASK_STATE_INIT 0
#define DSP_TASK_STATE_RUN 1
#define DSP_TASK_STATE_YIELD 2
#define DSP_TASK_STATE_DONE 3
typedef void (*DSPCallback)(void* task);
typedef struct STRUCT_DSP_TASK {
vu32 state;
vu32 priority;
vu32 flags;
u16* iram_mmem_addr;
u32 iram_length;
u32 iram_addr;
u16* dram_mmem_addr;
u32 dram_length;
u32 dram_addr;
u16 dsp_init_vector;
u16 dsp_resume_vector;
DSPCallback init_cb;
DSPCallback res_cb;
DSPCallback done_cb;
DSPCallback req_cb;
struct STRUCT_DSP_TASK* next;
struct STRUCT_DSP_TASK* prev;
OSTime t_context;
OSTime t_task;
} DSPTaskInfo;
void DSPInit();
void DSPReset();
void DSPHalt();
void DSPSendMailToDSP(u32 mail);
u32 DSPCheckMailToDSP();
u32 DSPCheckMailFromDSP();
u32 DSPGetDMAStatus();
DSPTaskInfo* DSPAddTask(DSPTaskInfo* task);
void __DSP_exec_task(DSPTaskInfo* curr, DSPTaskInfo* next);
void __DSP_boot_task(DSPTaskInfo* task);
void __DSP_remove_task(DSPTaskInfo* task);
void __DSP_add_task(DSPTaskInfo* task);
void __DSP_debug_printf(const char* fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
+13
View File
@@ -13,6 +13,19 @@ extern "C" {
#define OS_RESET_HOTRESET 1 /* Soft reset */
#define OS_RESET_SHUTDOWN 2
typedef BOOL (*OSResetFunction)(BOOL final);
typedef struct OSResetFunctionInfo OSResetFunctionInfo;
struct OSResetFunctionInfo {
// public
OSResetFunction func;
u32 priority;
// private
OSResetFunctionInfo* next;
OSResetFunctionInfo* prev;
};
u32 OSGetResetCode();
void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu);
BOOL OSGetResetSwitchState();
+70
View File
@@ -0,0 +1,70 @@
#ifndef DOLPHIN_OSSERIAL
#define DOLPHIN_OSSERIAL
#include <types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SI_MAX_CHAN 4
#define SI_MAX_COMCSR_INLNGTH 128
#define SI_MAX_COMCSR_OUTLNGTH 128
#define SI_ERROR_UNDER_RUN 0x0001
#define SI_ERROR_OVER_RUN 0x0002
#define SI_ERROR_COLLISION 0x0004
#define SI_ERROR_NO_RESPONSE 0x0008
#define SI_ERROR_WRST 0x0010
#define SI_ERROR_RDST 0x0020
#define SI_ERROR_UNKNOWN 0x0040
#define SI_ERROR_BUSY 0x0080
#define SI_CHAN0 0
#define SI_CHAN1 1
#define SI_CHAN2 2
#define SI_CHAN3 3
#define SI_CHAN0_BIT 0x80000000
#define SI_CHAN1_BIT 0x40000000
#define SI_CHAN2_BIT 0x20000000
#define SI_CHAN3_BIT 0x10000000
#define SI_CHAN_BIT(chan) (SI_CHAN0_BIT >> (chan))
#define SI_TYPE_MASK 0x18000000u
#define SI_TYPE_N64 0x00000000u
#define SI_TYPE_DOLPHIN 0x08000000u
#define SI_TYPE_GC SI_TYPE_DOLPHIN
#define SI_GC_WIRELESS 0x80000000
#define SI_GC_NOMOTOR 0x20000000
#define SI_GC_STANDARD 0x01000000
#define SI_WIRELESS_RECEIVED 0x40000000
#define SI_WIRELESS_IR 0x04000000
#define SI_WIRELESS_STATE 0x02000000
#define SI_WIRELESS_ORIGIN 0x00200000
#define SI_WIRELESS_FIX_ID 0x00100000
#define SI_WIRELESS_TYPE 0x000f0000
#define SI_WIRELESS_LITE_MASK 0x000c0000
#define SI_WIRELESS_LITE 0x00040000
#define SI_WIRELESS_CONT_MASK 0x00080000
#define SI_WIRELESS_CONT 0x00000000
#define SI_WIRELESS_ID 0x00c0ff00
#define SI_WIRELESS_TYPE_ID (SI_WIRELESS_TYPE | SI_WIRELESS_ID)
#define SI_N64_CONTROLLER (SI_TYPE_N64 | 0x05000000)
#define SI_N64_MIC (SI_TYPE_N64 | 0x00010000)
#define SI_N64_KEYBOARD (SI_TYPE_N64 | 0x00020000)
#define SI_N64_MOUSE (SI_TYPE_N64 | 0x02000000)
#define SI_GBA (SI_TYPE_N64 | 0x00040000)
#define SI_GC_CONTROLLER (SI_TYPE_GC | SI_GC_STANDARD)
#define SI_GC_RECEIVER (SI_TYPE_GC | SI_GC_WIRELESS)
#define SI_GC_WAVEBIRD \
(SI_TYPE_GC | SI_GC_WIRELESS | SI_GC_STANDARD | SI_WIRELESS_STATE | SI_WIRELESS_FIX_ID)
#define SI_GC_KEYBOARD (SI_TYPE_GC | 0x00200000)
#define SI_GC_STEERING (SI_TYPE_GC | 0x00000000)
u32 SIProbe(s32 chan);
char* SIGetTypeString(u32 type);
void SIRefreshSamplingRate(void);
void SISetSamplingRate(u32 msec);
#ifdef __cplusplus
}
#endif
#endif
+56
View File
@@ -0,0 +1,56 @@
#ifndef DOLPHIN_SIPRIV
#define DOLPHIN_SIPRIV
#include "types.h"
#include "dolphin/os.h"
#include "dolphin/os/OSTime.h"
#include "dolphin/os/OSInterrupt.h"
#include "dolphin/os/OSSerial.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*SICallback)(s32 chan, u32 sr, OSContext* context);
typedef void (*SITypeAndStatusCallback)(s32 chan, u32 type);
typedef struct SIPacket {
s32 chan;
void* output;
u32 outputBytes;
void* input;
u32 inputBytes;
SICallback callback;
OSTime fire;
} SIPacket;
void SIInit(void);
u32 SIGetStatus(s32 chan);
BOOL SIBusy(void);
BOOL SIIsChanBusy(s32 chan);
BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
SICallback callback, OSTime delay);
u32 SISync(void);
void SISetCommand(s32 chan, u32 command);
u32 SIGetCommand(s32 chan);
void SITransferCommands(void);
u32 SISetXY(u32 x, u32 y);
u32 SIEnablePolling(u32 poll);
u32 SIDisablePolling(u32 poll);
BOOL SIGetResponse(s32 chan, void* data);
BOOL SIRegisterPollingHandler(OSInterruptHandler handler);
BOOL SIUnregisterPollingHandler(OSInterruptHandler handler);
u32 SIGetType(s32 chan);
u32 SIGetTypeAsync(s32 chan, SITypeAndStatusCallback callback);
u32 SIDecodeType(u32 type);
#ifdef __cplusplus
}
#endif
#endif
+3
View File
@@ -22,6 +22,9 @@ typedef struct gameAlloc_s {
} GameAlloc;
extern void* gamealloc_malloc(GameAlloc* gamealloc, size_t size);
extern void gamealloc_free(GameAlloc* gamealloc, void* ptr);
extern void gamealloc_cleanup(GameAlloc* gamealloc);
extern void gamealloc_init(GameAlloc* gamealloc);
#ifdef __cplusplus
};
+93
View File
@@ -0,0 +1,93 @@
#include "GBA/GBAPriv.h"
static GBASecParam SecParams[4];
GBAControl __GBA[4];
BOOL __GBAReset = FALSE;
static BOOL OnReset(BOOL);
static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127};
static void ShortCommandProc(s32 chan) {
GBAControl* gba;
gba = &__GBA[chan];
if (gba->ret != 0) {
return;
}
if (gba->input[0] != 0 || gba->input[1] != 4) {
gba->ret = 1;
return;
}
gba->status[0] = gba->input[2] & GBA_JSTAT_MASK;
}
void GBAInit() {
GBAControl* gba;
s32 chan;
for (chan = 0; chan < 4; ++chan) {
gba = &__GBA[chan];
gba->delay = OSMicrosecondsToTicks(60);
OSInitThreadQueue(&gba->threadQueue);
gba->param = &SecParams[chan];
}
OSInitAlarm();
DSPInit();
__GBAReset = FALSE;
OSRegisterResetFunction(&ResetFunctionInfo);
}
s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) {
GBAControl* gba;
gba = &__GBA[chan];
if (gba->callback != NULL) {
return GBA_BUSY;
}
gba->output[0] = 0;
gba->status = status;
gba->callback = callback;
return __GBATransfer(chan, 1, 3, ShortCommandProc);
}
s32 GBAGetStatus(s32 chan, u8* status) {
GBAControl* gba = &__GBA[chan];
s32 ret = GBAGetStatusAsync(chan, status, __GBASyncCallback);
if (ret != GBA_READY) {
return ret;
}
return __GBASync(chan);
}
s32 GBAResetAsync(s32 chan, u8* status, GBACallback callback) {
GBAControl* gba = &__GBA[chan];
s32 ret;
if (gba->callback != NULL) {
return GBA_BUSY;
}
gba->output[0] = 0xFF;
gba->status = status;
gba->callback = callback;
return __GBATransfer(chan, 1, 3, ShortCommandProc);
}
s32 GBAReset(s32 chan, u8* status) {
GBAControl* gba = &__GBA[chan];
s32 ret;
ret = GBAResetAsync(chan, status, __GBASyncCallback);
if (ret != GBA_READY) {
return ret;
}
return __GBASync(chan);
}
BOOL OnReset(BOOL unused) {
__GBAReset = TRUE;
return TRUE;
}
+39
View File
@@ -0,0 +1,39 @@
#include "GBA/GBAPriv.h"
s32 GBAGetProcessStatus(s32 chan, u8* percentp) {
BOOL enabled;
s32 ret; // r29
GBAControl* gba = &__GBA[chan]; // r25
GBABootInfo* bootInfo; // r31
u8 percent; // r30
OSTime t; // r27
bootInfo = &gba->bootInfo;
enabled = OSDisableInterrupts();
if (bootInfo->callback != NULL) {
ret = 2;
percent = (bootInfo->curOffset * 100) / bootInfo->realLength;
if (bootInfo->begin != 0) {
t = OSGetTime();
if (OSTicksToMilliseconds(t - bootInfo->begin) < (5500)) {
percent = ((t - bootInfo->begin) * percent) / OSMillisecondsToTicks((OSTime)5500);
}
if (percent >= 100) {
percent = 100;
}
}
if (percentp != NULL) {
*percentp = percent;
}
} else if (gba->callback != NULL) {
ret = 2;
} else {
ret = 0;
}
OSRestoreInterrupts(enabled);
return ret;
}
+375
View File
@@ -0,0 +1,375 @@
#include "GBA/GBAPriv.h"
static volatile u8 D54[] = {
0x18, 0xFC, 0xC0, 0x80, 0x7f, 0x40, 0x3f, 0x01, 0x00, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x64,
0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x4b, 0x61, 0x77, 0x61, 0x73, 0x65, 0x64, 0x6f, 0x00,
0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xAC, 0xC4, 0xF8, 0x08, 0x10, 0xBF, 0x18,
};
static void F23(s32 chan, s32 ret);
static void F25(s32 chan, s32 ret);
static void F27(s32 chan, s32 ret);
static void F29(s32 chan, s32 ret);
static void F31(s32 chan, s32 ret);
static void F33(s32 chan, s32 ret);
static void F35(s32 chan, s32 ret);
static void F37(s32 chan, s32 ret);
static void F39(s32 chan, s32 ret);
static u32 F72(u32 crc, u32 src, vu8* keyp) {
int i; // r31
int poly =
(keyp[0x13] << 8) + ((keyp[0x15] + (keyp[0x18] - (keyp[0x18] << 4))) - keyp[0x10]); // r30
for (i = keyp[1]; i > keyp[11]; --i) {
if ((src ^ crc) & 1) {
crc >>= 1;
crc ^= poly;
} else {
crc >>= 1;
}
src >>= 1;
}
return crc;
}
static u32 F95(u32 src, vu8* keyp) {
src = (src * ((keyp[3] << keyp[0x16]) | ((keyp[1] | (keyp[4] << keyp[0x11])) | (keyp[4] << keyp[0x18])))) - (keyp[7] - keyp[6]);
return src;
}
static void F104(s32 chan, s32 ret) {
GBABootInfo* bootInfo;
GBACallback callback;
bootInfo = &__GBA[chan].bootInfo;
bootInfo->begin = 0;
if (bootInfo->callback != NULL) {
callback = bootInfo->callback;
bootInfo->callback = NULL;
callback(chan, ret);
}
}
s32 GBAJoyBootAsync(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length,
u8* status, GBACallback callback) {
int ret;
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
u8 percent;
if (chan & ~3) {
return GBA_JOYBOOT_ERR_INVALID;
} else if (length == 0 || GBA_JOYBOOT_PROGRAM_SIZE_MAX < length) {
return GBA_JOYBOOT_ERR_INVALID;
} else if (paletteSpeed < -4 || paletteSpeed > 4) {
return GBA_JOYBOOT_ERR_INVALID;
} else if (paletteColor < 0 || paletteColor > 6) {
return GBA_JOYBOOT_ERR_INVALID;
} else if (programp[0xac] * programp[0xad] * programp[0xae] * programp[0xaf] == 0) {
return GBA_JOYBOOT_ERR_INVALID;
}
ret = GBAGetProcessStatus(chan, &percent);
if (ret != 0) {
return ret;
}
bootInfo->paletteColor = paletteColor;
bootInfo->paletteSpeed = paletteSpeed;
bootInfo->programp = programp;
bootInfo->length = length;
bootInfo->status = status;
bootInfo->callback = callback;
bootInfo->curOffset = D54[8];
ret = GBAGetStatusAsync(chan, bootInfo->status, F23);
if (ret != GBA_READY) {
bootInfo->callback = NULL;
}
return ret;
}
static void F23(s32 chan, s32 ret) {
GBAControl* gba;
GBABootInfo* bootInfo;
gba = &__GBA[chan];
bootInfo = &__GBA[chan].bootInfo;
if (ret != GBA_READY || (ret = GBAResetAsync(chan, bootInfo->status, F25)) != GBA_READY) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F25(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY && *bootInfo->status != D54[37]) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
}
if (ret != GBA_READY || (ret = GBAGetStatusAsync(chan, bootInfo->status, F27))) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F27(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY && *bootInfo->status != D54[0]) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
}
if (ret != GBA_READY || (ret = GBAReadAsync(chan, bootInfo->readbuf, bootInfo->status, F29))) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F29(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) {
__GBAX02(chan, bootInfo->readbuf);
} else {
F104(chan, ret);
}
gba->ret = ret;
}
void __GBAX01(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
int val200;
if (ret == GBA_READY) {
bootInfo->keyA = gba->param->keyA;
bootInfo->keyB = gba->param->keyB;
if (bootInfo->readbuf[3] == 0 || bootInfo->readbuf[2] == 0 ||
(bootInfo->keyA & (D54[5] << 9)) == 0 || bootInfo->readbuf[1] == 0 ||
(bootInfo->keyA >> 15) == 0 || bootInfo->readbuf[0] == 0) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
} else {
bootInfo->i = ~D54[36] & bootInfo->length + D54[36];
val200 = D54[20] << D54[33];
if (bootInfo->i < val200) {
bootInfo->i = val200;
}
bootInfo->realLength = bootInfo->i;
bootInfo->i -= val200;
bootInfo->i >>= D54[32];
bootInfo->writebuf[0] = (u8)(bootInfo->keyB >> 0);
bootInfo->writebuf[1] = (u8)(bootInfo->keyB >> 8);
bootInfo->writebuf[3] = (u8)(bootInfo->keyB >> 24);
bootInfo->writebuf[2] = (u8)(bootInfo->keyB >> 16);
bootInfo->crc = (D54[38] + 1) << D54[34];
bootInfo->curOffset = D54[8];
bootInfo->begin = OSGetTime();
bootInfo->firstXfer = TRUE;
ret = GBAWriteAsync(chan, bootInfo->writebuf, bootInfo->status, F31);
}
}
if (ret != GBA_READY) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F31(s32 chan, s32 ret) {
GBAControl* gba;
GBABootInfo* bootInfo;
u32 writeWord;
gba = &__GBA[chan];
bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) {
if (bootInfo->firstXfer != FALSE) {
bootInfo->firstXfer = FALSE;
} else if ((*bootInfo->status & D54[20]) == 0 ||
(*bootInfo->status & D54[42]) >> D54[33] !=
(bootInfo->curOffset & D54[33]) >> D54[31]) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
goto exit;
} else {
bootInfo->curOffset -= D54[25] - D54[23];
}
if (bootInfo->curOffset <= bootInfo->realLength) {
if (bootInfo->curOffset < bootInfo->realLength) {
writeWord = D54[29];
for (bootInfo->i = D54[29]; bootInfo->i < D54[33]; ++bootInfo->i) {
if (bootInfo->length != 0) {
writeWord |= *(bootInfo->programp++) << (bootInfo->i * D54[37]);
--bootInfo->length;
}
}
if (bootInfo->curOffset == D54[38]) {
bootInfo->initialCode = writeWord;
} else if (bootInfo->curOffset == D54[39]) {
writeWord = chan << D54[37];
}
if (bootInfo->curOffset >= D54[2]) {
bootInfo->crc = F72(bootInfo->crc, writeWord, &D54[19]);
}
if (bootInfo->curOffset == D54[40] + 0x100) {
bootInfo->dummyWord[0] = writeWord;
} else if (bootInfo->curOffset == D54[1] + 0x100) {
bootInfo->i = D54[7];
bootInfo->dummyWord[bootInfo->i] = writeWord;
}
} else {
writeWord = bootInfo->crc | (bootInfo->curOffset << 16);
}
if (bootInfo->curOffset > D54[43]) {
bootInfo->keyA = F95(bootInfo->keyA, &D54[20]);
writeWord ^= bootInfo->keyA;
writeWord ^= -(bootInfo->curOffset + D54[11] * 0x100000);
writeWord ^= (D54[11] | (D54[11] << 24)) | (D54[19] << 16) | (D54[18] << 8);
}
bootInfo->writebuf[3] = (writeWord >> D54[0]);
bootInfo->writebuf[0] = (writeWord >> D54[30]);
bootInfo->writebuf[1] = (writeWord >> D54[41]);
bootInfo->writebuf[2] = (writeWord >> D54[42]);
if (bootInfo->curOffset == D54[1] + D54[1]) {
bootInfo->dummyWord[2] = writeWord;
}
if (bootInfo->i < D54[33]) {
bootInfo->dummyWord[3 - (1 - bootInfo->i)] = writeWord;
bootInfo->dummyWord[5 - bootInfo->i] =
bootInfo->dummyWord[(2 - (1 - bootInfo->i))] * bootInfo->dummyWord[4 - bootInfo->i];
bootInfo->dummyWord[5 - (1 - bootInfo->i)] =
bootInfo->dummyWord[((1 - bootInfo->i))] * bootInfo->dummyWord[1 - (1 - bootInfo->i)];
bootInfo->dummyWord[7 - bootInfo->i] =
bootInfo->dummyWord[(-(1 - bootInfo->i))] * bootInfo->dummyWord[4 - bootInfo->i];
}
ret = GBAWriteAsync(chan, bootInfo->writebuf, bootInfo->status, F31);
} else {
bootInfo->start = OSGetTick();
ret = GBAReadAsync(chan, bootInfo->readbuf, bootInfo->status, F33);
}
}
exit:
if (ret != GBA_READY) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F33(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) {
for (bootInfo->i = 33; bootInfo->i < 36; ++bootInfo->i) {
ret = (((bootInfo->readbuf[3] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 24)) |
(bootInfo->readbuf[2] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 16)) |
(bootInfo->readbuf[1] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 8)) |
(bootInfo->readbuf[0] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 0)))
<< 24);
if (ret == GBA_READY) {
break;
}
}
if (ret != GBA_READY) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
} else {
bootInfo->start = OSGetTick();
ret = GBAGetStatusAsync(chan, bootInfo->status, F35);
}
}
if (ret != GBA_READY) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F35(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == 0) {
if (OSSecondsToTicks(10) <= OSGetTick() - bootInfo->start) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
} else if ((*bootInfo->status & 0x32) != 0) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
} else if (*bootInfo->status != 8) {
ret = GBAGetStatusAsync(chan, bootInfo->status, F35);
} else {
__GBASetDelay(chan, OSMillisecondsToTicks(8));
ret = GBAReadAsync(chan, bootInfo->readbuf, bootInfo->status, F37);
__GBASetDelay(chan, OSMicrosecondsToTicks(60));
}
}
if (ret != GBA_READY) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F37(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) {
if ((((bootInfo->readbuf[3] ^ (bootInfo->initialCode >> 24)) |
(bootInfo->readbuf[2] ^ (bootInfo->initialCode >> 16)) |
(bootInfo->readbuf[1] ^ (bootInfo->initialCode >> 8)) |
(bootInfo->readbuf[0] ^ (bootInfo->initialCode >> 0)))
<< 24) != 0) {
ret = GBA_JOYBOOT_UNKNOWN_STATE;
} else {
ret = GBAWriteAsync(chan, bootInfo->readbuf, bootInfo->status, F39);
}
}
if (ret != GBA_READY) {
F104(chan, ret);
}
gba->ret = ret;
}
static void F39(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
GBABootInfo* bootInfo = &__GBA[chan].bootInfo;
if (ret == GBA_READY) {
*bootInfo->status = 0;
}
F104(chan, ret);
gba->ret = ret;
}
s32 GBAJoyBoot(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length, u8* status) {
s32 ret = GBAJoyBootAsync(chan, paletteColor, paletteSpeed, programp, length, status,
__GBASyncCallback);
if (ret != GBA_READY) {
return ret;
}
return __GBASync(chan);
}
+114
View File
@@ -0,0 +1,114 @@
#include "GBA/GBAPriv.h"
static volatile u8 D35[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 33, 2, 255, 0, 33, 19, 6, 18, 3, 18, 4,
19, 5, 0, 146, 0, 255, 0, 136, 255, 255, 0, 137, 255, 255, 0, 138, 255, 255, 0,
139, 255, 255, 143, 0, 139, 0, 140, 0, 2, 191, 128, 126, 22, 252, 220, 209, 22, 253,
0, 0, 22, 251, 0, 1, 2, 191, 128, 120, 36, 255, 2, 128, 171, 186, 2, 148, 0,
41, 142, 0, 2, 191, 128, 120, 32, 255, 2, 64, 15, 255, 31, 94, 0, 155, 0, 0,
0, 153, 0, 32, 0, 135, 0, 0, 0, 128, 0, 65, 2, 159, 128, 188, 2, 191, 0,
140, 2, 191, 128, 126, 22, 252, 220, 209, 22, 253, 0, 3, 22, 251, 0, 1, 143, 0,
2, 191, 128, 120, 2, 128, 205, 209, 2, 148, 0, 76, 38, 255, 2, 128, 0, 1, 2,
149, 0, 94, 2, 128, 0, 2, 2, 149, 128, 0, 2, 159, 0, 76, 0, 33, 142, 0,
2, 191, 128, 120, 36, 255, 2, 191, 128, 120, 36, 255, 2, 191, 128, 120, 36, 255, 2,
191, 128, 120, 0, 197, 255, 255, 2, 64, 15, 255, 28, 158, 2, 191, 128, 120, 0, 199,
255, 255, 2, 191, 128, 120, 0, 198, 255, 255, 2, 191, 128, 120, 0, 192, 255, 255, 2,
191, 128, 120, 32, 255, 2, 64, 15, 255, 31, 94, 2, 191, 128, 120, 33, 255, 2, 191,
128, 120, 35, 255, 18, 5, 18, 6, 2, 159, 128, 181, 0, 33, 129, 0, 0, 129, 0,
16, 16, 32, 27, 62, 0, 223, 20, 86, 3, 64, 255, 208, 132, 23, 0, 128, 0, 0,
0, 134, 0, 0, 0, 130, 0, 31, 0, 222, 21, 246, 20, 8, 0, 223, 23, 102, 3,
64, 0, 255, 31, 95, 2, 191, 136, 229, 31, 28, 129, 30, 25, 30, 20, 120, 31, 252,
31, 94, 2, 191, 136, 9, 2, 191, 135, 35, 0, 6, 129, 6, 0, 222, 22, 108, 20,
4, 2, 64, 255, 0, 0, 223, 18, 49, 21, 120, 3, 64, 0, 255, 31, 95, 2, 191,
136, 229, 31, 28, 129, 30, 25, 30, 20, 120, 31, 252, 31, 94, 2, 191, 136, 9, 2,
191, 135, 35, 129, 0, 137, 0, 0, 209, 0, 5, 153, 0, 130, 0, 2, 149, 0, 229,
2, 145, 0, 243, 0, 130, 0, 16, 0, 134, 0, 1, 0, 208, 23, 27, 145, 0, 125,
0, 77, 0, 21, 1, 31, 95, 0, 223, 0, 3, 21, 4, 2, 191, 136, 9, 2, 159,
1, 2, 0, 130, 0, 17, 0, 223, 0, 3, 21, 1, 31, 95, 0, 222, 16, 67, 2,
64, 255, 240, 2, 191, 136, 229, 2, 159, 1, 2, 0, 130, 0, 16, 0, 134, 0, 1,
0, 208, 18, 133, 145, 0, 77, 0, 21, 1, 0, 222, 0, 3, 20, 4, 31, 94, 2,
191, 136, 9, 0, 131, 0, 19, 27, 126, 137, 35, 0, 131, 0, 19, 0, 223, 0, 7,
0, 222, 17, 184, 2, 64, 255, 240, 31, 94, 2, 191, 129, 244, 241, 0, 2, 191, 132,
88, 143, 0, 0, 130, 0, 21, 0, 222, 0, 6, 0, 218, 22, 91, 2, 191, 136, 229,
20, 253, 20, 3, 27, 94, 27, 92, 0, 130, 0, 22, 0, 222, 23, 35, 20, 244, 0,
218, 22, 107, 2, 191, 136, 229, 177, 0, 2, 144, 1, 46, 129, 0, 20, 253, 142, 0,
0, 223, 20, 145, 3, 64, 208, 240, 28, 191, 0, 223, 20, 104, 0, 209, 17, 252, 21,
124, 28, 223, 0, 209, 17, 184, 153, 0, 20, 24, 20, 120, 31, 94, 31, 254, 31, 101,
54, 0, 20, 2, 31, 102, 55, 0, 21, 1, 76, 0, 21, 24, 153, 0, 53, 0, 76,
0, 0, 223, 0, 18, 63, 0, 0, 255, 0, 18, 20, 112, 0, 223, 0, 17, 63, 0,
0, 255, 0, 17, 31, 165, 21, 1, 31, 230, 241, 0, 21, 248, 245, 0, 31, 95, 31,
125, 129, 0, 0, 222, 0, 17, 52, 0, 137, 0, 0, 223, 0, 18, 53, 0, 76, 0,
0, 223, 0, 18, 21, 120, 76, 0, 137, 0, 31, 254, 21, 8, 59, 0, 0, 222, 0,
17, 62, 0, 0, 223, 0, 18, 59, 0, 28, 191, 0, 218, 21, 241, 53, 0, 2, 149,
1, 146, 0, 223, 16, 226, 21, 8, 31, 95, 0, 223, 16, 59, 121, 0, 57, 0, 48,
128, 0, 254, 0, 34, 0, 220, 18, 41, 0, 221, 17, 248, 92, 0, 240, 0, 31, 229,
48, 128, 2, 159, 1, 165, 0, 223, 16, 202, 21, 8, 31, 95, 0, 223, 16, 67, 117,
0, 57, 0, 48, 128, 0, 254, 0, 34, 0, 220, 18, 89, 0, 221, 22, 254, 76, 0,
240, 0, 31, 229, 48, 128, 0, 254, 0, 35, 0, 218, 0, 8, 0, 216, 0, 9, 0,
155, 0, 32, 0, 153, 0, 8, 0, 135, 0, 0, 2, 191, 128, 139, 2, 223, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
};
static s32 F152(DSPTaskInfo* task) {
s32 chan; // r31
GBAControl* gba; // r29
for (chan = 0; chan < 4; ++chan) {
gba = &__GBA[chan];
if (&gba->task == task) {
return chan;
}
}
ASSERT(0 <= chan && chan < 4);
OSPanic(__FILE__, 169, "GBA - unexpected dsp call");
return -1;
}
static void F23(void* task) {
s32 chan; // r31
GBAControl* gba; // r30
chan = F152(task);
gba = &__GBA[chan];
DSPSendMailToDSP(0xabba0000);
while (DSPCheckMailToDSP()) {}
DSPSendMailToDSP((u32)gba->param);
while (DSPCheckMailToDSP()) {}
}
void F25(void* task) {
s32 chan; // r31
chan = F152(task);
__GBAX01(chan, 0);
}
void __GBAX02(s32 chan, u8* readbuf) {
GBAControl* gba; // r28
GBABootInfo* bootInfo; // r29
GBASecParam* param; // r30
DSPTaskInfo* task; // r31
gba = &__GBA[chan];
bootInfo = &__GBA[chan].bootInfo;
param = gba->param;
memcpy(param, readbuf, 4);
param->paletteColor = bootInfo->paletteColor;
param->paletteSpeed = bootInfo->paletteSpeed;
param->length = bootInfo->length;
param->out = &param->keyA;
DCInvalidateRange(&param->keyA, 32);
DCFlushRange(param, 32);
task = &gba->task;
task->priority = 255;
task->iram_mmem_addr = (u16*)OSCachedToPhysical(D35);
task->iram_length = sizeof(D35);
task->iram_addr = 0;
task->dsp_init_vector = 16;
task->init_cb = F23;
task->res_cb = NULL;
task->done_cb = F25;
task->req_cb = NULL;
DSPAddTask(task);
}
+40
View File
@@ -0,0 +1,40 @@
#include "GBA/GBAPriv.h"
static void ReadProc(s32 chan) {
GBAControl* gba;
gba = &__GBA[chan];
if (gba->ret == 0) {
memcpy(gba->ptr, gba->input, 4);
gba->status[0] = gba->input[4] & GBA_JSTAT_MASK;
}
}
s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback) {
GBAControl* gba;
gba = &__GBA[chan];
if (gba->callback != NULL) {
return 2;
}
gba->output[0] = 0x14;
gba->ptr = dst;
gba->status = status;
gba->callback = callback;
return __GBATransfer(chan, 1, 5, ReadProc);
}
s32 GBARead(s32 chan, u8* dst, u8* status) {
s32 tmp;
GBAControl* gba = &__GBA[chan];
s32 ret;
ret = GBAReadAsync(chan, dst, status, __GBASyncCallback);
if (ret != GBA_READY) {
return ret;
}
return __GBASync(chan);
}
+37
View File
@@ -0,0 +1,37 @@
#include "GBA/GBAPriv.h"
static void WriteProc(s32 chan) {
GBAControl* gba;
gba = &__GBA[chan];
if (gba->ret != 0) {
return;
}
gba->status[0] = gba->input[0] & GBA_JSTAT_MASK;
}
s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback) {
GBAControl* gba = &__GBA[chan];
if (gba->callback != NULL) {
return GBA_BUSY;
}
gba->output[0] = 0x15;
memcpy(&gba->output[1], src, 4);
gba->ptr = src;
gba->status = status;
gba->callback = callback;
return __GBATransfer(chan, 5, 1, WriteProc);
}
s32 GBAWrite(s32 chan, u8* src, u8* status) {
s32 tmp;
GBAControl* gba = &__GBA[chan];
s32 ret;
ret = GBAWriteAsync(chan, src, status, __GBASyncCallback);
if (ret != GBA_READY) {
return ret;
}
return __GBASync(chan);
}
+124
View File
@@ -0,0 +1,124 @@
#include "GBA/GBAPriv.h"
#include "dolphin/sipriv.h"
static void __GBAHandler(s32 chan, u32 error, OSContext* context) {
GBAControl* gba;
GBATransferCallback proc;
GBACallback callback;
OSContext exceptionContext;
gba = &__GBA[chan];
if (__GBAReset != 0) {
return;
}
if ((error & 0xf)) {
gba->ret = 1;
} else {
gba->ret = 0;
}
if (gba->proc != NULL) {
proc = gba->proc;
gba->proc = NULL;
proc(chan);
}
if (gba->callback == NULL) {
return;
}
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
callback = gba->callback;
gba->callback = NULL;
callback(chan, gba->ret);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
void __GBASyncCallback(s32 chan, s32 ret) {
GBAControl* gba = &__GBA[chan];
OSWakeupThread(&gba->threadQueue);
}
s32 __GBASync(s32 chan) {
GBAControl* gba;
s32 ret;
s32 enabled;
gba = &__GBA[chan];
enabled = OSDisableInterrupts();
while (gba->callback != NULL) {
OSSleepThread(&gba->threadQueue);
}
ret = gba->ret;
OSRestoreInterrupts(enabled);
return ret;
}
void TypeAndStatusCallback(s32 chan, u32 type) {
GBAControl* gba;
GBATransferCallback proc;
GBACallback callback;
OSContext exceptionContext;
OSContext* context;
gba = &__GBA[chan];
if (__GBAReset != 0) {
return;
}
if ((type & 0xFF) != 0 || (type & 0xffff0000) != 0x40000) {
gba->ret = GBA_NOT_READY;
} else {
if (SITransfer(chan, gba->output, gba->outputBytes, gba->input, gba->inputBytes, __GBAHandler,
gba->delay)) {
return;
}
gba->ret = GBA_BUSY;
}
if (gba->proc != NULL) {
proc = gba->proc;
gba->proc = NULL;
proc(chan);
}
if (gba->callback != NULL) {
context = OSGetCurrentContext();
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
callback = gba->callback;
gba->callback = NULL;
callback(chan, gba->ret);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
__OSReschedule();
}
}
s32 __GBATransfer(s32 chan, s32 w1, s32 w2, GBATransferCallback callback) {
s32 enabled;
GBAControl* gba;
gba = &__GBA[chan];
enabled = OSDisableInterrupts();
gba->proc = callback;
gba->outputBytes = w1;
gba->inputBytes = w2;
SIGetTypeAsync(chan, TypeAndStatusCallback);
OSRestoreInterrupts(enabled);
return GBA_READY;
}
OSTime __GBASetDelay(s32 chan, OSTime delay) {
OSTime oldDelay;
GBAControl* gba;
gba = &__GBA[chan];
oldDelay = gba->delay;
gba->delay = delay;
return oldDelay;
}
+955
View File
@@ -0,0 +1,955 @@
#include "GBA2/gba2.h"
#include "_mem.h"
#include "MSL_C/printf.h"
static Joy_wrk_c g_Joy_wrk;
int Port;
static u32 mJOYSIO_ConvData(u8* data) {
u8 conv_buf[sizeof(u32)];
conv_buf[0] = data[3];
conv_buf[1] = data[2];
conv_buf[2] = data[1];
conv_buf[3] = data[0];
return *(u32*)conv_buf;
}
extern void mGcgba_Init() { }
extern void mGcgba_InitVar() {
memset(&g_Joy_wrk, 0, sizeof(Joy_wrk_c));
}
extern void mGcgba_EndComm() {
Port = -1;
}
extern int mGcgba_ConnectEnabled() {
int state = GBA2_GBA_STATE_TRANSMITTING;
if (g_Joy_wrk.cmd_attempts < GBA2_CONNECTED_TRIES) {
int port;
for (port = 0; port < GBA_MAX_CHAN; port++) {
u8 status;
if (GBAGetStatus(port, &status) == GBA_READY) {
state = GBA2_GBA_STATE_SUCCESS;
Port = port;
break;
}
}
if (state != GBA2_GBA_STATE_SUCCESS) {
Port = -1;
}
}
else {
state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
return state;
}
static void CallBack(s32 port, s32 ret) {
g_Joy_wrk.port_connection_states[port] = ret;
}
extern int mGcgba_Boot(u8* data_buf, size_t buf_size) {
static u8 state;
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
return GBA2_GBA_STATE_ERROR;
}
else {
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
switch (g_Joy_wrk.cmd_stage) {
case 0:
{
int port;
for (port = 0; port < GBA_MAX_CHAN; port++) {
g_Joy_wrk.port_connection_states[port] = GBA2_GBA_STATE_SUCCESS;
}
g_Joy_wrk.cmd_stage++;
break;
}
case 1:
{
if (GBAGetProcessStatus(Port, NULL) == GBA_BUSY) {
g_Joy_wrk.cmd_attempts = 0;
}
else if (g_Joy_wrk.port_connection_states[Port] == GBA_READY) {
gba_state = GBA2_GBA_STATE_SUCCESS;
}
else {
if (GBAJoyBootAsync(Port, 1, 2, data_buf, buf_size, &state, CallBack)) {
g_Joy_wrk.port_connection_states[Port] = GBA2_GBA_STATE_TRANSMITTING;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
static int mJOYSIO_OpenConnection(Joy_wrk_c* joywork) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
u8 status;
if (GBAGetStatus(Port, &status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
else {
if (joywork->gba_awaiting_ack == TRUE) {
u32 data = mJOYSIO_ConvData((u8*)"GAFJ");
if (GBAWrite(Port, (u8*)&data, &status) == GBA_READY) {
gba_state = GBA2_GBA_STATE_SUCCESS;
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
else {
if (status & GBA_JSTAT_SEND) {
u32 recv;
if (GBARead(Port, (u8*)&recv, &status) == GBA_READY) {
if (*(u32*)"AAFJ" == recv) {
joywork->gba_awaiting_ack = TRUE;
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
if (gba_state == GBA2_GBA_STATE_TRANSMITTING && joywork->gba_awaiting_ack == FALSE && GBAReset(Port, &status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
}
return gba_state;
}
static int mGcgba_StartScan(Joy_wrk_c* joywork, u32 cmd) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
u8 status;
u8 status2;
u32 send;
u32 recv;
if (GBAGetStatus(Port, &status) == GBA_READY) {
if (joywork->scan_state == 1) {
if (status & GBA_JSTAT_SEND) {
if (GBARead(Port, (u8*)&recv, &status2) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
else {
switch (mJOYSIO_ConvData((u8*)&recv)) {
case 0xFFFE0208:
{
gba_state = GBA2_GBA_STATE_SUCCESS;
break;
}
case 0xFFFE020A:
{
gba_state = GBA2_GBA_STATE_ALREADY_EXIST;
break;
}
default:
{
gba_state = GBA2_GBA_STATE_ERROR;
break;
}
}
}
}
else {
send = 0xFFFE0109;
send = mJOYSIO_ConvData((u8*)&send);
if (GBAWrite(Port, (u8*)&send, &status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
if (GBAReset(Port, &status2) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
}
else if (status & GBA_JSTAT_SEND) {
recv;
if (GBARead(Port, (u8*)&recv, &status2) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
else{
switch (mJOYSIO_ConvData((u8*)&recv)) {
case 0xFFFE0208:
{
joywork->scan_state = 1;
break;
}
case 0xFFFE020A:
{
gba_state = GBA2_GBA_STATE_ALREADY_EXIST;
break;
}
default:
{
gba_state = GBA2_GBA_STATE_ERROR;
break;
}
}
}
}
else {
send = cmd;
send = mJOYSIO_ConvData((u8*)&send);
if (GBAWrite(Port, (u8*)&send, &status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
if (GBAReset(Port, &status2) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
}
return gba_state;
}
static int mGcgba_IsTypes(Joy_wrk_c* joywork, u32 load_type, u32 program_type) {
int gba_status = GBA2_GBA_STATE_TRANSMITTING;
u8 status;
u32 send;
if (GBAGetStatus(Port, &status) != GBA_READY) {
gba_status = GBA2_GBA_STATE_ERROR;
}
else {
if (status & GBA_JSTAT_SEND) {
u32 recv;
u8 readStatus;
if (GBARead(Port, (u8*)&recv, &readStatus) != GBA_READY) {
gba_status = GBA2_GBA_STATE_ERROR;
goto exit;
}
else {
if (joywork->scan_state == 1) {
if (load_type == mJOYSIO_ConvData((u8*)&recv)) {
gba_status = GBA2_GBA_STATE_SUCCESS;
goto exit;
}
if (program_type == mJOYSIO_ConvData((u8*)&recv)) {
gba_status = GBA2_GBA_STATE_ALREADY_EXIST;
goto exit;
}
gba_status = GBA2_GBA_STATE_ERROR;
goto exit;
}
joywork->cmd_attempts = 0;
}
}
send = 0xFFFE0105;
send = mJOYSIO_ConvData((u8*)&send);
if (GBAWrite(Port, (u8*)&send, &status) == GBA_READY) {
joywork->scan_state = 1;
}
else {
gba_status = GBA2_GBA_STATE_ERROR;
}
}
exit:
return gba_status;
}
extern int mGcgba_IsEditor() {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
return GBA2_GBA_STATE_ERROR;
}
else {
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
switch (g_Joy_wrk.cmd_stage)
{
case 0:
{
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
break;
}
case 1:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
gba_state = mGcgba_IsTypes(&g_Joy_wrk, 0xFFFE0206, 0xFFFE0207);
if (gba_state != GBA2_GBA_STATE_TRANSMITTING) {
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
extern int mGcgba_IsIsland() {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
return GBA2_GBA_STATE_ERROR;
}
else {
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
switch (g_Joy_wrk.cmd_stage)
{
case 0:
{
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
break;
}
case 1:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
gba_state = mGcgba_IsTypes(&g_Joy_wrk, 0xFFFE0207, 0xFFFE0206);
if (gba_state != GBA2_GBA_STATE_TRANSMITTING) {
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
static int mGcgba_Recv_sub(Joy_wrk_c* jwork, u8* recv_buf, size_t buf_size, u32 cmd) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
u8 status;
u8 read_status;
u32 gba_cmd;
u32 recv;
u32 data;
if (GBAGetStatus(Port, &status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
else {
if (status & GBA_JSTAT_SEND) {
if (GBARead(Port, (u8*)&recv, &read_status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
else {
data = mJOYSIO_ConvData((u8*)&recv);
switch (jwork->recv_state) {
case 0:
{
if (data == 0xFFFE0204) {
jwork->readwrite_ofs = 0;
jwork->packets_processed = 0;
jwork->packet_block_checksum = 0;
jwork->total_xfer_checksum = 0;
jwork->checksum_valid = FALSE;
jwork->checksum_invalid = FALSE;
jwork->recv_state++;
}
break;
}
case 1:
{
if (jwork->readwrite_ofs == (int)buf_size / 4) {
jwork->total_xfer_checksum += data;
if (jwork->total_xfer_checksum == 0xFFFFFFFF) {
jwork->checksum_valid = TRUE;
}
else {
jwork->checksum_invalid = TRUE;
}
jwork->recv_state++;
}
else if ((jwork->packets_processed & 0xFF) == 0xFF) {
jwork->packet_block_checksum += data;
if (jwork->packet_block_checksum != 0xFFFFFFFF) {
gba_state = GBA2_GBA_STATE_ERROR;
}
jwork->packet_block_checksum = 0;
}
else {
memcpy(recv_buf + jwork->readwrite_ofs * sizeof(u32), (u8*)&recv, sizeof(u32));
jwork->packet_block_checksum += data;
jwork->total_xfer_checksum += data;
jwork->readwrite_ofs++;
}
jwork->packets_processed++;
jwork->cmd_attempts = 0;
break;
}
case 2:
{
if (data == 0xFFFE0208) {
gba_state = GBA2_GBA_STATE_SUCCESS;
}
else if (data == 0xFFFE0209) {
gba_state = GBA2_GBA_STATE_ERROR;
}
break;
}
}
}
}
}
if (gba_state == GBA2_GBA_STATE_TRANSMITTING) {
if (jwork->checksum_valid == TRUE) {
gba_cmd = 0xFFFE0106;
}
else {
if (jwork->checksum_invalid == TRUE) {
gba_cmd = 0xFFFE0107;
}
else {
gba_cmd = cmd;
}
}
gba_cmd = mJOYSIO_ConvData((u8*)&gba_cmd);
if (GBAWrite(Port, (u8*)&gba_cmd, &read_status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
return gba_state;
}
extern int mGcgba_Recv(u8* recv_bufp, size_t recv_buf_size) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
return GBA2_GBA_STATE_ERROR;
}
else {
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
switch (g_Joy_wrk.cmd_stage)
{
case 0:
{
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
break;
}
case 1:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
gba_state = mGcgba_Recv_sub(&g_Joy_wrk, recv_bufp, recv_buf_size, 0xFFFE0102);
if (gba_state != GBA2_GBA_STATE_TRANSMITTING) {
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
extern int mGcgba_Read(u8* read_buf, size_t read_buf_size, u8 prog_type) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
printf("port 設定されていない\n"); // port not set
return GBA2_GBA_STATE_ERROR;
}
else {
if ((g_Joy_wrk.cmd_stage == 1 && g_Joy_wrk.cmd_attempts < GBA2_READ_TRIES) ||
(g_Joy_wrk.cmd_stage != 1 && g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES)
) {
switch (g_Joy_wrk.cmd_stage) {
case 0:
{
printf("read:イニシャルコード交換\n"); // read: initial code exchange
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
break;
}
case 1:
{
int res;
printf("read:スキャン\n"); // read: scan
switch (prog_type) {
case GBA2_EAPPLI_TYPE_NEEDLEWORK:
{
res = mGcgba_StartScan(&g_Joy_wrk, 0xFFFE0108);
break;
}
case GBA2_EAPPLI_TYPE_MUSICSCORE:
{
res = mGcgba_StartScan(&g_Joy_wrk, 0xFFFE010B);
break;
}
default: /* GBA2_EAPPLI_TYPE_PTERMINAL */
{
res = mGcgba_StartScan(&g_Joy_wrk, 0xFFFE010C);
break;
}
}
if (res == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
g_Joy_wrk.cmd_attempts = 0;
}
else if (res == GBA2_GBA_STATE_ERROR) {
gba_state = GBA2_GBA_STATE_ERROR;
}
break;
}
case 2:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
gba_state = mGcgba_Recv_sub(&g_Joy_wrk, read_buf, read_buf_size, 0xFFFE010A);
if (gba_state != GBA2_GBA_STATE_TRANSMITTING) {
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
extern int mGcgba_CheckRecv(u8* recv_bufp, size_t recv_buf_size) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
return GBA2_GBA_STATE_ERROR;
}
else {
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
switch (g_Joy_wrk.cmd_stage)
{
case 0:
{
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
break;
}
case 1:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
gba_state = mGcgba_Recv_sub(&g_Joy_wrk, recv_bufp, recv_buf_size, 0xFFFE0101);
if (gba_state != GBA2_GBA_STATE_TRANSMITTING) {
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
static int mGcgba_Send_sub(Joy_wrk_c* jwork, u8* send_bufp, size_t send_buf_size) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
u8 status;
u8 read_status;
u8 received_data;
u8 sent_data;
int recv_cmd;
u32 send_cmd;
u32 recv;
if (GBAGetStatus(Port, &status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
else {
received_data = FALSE;
sent_data = FALSE;
jwork->status = status;
if (status & GBA_JSTAT_SEND) {
if (GBARead(Port, (u8*)&recv, &read_status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
goto exit;
}
recv_cmd = mJOYSIO_ConvData((u8*)&recv);
received_data = TRUE;
}
switch (jwork->send_state) {
case 0:
{
if (received_data == TRUE && recv_cmd == 0xFFFE0104) {
jwork->readwrite_ofs = 0;
jwork->packets_processed = 0;
jwork->packet_block_checksum = 0;
jwork->total_xfer_checksum = 0;
jwork->send_state++;
}
break;
}
case 1:
{
if ((status & GBA_JSTAT_RECV) == 0) {
if (jwork->readwrite_ofs == (int)send_buf_size / 4) {
send_cmd = ~jwork->total_xfer_checksum;
jwork->send_state++;
}
else if ((jwork->packets_processed & 0xFF) == 0xFF) {
send_cmd = ~jwork->packet_block_checksum;
jwork->packet_block_checksum = 0;
}
else {
send_cmd = *(u32*)(send_bufp + jwork->readwrite_ofs * sizeof(u32));
jwork->packet_block_checksum += send_cmd;
jwork->total_xfer_checksum += send_cmd;
jwork->readwrite_ofs++;
}
if (GBAWrite(Port, (u8*)&send_cmd, &read_status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
sent_data = TRUE;
jwork->packets_processed++;
jwork->cmd_attempts = 0;
}
else {
if (GBAReset(Port, &read_status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
break;
}
case 2:
{
if (received_data == TRUE) {
if (recv_cmd == 0xFFFE0208) {
gba_state = GBA2_GBA_STATE_SUCCESS;
}
else if (recv_cmd == 0xFFFE0209) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
break;
}
}
}
exit:
if (gba_state == GBA2_GBA_STATE_TRANSMITTING && jwork->send_state != 1 && sent_data == FALSE) {
send_cmd = 0xFFFE0202;
send_cmd = mJOYSIO_ConvData((u8*)&send_cmd);
if (GBAWrite(Port, (u8*)&send_cmd, &read_status) != GBA_READY) {
gba_state = GBA2_GBA_STATE_ERROR;
}
}
return gba_state;
}
extern int mGcgba_Send(u8* send_bufp, size_t send_buf_size) {
int gba_state = GBA2_GBA_STATE_TRANSMITTING;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
return GBA2_GBA_STATE_ERROR;
}
else {
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
switch (g_Joy_wrk.cmd_stage)
{
case 0:
{
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
break;
}
case 1:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
gba_state = mGcgba_Send_sub(&g_Joy_wrk, send_bufp, send_buf_size);
if (gba_state != GBA2_GBA_STATE_TRANSMITTING) {
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_GBA_STATE_ERROR;
}
g_Joy_wrk.cmd_attempts++;
}
return gba_state;
}
static u32 changeEndian(u32 v) {
return ((v >> 24) & 0xFF) |
((v >> 8) & 0xFF00) |
((v & 0xFF00) << 8) |
((v & 0xFF) << 24);
}
extern int mGcgba_send_eAppri(u8* eappli_p, size_t eappli_size) {
int gba_state = GBA2_EAPPLI_TRANSMITTING;
int gba_status;
u32 data;
u32 recv;
u8 status;
if (Port < GBA_CHAN0 || Port >= GBA_MAX_CHAN) {
gba_state = GBA2_EAPPLI_FAILURE_NO_GBA;
}
else {
g_Joy_wrk.cmd_attempts++;
if (g_Joy_wrk.cmd_attempts < GBA2_DEFAULT_TRIES) {
gba_status = GBAGetStatus(Port, &status);
if (gba_status == GBA_READY) {
if ((status & GBA_JSTAT_RECV) == 0) {
g_Joy_wrk.recv_wait = 0;
}
else if (g_Joy_wrk.recv_wait < GBA2_SEND_RECV_TRIES) {
g_Joy_wrk.recv_wait++;
}
}
if (gba_status == GBA_READY && g_Joy_wrk.recv_wait <= GBA2_SEND_RECV_TRIES - 1) {
switch (g_Joy_wrk.cmd_stage) {
case SEND_EAPPLI_STATE_WAIT_FOR_GBA:
{
if ((status & GBA_JSTAT_SEND) != 0 &&
(status & GBA_JSTAT_PSF1) != 0 &&
(GBARead(Port, (u8*)&recv, &status) == GBA_READY) &&
(*(u32*)"PSAE" == recv)
) {
g_Joy_wrk.cmd_attempts = 0;
g_Joy_wrk.cmd_stage++;
}
else {
if (GBAReset(Port, &status) != GBA_READY) {
gba_state = GBA2_EAPPLI_FAILURE_NO_GBA;
}
}
break;
}
case SEND_EAPPLI_STATE_GC_ACKNOWLEDGE_TO_GBA:
{
data = *(u32*)"PSAE";
if (GBAWrite(Port, (u8*)&data, &status) == GBA_READY) {
g_Joy_wrk.cmd_attempts = 0;
g_Joy_wrk.cmd_stage++;
g_Joy_wrk.cmd_stage++; // lol duplication
}
break;
}
// case 2 unused
case SEND_EAPPLI_STATE_GC_SEND_EAPPLI_SIZE_TO_GBA:
{
if ((status & GBA_JSTAT_PSF0) && (status & GBA_JSTAT_PSF1)) {
data = changeEndian(eappli_size);
if (GBAWrite(Port, (u8*)&data, &status) == GBA_READY) {
g_Joy_wrk.cmd_attempts = 0;
g_Joy_wrk.cmd_stage++;
}
}
break;
}
case SEND_EAPPLI_STATE_WAIT_FOR_GBA_ACKNOWLEDGED_EAPPLI_SIZE:
{
if ((status & GBA_JSTAT_SEND) && GBARead(Port, (u8*)&recv, &status) == GBA_READY && eappli_size == changeEndian(recv)) {
g_Joy_wrk.cmd_attempts = 0;
g_Joy_wrk.readwrite_ofs = 0;
g_Joy_wrk.cmd_stage++;
}
break;
}
case SEND_EAPPLI_STATE_GC_SEND_EAPPLI_DATA_TO_GBA:
{
if ((u32)g_Joy_wrk.readwrite_ofs >= eappli_size / sizeof(u32)) {
g_Joy_wrk.cmd_stage++;
}
else {
if ((status & GBA_JSTAT_FLAGS_MASK) != GBA_JSTAT_FLAGS_MASK) {
return GBA2_EAPPLI_FAILURE_NO_GBA;
}
if ((status & GBA_JSTAT_RECV) == 0) {
data = *(u32*)(eappli_p + g_Joy_wrk.readwrite_ofs * sizeof(u32));
if (GBAWrite(Port, (u8*)&data, &status) == GBA_READY) {
g_Joy_wrk.cmd_attempts = 0;
g_Joy_wrk.readwrite_ofs++;
}
}
}
break;
}
case SEND_EAPPLI_STATE_GC_OPEN_JOY_SIO_CONNECTION:
{
if (mJOYSIO_OpenConnection(&g_Joy_wrk) == GBA2_GBA_STATE_SUCCESS) {
g_Joy_wrk.cmd_stage++;
}
else {
g_Joy_wrk.cmd_attempts = 0;
}
break;
}
case SEND_EAPPLI_STATE_JOY_SIO_CONNECTION_OPEN:
{
int attempt;
for (attempt = 0; attempt < 24; attempt++) {
int res = mGcgba_IsTypes(&g_Joy_wrk, 0xFFFE020A, 0xCDCDCDCD);
if (res != GBA2_GBA_STATE_TRANSMITTING) {
if (res == GBA2_GBA_STATE_SUCCESS) {
gba_state = GBA2_EAPPLI_SUCCESS;
}
else {
gba_state = GBA2_EAPPLI_FAILURE_NO_GBA;
}
break;
}
}
break;
}
}
}
else {
gba_state = GBA2_EAPPLI_FAILURE_NO_GBA;
}
}
else {
gba_state = GBA2_EAPPLI_FAILURE_NO_GBA;
}
}
if (gba_state == GBA2_EAPPLI_FAILURE_NO_GBA && g_Joy_wrk.cmd_stage != 0) {
gba_state = GBA2_EAPPLI_FAILURE_XFER_ERROR;
}
return gba_state;
}