diff options
author | jiangzhengwenjz <jiangzhengwenjzw@qq.com> | 2019-12-29 06:24:26 +0800 |
---|---|---|
committer | jiangzhengwenjz <jiangzhengwenjzw@qq.com> | 2020-01-09 12:38:57 +0800 |
commit | 973cb394b23002acde7d7ea19abc754019dd106c (patch) | |
tree | cf05524128224aceb57dd33f84ea4fdaacb4ecb3 /src | |
parent | 8f1a8972c19f5cd2522c9e7982bd330ac05305e9 (diff) |
librfu through 0x81E13F0
Diffstat (limited to 'src')
-rw-r--r-- | src/agb_flash.c | 2 | ||||
-rw-r--r-- | src/librfu_rfu.c | 736 | ||||
-rw-r--r-- | src/librfu_stwi.c | 21 |
3 files changed, 748 insertions, 11 deletions
diff --git a/src/agb_flash.c b/src/agb_flash.c index 5b171abcb..7eb4ae737 100644 --- a/src/agb_flash.c +++ b/src/agb_flash.c @@ -74,7 +74,7 @@ u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void)) return 1; sTimerNum = timerNum; - sTimerReg = ®_TMCNT(sTimerNum); + sTimerReg = ®_TMCNT_L(sTimerNum); *intrFunc = FlashTimerIntr; return 0; } diff --git a/src/librfu_rfu.c b/src/librfu_rfu.c new file mode 100644 index 000000000..96f4e9519 --- /dev/null +++ b/src/librfu_rfu.c @@ -0,0 +1,736 @@ +#include "global.h" +#include "librfu.h" + +void rfu_CB_defaultCallback(u8, u16); +void rfu_CB_reset(u8, u16); +void rfu_CB_configGameData(u8, u16); +void rfu_CB_stopMode(u8, u16); +void rfu_CB_startSearchChild(u8, u16); +void rfu_CB_pollAndEndSearchChild(u8, u16); +void rfu_CB_startSearchParent(u8, u16); +void rfu_CB_pollSearchParent(u8, u16); +void rfu_CB_pollConnectParent(u8, u16); +void rfu_CB_pollConnectParent(u8, u16); +s32 sub_81E349C(u8); +void rfu_enableREQCallback(bool8); +void rfu_STC_readChildList(void); +void rfu_STC_readParentCandidateList(void); +void rfu_STC_REQ_callback(u8, u16); +void rfu_STC_removeLinkData(u8, u8); +void rfu_STC_fastCopy(u8 **a1, u8 **a2, s32 a3); +void rfu_STC_clearLinkStatus(u8); +void rfu_NI_checkCommFailCounter(void); + +extern const char _Str_RFU_MBOOT[]; + +struct RfuStruct *gRfuState; +ALIGNED(8) struct RfuSlotStatusUNI *gRfuSlotStatusUNI[4]; +struct RfuSlotStatusNI *gRfuSlotStatusNI[4]; +struct RfuLinkStatus *gRfuLinkStatus; +struct RfuStatic *gRfuStatic; +struct RfuFixed *gRfuFixed; +ALIGNED(8) struct Unk_3007470 gUnknown_3007470; + +u16 rfu_initializeAPI(struct Unk_3001190 *unk0, u16 unk1, IntrFunc *interrupt, bool8 copyInterruptToRam) +{ + u16 i; + u16 *dst; + const u16 *src; + u16 r3; + + // is in EWRAM? + if (((u32)unk0 & 0xF000000) == 0x2000000 && copyInterruptToRam) + return 2; + // is not 4-byte aligned? + if ((u32)unk0 & 3) + return 2; + // Nintendo pls, just use a ternary for once + if (copyInterruptToRam) + { + // An assert/debug print may have existed before, ie + // printf("%s %u < %u", "somefile.c:12345", unk1, num) + // to push this into r3? + r3 = 0xe64; + if (unk1 < r3) + return 1; + } + if (!copyInterruptToRam) + { + r3 = 0x504; // same as above, this should be r3 not r0 + if (unk1 < r3) + return 1; + } + gRfuLinkStatus = &unk0->linkStatus; + gRfuStatic = &unk0->static_; + gRfuFixed = &unk0->fixed; + gRfuSlotStatusNI[0] = &unk0->NI[0]; + gRfuSlotStatusUNI[0] = &unk0->UNI[0]; + for (i = 1; i < NELEMS(gRfuSlotStatusNI); ++i) + { + gRfuSlotStatusNI[i] = &gRfuSlotStatusNI[i - 1][1]; + gRfuSlotStatusUNI[i] = &gRfuSlotStatusUNI[i - 1][1]; + } + // TODO: Is it possible to fix the following 2 statements? + // It's equivalent to: + // gRfuFixed->STWIBuffer = &unk0->intr; + // STWI_init_all(&unk0->intr, interrupt, copyInterruptToRam); + gRfuFixed->STWIBuffer = (struct RfuIntrStruct *)&gRfuSlotStatusUNI[3][1]; + STWI_init_all((struct RfuIntrStruct *)&gRfuSlotStatusUNI[3][1], interrupt, copyInterruptToRam); + rfu_STC_clearAPIVariables(); + for (i = 0; i < NELEMS(gRfuSlotStatusNI); ++i) + { + gRfuSlotStatusNI[i]->recvBuffer = 0; + gRfuSlotStatusNI[i]->recvBufferSize = 0; + gRfuSlotStatusUNI[i]->recvBuffer = 0; + gRfuSlotStatusUNI[i]->recvBufferSize = 0; + } + src = (const u16 *)((u32)&rfu_STC_fastCopy & ~1); + dst = gRfuFixed->fastCopyBuffer; + // rfu_REQ_changeMasterSlave is the function next to rfu_STC_fastCopy + for (r3 = ((void *)rfu_REQ_changeMasterSlave - (void *)rfu_STC_fastCopy) / sizeof(u16), --r3; r3 != 0xFFFF; --r3) + *dst++ = *src++; + gRfuFixed->fastCopyPtr = (u8 *)gRfuFixed->fastCopyBuffer + 1; + return 0; +} + +void rfu_STC_clearAPIVariables(void) +{ + u16 IMEBackup = REG_IME; + u8 i, r4; + + REG_IME = 0; + r4 = gRfuStatic->flags; + CpuFill16(0, gRfuStatic, sizeof(struct RfuStatic)); + gRfuStatic->flags = r4 & 8; + CpuFill16(0, gRfuLinkStatus, sizeof(struct RfuLinkStatus)); + gRfuLinkStatus->watchInterval = 4; + gRfuStatic->nowWatchInterval = 0; + gRfuLinkStatus->connMode = 0xFF; + rfu_clearAllSlot(); + gRfuStatic->SCStartFlag = 0; + for (i = 0; i < NELEMS(gRfuStatic->cidBak); ++i) + gRfuStatic->cidBak[i] = 0; + REG_IME = IMEBackup; +} + +void rfu_REQ_PARENT_resumeRetransmitAndChange(void) +{ + STWI_set_Callback_M(rfu_STC_REQ_callback); + STWI_send_ResumeRetransmitAndChangeREQ(); +} + +u16 rfu_UNI_PARENT_getDRAC_ACK(u8 *ackFlag) +{ + struct RfuIntrStruct *buf; + *ackFlag = 0; + if (gRfuLinkStatus->connMode != 1) + return 0x300; + buf = rfu_getSTWIRecvBuffer(); + switch (buf->rxPacketAlloc.rfuPacket8.data[0]) + { + case 40: + case 54: + if (buf->rxPacketAlloc.rfuPacket8.data[1] == 0) + *ackFlag = gRfuLinkStatus->connSlotFlag; + else + *ackFlag = buf->rxPacketAlloc.rfuPacket8.data[4]; + return 0; + default: + return 0x10; + } +} + +void rfu_setTimerInterrupt(u8 which, IntrFunc *intr) +{ + STWI_init_timer(intr, which); +} + +struct RfuIntrStruct *rfu_getSTWIRecvBuffer(void) +{ + return gRfuFixed->STWIBuffer; +} + +void rfu_setMSCCallback(void (*callback)(u16)) +{ + STWI_set_Callback_S(callback); +} + +void rfu_setREQCallback(void (*callback)(u16, u16)) +{ + gRfuFixed->reqCallback = callback; + rfu_enableREQCallback(callback != NULL); +} + +void rfu_enableREQCallback(bool8 enable) +{ + if (enable) + gRfuStatic->flags |= 8; + else + gRfuStatic->flags &= 0xF7; +} + +void rfu_STC_REQ_callback(u8 r5, u16 reqResult) +{ + STWI_set_Callback_M(rfu_CB_defaultCallback); + gRfuStatic->reqResult = reqResult; + if (gRfuStatic->flags & 8) + gRfuFixed->reqCallback(r5, reqResult); +} + +void rfu_CB_defaultCallback(u8 r0, u16 reqResult) +{ + s32 r5; + u8 i; + + if (r0 == 0xFF) + { + if (gRfuStatic->flags & 8) + gRfuFixed->reqCallback(r0, reqResult); + r5 = gRfuLinkStatus->connSlotFlag | gRfuLinkStatus->linkLossSlotFlag; + for (i = 0; i < 4; ++i) + if ((r5 >> i) & 1) + rfu_STC_removeLinkData(i, 1); + gRfuLinkStatus->connMode = 0xFF; + } +} + +u16 rfu_waitREQComplete(void) +{ + STWI_poll_CommandEnd(); + return gRfuStatic->reqResult; +} + +void rfu_REQ_RFUStatus(void) +{ + STWI_set_Callback_M(rfu_STC_REQ_callback); + STWI_send_SystemStatusREQ(); +} + +u32 rfu_getRFUStatus(u8 *status) +{ + if (gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[0] != 0x93) + return 0x10; + if (STWI_poll_CommandEnd() == 0) + *status = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[7]; + else + *status = 0xFF; + return 0; +} + +s32 rfu_MBOOT_CHILD_inheritanceLinkStatus(void) +{ + const char *s1 = _Str_RFU_MBOOT; + char *s2 = (char *)0x30000F0; + u16 checksum; + u16 *r2; + u8 i; + + while (*s1 != '\0') + if (*s1++ != *s2++) + return 1; + r2 = (u16 *)0x3000000; + checksum = 0; + for (i = 0; i < 90; ++i) + checksum += *r2++; + if (checksum != *(u16 *)0x30000FA) + return 1; + CpuCopy16((u16 *)0x3000000, gRfuLinkStatus, sizeof(struct RfuLinkStatus)); + gRfuStatic->flags |= 0x80; + return 0; +} + +void rfu_REQ_stopMode(void) +{ + vu32 *timerReg; + + if (REG_IME == 0) + { + rfu_STC_REQ_callback(61, 6); + gRfuState->error = 6; + } + else + { + AgbRFU_SoftReset(); + rfu_STC_clearAPIVariables(); + if (sub_81E349C(8) == 0x8001) + { + timerReg = ®_TMCNT(gRfuState->timerSelect); + *timerReg = 0; + *timerReg = (TIMER_ENABLE | TIMER_1024CLK) << 16; + while (*timerReg << 16 < 262 << 16) + ; + *timerReg = 0; + STWI_set_Callback_M(rfu_CB_stopMode); + STWI_send_StopModeREQ(); + } + else + { + REG_SIOCNT = SIO_MULTI_MODE; + rfu_STC_REQ_callback(61, 0); + } + } +} + +void rfu_CB_stopMode(u8 a1, u16 reqResult) +{ + if (reqResult == 0) + REG_SIOCNT = SIO_MULTI_MODE; + rfu_STC_REQ_callback(a1, reqResult); +} + +s32 rfu_REQBN_softReset_and_checkID(void) +{ + s32 r2; + + if (REG_IME == 0) + return -1; + AgbRFU_SoftReset(); + rfu_STC_clearAPIVariables(); + if ((r2 = sub_81E349C(30)) == 0) + REG_SIOCNT = SIO_MULTI_MODE; + return r2; +} + +void rfu_REQ_reset(void) +{ + STWI_set_Callback_M(rfu_CB_reset); + STWI_send_ResetREQ(); +} + +void rfu_CB_reset(u8 a1, u16 reqResult) +{ + if (reqResult == 0) + rfu_STC_clearAPIVariables(); + rfu_STC_REQ_callback(a1, reqResult); +} + +void rfu_REQ_configSystem(u16 r4, u8 r5, u8 r6) +{ + STWI_set_Callback_M(rfu_STC_REQ_callback); + STWI_send_SystemConfigREQ((r4 & 3) | 0x3C, r5, r6); + if (r6 == 0) + { + gRfuStatic->unk_1a = 1; + } + else + { + u16 IMEBackup = REG_IME; + + REG_IME = 0; + gRfuStatic->unk_1a = Div(600, r6); + REG_IME = IMEBackup; + } +} + +void rfu_REQ_configGameData(u8 r6, u16 r2, const u8 *r4, const u8 *r7) +{ + u8 sp[16]; + u8 i; + u8 r3; + const u8 *r5 = r4; + const u8 *r1; + + sp[0] = r2; + sp[1] = r2 >> 8; + if (r6 != 0) + sp[1] = (r2 >> 8) | 0x80; + for (i = 2; i < 15; ++i) + sp[i] = *r4++; + r3 = 0; + r1 = r7; + for (i = 0; i < 8; ++i) + { + r3 += *r1++; + r3 += *r5++; + } + sp[15] = ~r3; + if (r6 != 0) + sp[14] = 0; + STWI_set_Callback_M(rfu_CB_configGameData); + STWI_send_GameConfigREQ(sp, r7); +} + +void rfu_CB_configGameData(u8 ip, u16 r7) +{ + s32 r2, r3; + u8 *r4; + u8 i; + u8 *r1; + + if (r7 == 0) + { + r1 = gRfuState->txPacket->rfuPacket8.data; + r2 = gRfuLinkStatus->my.serialNum = r1[4]; + gRfuLinkStatus->my.serialNum = (r1[5] << 8) | r2; + r4 = &r1[6]; + if (gRfuLinkStatus->my.serialNum & 0x8000) + { + gRfuLinkStatus->my.serialNum = gRfuLinkStatus->my.serialNum ^ 0x8000; + gRfuLinkStatus->my.multibootFlag = 1; + } + else + { + gRfuLinkStatus->my.multibootFlag = 0; + } + for (i = 0; i < NELEMS(gRfuLinkStatus->my.gname) - 2; ++i) + gRfuLinkStatus->my.gname[i] = *r4++; + ++r4; + for (i = 0; i < NELEMS(gRfuLinkStatus->my.uname) - 1; ++i) + gRfuLinkStatus->my.uname[i] = *r4++; + } + rfu_STC_REQ_callback(ip, r7); +} + +void rfu_REQ_startSearchChild(void) +{ + u16 r1; + + STWI_set_Callback_M(rfu_CB_defaultCallback); + STWI_send_SystemStatusREQ(); + r1 = STWI_poll_CommandEnd(); + if (r1 == 0) + { + if (gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[7] == 0) + rfu_STC_clearLinkStatus(1); + } + else + { + rfu_STC_REQ_callback(25, r1); + } + STWI_set_Callback_M(rfu_CB_startSearchChild); + STWI_send_SC_StartREQ(); +} + +void rfu_CB_startSearchChild(u8 r3, u16 reqResult) +{ + if (reqResult == 0) + gRfuStatic->SCStartFlag = 1; + rfu_STC_REQ_callback(r3, reqResult); +} + +void rfu_STC_clearLinkStatus(u8 r4) +{ + u8 i; + + rfu_clearAllSlot(); + if (r4 != 0) + { + CpuFill16(0, gRfuLinkStatus->partner, sizeof(gRfuLinkStatus->partner)); + gRfuLinkStatus->findParentCount = 0; + } + for (i = 0; i < NELEMS(gRfuLinkStatus->strength); ++i) + gRfuLinkStatus->strength[i] = 0; + gRfuLinkStatus->connCount = 0; + gRfuLinkStatus->connSlotFlag = 0; + gRfuLinkStatus->linkLossSlotFlag = 0; + gRfuLinkStatus->getNameFlag = 0; +} + +void rfu_REQ_pollSearchChild(void) +{ + STWI_set_Callback_M(rfu_CB_pollAndEndSearchChild); + STWI_send_SC_PollingREQ(); +} + +void rfu_REQ_endSearchChild(void) +{ + STWI_set_Callback_M(rfu_CB_pollAndEndSearchChild); + STWI_send_SC_EndREQ(); +} + +void rfu_CB_pollAndEndSearchChild(u8 r4, u16 reqResult) +{ + if (reqResult == 0) + rfu_STC_readChildList(); + if (r4 == 26) + { + if (gRfuLinkStatus->my.id == 0) + { + STWI_set_Callback_M(rfu_CB_defaultCallback); + STWI_send_SystemStatusREQ(); + if (STWI_poll_CommandEnd() == 0) + gRfuLinkStatus->my.id = *(u16 *)&gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket32.data[0]; + } + } + else if (r4 == 27) + { + if (gRfuLinkStatus->connMode == 255) + gRfuLinkStatus->my.id = 0; + gRfuStatic->SCStartFlag = 0; + } + rfu_STC_REQ_callback(r4, reqResult); +} + +void rfu_STC_readChildList(void) +{ + u32 r5; + u8 r8 = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[1]; + u8 *r4; + u8 i; + u8 sp[4]; + u8 r2; + + if (r8 != 0) + { + r5 = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket32.data[0]; + STWI_set_Callback_M(rfu_CB_defaultCallback); + STWI_send_LinkStatusREQ(); + if (STWI_poll_CommandEnd() == 0) + { + r4 = &gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[4]; + for (i = 0; i < NELEMS(sp); ++i) + sp[i] = *r4++; + } + gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket32.data[0] = r5; + } + for (r4 = &gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[4]; + r8 != 0; + r4 += 4) + { + r2 = r4[2]; + if (r2 < 4 && !((gRfuLinkStatus->connSlotFlag >> r2) & 1) && !((gRfuLinkStatus->linkLossSlotFlag >> r2) & 1)) + { + if (sp[r2] != 0) + ++gRfuStatic->lsFixedCount[r2]; + if (gRfuStatic->lsFixedCount[r2] >= 4) + { + gRfuStatic->lsFixedCount[r2] = 0; + gRfuLinkStatus->strength[r2] = 0xFF; + gRfuLinkStatus->connSlotFlag |= 1 << r2; + ++gRfuLinkStatus->connCount; + gRfuLinkStatus->partner[r2].id = *(u16 *)r4; + gRfuLinkStatus->partner[r2].slot = r2; + gRfuLinkStatus->connMode = 1; + gRfuStatic->flags &= 0x7F; + gRfuStatic->cidBak[r2] = gRfuLinkStatus->partner[r2].id; + } + } + --r8; + } +} + +void rfu_REQ_startSearchParent(void) +{ + STWI_set_Callback_M(rfu_CB_startSearchParent); + STWI_send_SP_StartREQ(); +} + +void rfu_CB_startSearchParent(u8 r5, u16 reqResult) +{ + if (reqResult == 0) + rfu_STC_clearLinkStatus(0); + rfu_STC_REQ_callback(r5, reqResult); +} + +void rfu_REQ_pollSearchParent(void) +{ + STWI_set_Callback_M(rfu_CB_pollSearchParent); + STWI_send_SP_PollingREQ(); +} + +void rfu_CB_pollSearchParent(u8 r5, u16 reqResult) +{ + if (reqResult == 0) + rfu_STC_readParentCandidateList(); + rfu_STC_REQ_callback(r5, reqResult); +} + +void rfu_REQ_endSearchParent(void) +{ + STWI_set_Callback_M(rfu_STC_REQ_callback); + STWI_send_SP_EndREQ(); +} + +void rfu_STC_readParentCandidateList(void) +{ + u8 r7, r6, r5, r4, r3; + u8 *r1, *r2; + struct RfuTgtData *r4_; + + CpuFill16(0, gRfuLinkStatus->partner, sizeof(gRfuLinkStatus->partner)); + r2 = &gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[0]; + r7 = r2[1]; + r2 += 4; + gRfuLinkStatus->findParentCount = 0; + for (r6 = 0; r6 < 4 && r7 != 0; ++r6) + { + r7 -= 7; + r1 = r2 + 6; + r2 += 19; + r5 = ~*r2; + ++r2; + r4 = 0; + for (r3 = 0; r3 < 8; ++r3) + { + r4 += *r2++; + r4 += *r1++; + } + if (r4 == r5) + { + r2 -= 28; + r4_ = &gRfuLinkStatus->partner[gRfuLinkStatus->findParentCount]; + r4_->id = *(u16 *)r2; + r2 += 2; + r4_->slot = *r2; + r2 += 2; + r4_->serialNum = *(u16 *)r2 & 0x7FFF; + if (*(u16 *)r2 & 0x8000) + r4_->multibootFlag = 1; + else + r4_->multibootFlag = 0; + r2 += 2; + for (r3 = 0; r3 < NELEMS(r4_->gname) - 2; ++r3) + r4_->gname[r3] = *r2++; + ++r2; + for (r3 = 0; r3 < NELEMS(r4_->uname) - 1; ++r3) + r4_->uname[r3] = *r2++; + ++gRfuLinkStatus->findParentCount; + } + } +} + +void rfu_REQ_startConnectParent(u16 r4) +{ + u16 r3 = 0; + u8 i; + for (i = 0; i < NELEMS(gRfuLinkStatus->partner) && gRfuLinkStatus->partner[i].id != r4; ++i) + ; + if (i == 4) + r3 = 256; + if (r3 == 0) + { + gRfuStatic->tryPid = r4; + STWI_set_Callback_M(rfu_STC_REQ_callback); + STWI_send_CP_StartREQ(r4); + } + else + { + rfu_STC_REQ_callback(31, r3); + } +} + +void rfu_REQ_pollConnectParent(void) +{ + STWI_set_Callback_M(rfu_CB_pollConnectParent); + STWI_send_CP_PollingREQ(); +} + +void rfu_CB_pollConnectParent(u8 sp24, u16 sp28) +{ + u16 id; + u8 slot; + u8 r2, r5; + struct RfuTgtData *r9; + struct RfuTgtData sp; + + if (sp28 == 0) + { + id = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket32.data[0]; + slot = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[6]; + if (gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[7] == 0) + { + r2 = 1 << slot; + if (!(r2 & gRfuLinkStatus->connSlotFlag)) + { + gRfuLinkStatus->connSlotFlag |= r2; + gRfuLinkStatus->linkLossSlotFlag &= ~r2; + gRfuLinkStatus->my.id = id; + ++gRfuLinkStatus->connCount; + gRfuLinkStatus->connMode = 0; + gRfuStatic->flags |= 0x80; + for (r5 = 0; r5 < NELEMS(gRfuLinkStatus->partner); ++r5) + { + if (gRfuLinkStatus->partner[r5].id == gRfuStatic->tryPid) + { + if (gRfuLinkStatus->findParentCount != 0) + { + r9 = &sp; + CpuCopy16(&gRfuLinkStatus->partner[r5], &sp, sizeof(struct RfuTgtData)); + CpuFill16(0, gRfuLinkStatus->partner, sizeof(gRfuLinkStatus->partner)); + gRfuLinkStatus->findParentCount = 0; + } + else + { + r9 = &gRfuLinkStatus->partner[r5]; + } + break; + } + } + if (r5 < 4) + { + CpuCopy16(r9, &gRfuLinkStatus->partner[slot], sizeof(struct RfuTgtData)); + gRfuLinkStatus->partner[slot].slot = slot; + } + } + } + } + rfu_STC_REQ_callback(sp24, sp28); +} + +u16 rfu_getConnectParentStatus(u8 *status, u8 *r1) +{ + u8 r0, *r2; + + *status = 0xFF; + r2 = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data; + r0 = r2[0] + 96; + if (r0 <= 1) + { + r2 += 6; + *r1 = r2[0]; + *status = r2[1]; + return 0; + } + return 0x10; +} + +void rfu_REQ_endConnectParent(void) +{ + STWI_set_Callback_M(rfu_CB_pollConnectParent); + STWI_send_CP_EndREQ(); + if (gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[6] < 4) + gRfuStatic->linkEmergencyFlag[gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[6]] = 0; +} + +u16 rfu_syncVBlank(void) +{ + u8 r3, r4; + s32 r5; + + rfu_NI_checkCommFailCounter(); + if (gRfuLinkStatus->connMode == 0xFF) + return 0; + if (gRfuStatic->nowWatchInterval != 0) + --gRfuStatic->nowWatchInterval; + r3 = rfu_getMasterSlave(); + if (!(gRfuStatic->flags & 2)) + { + if (r3 == 0) + { + gRfuStatic->flags |= 4; + gRfuStatic->watchdogTimer = 360; + } + } + else if (r3 != 0) + { + gRfuStatic->flags &= 0xFB; + } + if (r3 != 0) + gRfuStatic->flags &= 0xFD; + else + gRfuStatic->flags |= 2; + if (!(gRfuStatic->flags & 4)) + return 0; + if (gRfuStatic->watchdogTimer == 0) + { + gRfuStatic->flags &= 0xFB; + r5 = gRfuLinkStatus->connSlotFlag | gRfuLinkStatus->linkLossSlotFlag; + for (r4 = 0; r4 < 4; ++r4) + if ((r5 >> r4) & 1) + rfu_STC_removeLinkData(r4, 1); + gRfuLinkStatus->connMode = 0xFF; + return 1; + } + --gRfuStatic->watchdogTimer; + return 0; +} diff --git a/src/librfu_stwi.c b/src/librfu_stwi.c index fe8a4ef76..c8df0ccfa 100644 --- a/src/librfu_stwi.c +++ b/src/librfu_stwi.c @@ -64,7 +64,7 @@ void AgbRFU_SoftReset(void) timerH = ®_TMCNT_H(gRfuState->timerSelect); *timerH = 0; *timerL = 0; - *timerH = 0x83; + *timerH = TIMER_ENABLE | TIMER_1024CLK; while (*timerL <= 0x11) REG_RCNT = 0x80A2; *timerH = 3; @@ -117,12 +117,13 @@ void STWI_init_Callback_S(void) STWI_set_Callback_S(NULL); } -void STWI_set_Callback_M(void (*callbackM)()) +// The callback can take 2 or 3 arguments. +void STWI_set_Callback_M(void *callbackM) { gRfuState->callbackM = callbackM; } -void STWI_set_Callback_S(void (*callbackS)()) +void STWI_set_Callback_S(void (*callbackS)(u16)) { gRfuState->callbackS = callbackS; } @@ -193,7 +194,7 @@ void STWI_send_ConfigStatusREQ(void) } } -void STWI_send_GameConfigREQ(u8 *unk1, u8 *data) +void STWI_send_GameConfigREQ(const u8 *unk1, const u8 *data) { u8 *packetBytes; s32 i; @@ -496,7 +497,7 @@ static void STWI_intr_timer(void) gRfuState->timerActive = 1; STWI_stop_timer(); STWI_reset_ClockCounter(); - if (gRfuState->callbackM) + if (gRfuState->callbackM != NULL) gRfuState->callbackM(255, 0); break; } @@ -546,7 +547,7 @@ static u16 STWI_init(u8 request) if (!REG_IME) { gRfuState->error = 6; - if (gRfuState->callbackM) + if (gRfuState->callbackM != NULL) gRfuState->callbackM(request, gRfuState->error); return TRUE; } @@ -554,14 +555,14 @@ static u16 STWI_init(u8 request) { gRfuState->error = 2; gRfuState->unk_2c = FALSE; - if (gRfuState->callbackM) + if (gRfuState->callbackM != NULL) gRfuState->callbackM(request, gRfuState->error); return TRUE; } else if(!gRfuState->msMode) { gRfuState->error = 4; - if (gRfuState->callbackM) + if (gRfuState->callbackM != NULL) gRfuState->callbackM(request, gRfuState->error, gRfuState); return TRUE; } @@ -617,14 +618,14 @@ static s32 STWI_restart_Command(void) { gRfuState->error = 1; gRfuState->unk_2c = 0; - if (gRfuState->callbackM) + if (gRfuState->callbackM != NULL) gRfuState->callbackM(gRfuState->reqActiveCommand, gRfuState->error); } else { gRfuState->error = 1; gRfuState->unk_2c = 0; - if (gRfuState->callbackM) + if (gRfuState->callbackM != NULL) gRfuState->callbackM(gRfuState->reqActiveCommand, gRfuState->error); gRfuState->state = 4; // TODO: what's 4 } |