mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-08 02:00:17 -04:00
12eb254d76
* switch to dtk setup * some cleanup / fixes * cleanup d_a_alink literals * Restore doxygen, update CI & README.md (#1) * Fix build image ref (#2) --------- Co-authored-by: Luke Street <luke@street.dev>
322 lines
7.5 KiB
C
322 lines
7.5 KiB
C
#include "dolphin/exi/EXIBios.h"
|
|
#include "dolphin/os.h"
|
|
|
|
typedef void (*MTRCallbackType)(int);
|
|
|
|
/* 804519D0-804519D4 000ED0 0004+00 2/2 0/0 0/0 .sbss MTRCallback */
|
|
static MTRCallbackType MTRCallback;
|
|
|
|
/* 804519D4-804519D8 000ED4 0004+00 2/2 0/0 0/0 .sbss DBGCallback */
|
|
static void (*DBGCallback)(u32, OSContext*);
|
|
|
|
/* 804519D8-804519DC 000ED8 0004+00 2/2 0/0 0/0 .sbss SendMailData */
|
|
static u32 SendMailData;
|
|
|
|
/* 804519DC-804519E0 000EDC 0004+00 2/2 0/0 0/0 .sbss RecvDataLeng */
|
|
static s32 RecvDataLeng;
|
|
|
|
/* 804519E0-804519E4 000EE0 0004+00 1/1 0/0 0/0 .sbss pEXIInputFlag */
|
|
static u8* pEXIInputFlag;
|
|
|
|
static u8 EXIInputFlag;
|
|
|
|
static u8 SendCount = 0x80;
|
|
|
|
#define IS_TRUE(x) ((x) != FALSE)
|
|
#define IS_FALSE(x) !IS_TRUE(x)
|
|
#define ROUND_UP(x, align) (((x) + (align)-1) & (-(align)))
|
|
|
|
void DBGEXIInit() {
|
|
__OSMaskInterrupts(0x18000);
|
|
__EXIRegs[10] = 0;
|
|
}
|
|
|
|
static u32 DBGEXISelect(u32 v) {
|
|
u32 regs = __EXIRegs[10];
|
|
regs &= 0x405;
|
|
regs |= 0x80 | (v << 4);
|
|
__EXIRegs[10] = regs;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL DBGEXIDeselect(void) {
|
|
__EXIRegs[10] &= 0x405;
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL DBGEXISync() {
|
|
while (__EXIRegs[13] & 1)
|
|
;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 80373514-803737AC 36DE54 0298+00 5/5 0/0 0/0 .text DBGEXIImm */
|
|
static BOOL DBGEXIImm(void* buffer, s32 bytecounter, u32 write) {
|
|
u8* tempPointer;
|
|
u32 writeOutValue;
|
|
int i;
|
|
|
|
if (write) {
|
|
tempPointer = buffer;
|
|
writeOutValue = 0;
|
|
for (i = 0; i < bytecounter; i++) {
|
|
u8* temp = ((u8*)buffer) + i;
|
|
writeOutValue |= *temp << ((3 - i) << 3);
|
|
}
|
|
__EXIRegs[14] = writeOutValue;
|
|
}
|
|
|
|
__EXIRegs[13] = 1 | write << 2 | (bytecounter - 1) << 4;
|
|
DBGEXISync();
|
|
|
|
if (!write) {
|
|
writeOutValue = __EXIRegs[14];
|
|
tempPointer = buffer;
|
|
for (i = 0; i < bytecounter; i++) {
|
|
*tempPointer++ = writeOutValue >> ((3 - i) << 3);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL DBGWriteMailbox(u32 p1) {
|
|
u32 cmd = 0xc0000000;
|
|
u32 v;
|
|
u32 base = p1;
|
|
BOOL total = FALSE;
|
|
|
|
DBGEXISelect(4);
|
|
v = (base & 0x1fffffff) | (cmd);
|
|
total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 1));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
total |= IS_FALSE(DBGEXIDeselect());
|
|
|
|
return IS_FALSE(total);
|
|
}
|
|
|
|
/* 80373468-80373514 36DDA8 00AC+00 1/1 0/0 0/0 .text DBGReadMailbox */
|
|
#pragma dont_inline on
|
|
static BOOL DBGReadMailbox(u32* p1) {
|
|
BOOL total = FALSE;
|
|
u32 v;
|
|
|
|
DBGEXISelect(4);
|
|
|
|
v = 0x60000000;
|
|
total |= IS_FALSE(DBGEXIImm(&v, 2, 1));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
total |= IS_FALSE(DBGEXIImm(p1, 4, 0));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
total |= IS_FALSE(DBGEXIDeselect());
|
|
|
|
return IS_FALSE(total);
|
|
}
|
|
#pragma dont_inline reset
|
|
|
|
/* 8037338C-80373468 36DCCC 00DC+00 1/1 0/0 0/0 .text DBGRead */
|
|
static BOOL DBGRead(u32 count, u32* buffer, s32 param3) {
|
|
BOOL total = FALSE;
|
|
u32* buf_p = (u32*)buffer;
|
|
u32 v1;
|
|
u32 v;
|
|
|
|
DBGEXISelect(4);
|
|
|
|
v1 = (count & 0x1fffc) << 8 | 0x20000000;
|
|
total |= IS_FALSE(DBGEXIImm(&v1, sizeof(v1), 1));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
while (param3) {
|
|
total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 0));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
*buf_p++ = v;
|
|
|
|
param3 -= 4;
|
|
if (param3 < 0) {
|
|
param3 = 0;
|
|
}
|
|
}
|
|
|
|
total |= IS_FALSE(DBGEXIDeselect());
|
|
return IS_FALSE(total);
|
|
}
|
|
|
|
/* 803732B0-8037338C 36DBF0 00DC+00 1/1 0/0 0/0 .text DBGWrite */
|
|
static BOOL DBGWrite(u32 count, void* buffer, s32 param3) {
|
|
BOOL total = FALSE;
|
|
u32* buf_p = (u32*)buffer;
|
|
u32 v1;
|
|
u32 v;
|
|
|
|
DBGEXISelect(4);
|
|
|
|
v1 = (count & 0x1fffc) << 8 | 0xa0000000;
|
|
total |= IS_FALSE(DBGEXIImm(&v1, sizeof(v1), 1));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
while (param3 != 0) {
|
|
v = *buf_p++;
|
|
|
|
total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 1));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
param3 -= 4;
|
|
if (param3 < 0) {
|
|
param3 = 0;
|
|
}
|
|
}
|
|
|
|
total |= IS_FALSE(DBGEXIDeselect());
|
|
return IS_FALSE(total);
|
|
}
|
|
|
|
/* 80373204-803732B0 36DB44 00AC+00 1/1 0/0 0/0 .text DBGReadStatus */
|
|
inline static BOOL _DBGReadStatus(u32* p1) {
|
|
BOOL total = FALSE;
|
|
u32 v;
|
|
|
|
DBGEXISelect(4);
|
|
|
|
v = 1 << 30;
|
|
total |= IS_FALSE(DBGEXIImm(&v, 2, 1));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
total |= IS_FALSE(DBGEXIImm(p1, 4, 0));
|
|
total |= IS_FALSE(DBGEXISync());
|
|
|
|
total |= IS_FALSE(DBGEXIDeselect());
|
|
|
|
return IS_FALSE(total);
|
|
}
|
|
#pragma dont_inline on
|
|
static BOOL DBGReadStatus(u32* p1) {
|
|
return _DBGReadStatus(p1);
|
|
}
|
|
#pragma dont_inline reset
|
|
|
|
/* 803731C8-80373204 36DB08 003C+00 1/1 0/0 0/0 .text MWCallback */
|
|
static void MWCallback(u32 a, OSContext* b) {
|
|
EXIInputFlag = TRUE;
|
|
if (MTRCallback) {
|
|
MTRCallback(0);
|
|
}
|
|
}
|
|
|
|
/* 80373188-803731C8 36DAC8 0040+00 1/1 0/0 0/0 .text DBGHandler */
|
|
static void DBGHandler(s16 a, OSContext* b) {
|
|
*__PIRegs = 0x1000;
|
|
if (DBGCallback) {
|
|
DBGCallback(a, b);
|
|
}
|
|
}
|
|
|
|
/* 80373110-80373188 36DA50 0078+00 0/0 1/1 0/0 .text DBInitComm */
|
|
void DBInitComm(u8** a, MTRCallbackType b) {
|
|
BOOL interrupts = OSDisableInterrupts();
|
|
{
|
|
pEXIInputFlag = (u8*)EXIInputFlag;
|
|
pEXIInputFlag = &EXIInputFlag;
|
|
|
|
*a = pEXIInputFlag;
|
|
|
|
MTRCallback = b;
|
|
|
|
DBGEXIInit();
|
|
}
|
|
OSRestoreInterrupts(interrupts);
|
|
}
|
|
|
|
/* 803730BC-80373110 36D9FC 0054+00 0/0 1/1 0/0 .text DBInitInterrupts */
|
|
void DBInitInterrupts(void) {
|
|
__OSMaskInterrupts(0x18000);
|
|
__OSMaskInterrupts(0x40);
|
|
DBGCallback = &MWCallback;
|
|
__OSSetInterruptHandler(0x19, DBGHandler);
|
|
__OSUnmaskInterrupts(0x40);
|
|
}
|
|
|
|
static void CheckMailBox(void) {
|
|
u32 v;
|
|
DBGReadStatus(&v);
|
|
if (v & 1) {
|
|
DBGReadMailbox(&v);
|
|
v &= 0x1fffffff;
|
|
|
|
if ((v & 0x1f000000) == 0x1f000000) {
|
|
SendMailData = v;
|
|
RecvDataLeng = v & 0x7fff;
|
|
EXIInputFlag = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 80373020-803730BC 36D960 009C+00 0/0 2/2 0/0 .text DBQueryData */
|
|
u32 DBQueryData(void) {
|
|
EXIInputFlag = 0;
|
|
if (!RecvDataLeng) {
|
|
BOOL interrupts = OSDisableInterrupts();
|
|
CheckMailBox();
|
|
OSRestoreInterrupts(interrupts);
|
|
}
|
|
return RecvDataLeng;
|
|
}
|
|
|
|
/* 80372F94-80373020 36D8D4 008C+00 0/0 2/2 0/0 .text DBRead */
|
|
BOOL DBRead(u32* buffer, s32 count) {
|
|
u32 interrupts = OSDisableInterrupts();
|
|
u32 v = SendMailData & 0x10000 ? 0x1000 : 0;
|
|
|
|
DBGRead(v + 0x1e000, buffer, ROUND_UP(count, 4));
|
|
|
|
RecvDataLeng = 0;
|
|
EXIInputFlag = 0;
|
|
|
|
OSRestoreInterrupts(interrupts);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* 80372D34-80372F94 36D674 0260+00 0/0 1/1 0/0 .text DBWrite */
|
|
BOOL DBWrite(void* src, u32 size) {
|
|
u32 v;
|
|
u32 busyFlag;
|
|
BOOL interrupts = OSDisableInterrupts();
|
|
|
|
do {
|
|
_DBGReadStatus(&busyFlag);
|
|
} while (busyFlag & 2);
|
|
|
|
SendCount++;
|
|
v = ((SendCount & 1) ? 0x1000 : 0);
|
|
|
|
while (!DBGWrite(v | 0x1c000, src, ROUND_UP(size, 4)))
|
|
;
|
|
|
|
do {
|
|
_DBGReadStatus(&busyFlag);
|
|
} while (busyFlag & 2);
|
|
|
|
v = SendCount;
|
|
while (!DBGWriteMailbox((0x1f000000) | v << 0x10 | size))
|
|
;
|
|
|
|
do {
|
|
while (!_DBGReadStatus(&busyFlag))
|
|
;
|
|
} while (busyFlag & 2);
|
|
|
|
OSRestoreInterrupts(interrupts);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* 80372D30-80372D34 36D670 0004+00 0/0 1/1 0/0 .text DBOpen */
|
|
void DBOpen(void) {}
|
|
|
|
/* 80372D2C-80372D30 36D66C 0004+00 0/0 1/1 0/0 .text DBClose */
|
|
void DBClose(void) {} |