diff --git a/src/savestate/IGT.ld b/src/savestate/IGT.ld new file mode 100644 index 0000000..197f6d6 --- /dev/null +++ b/src/savestate/IGT.ld @@ -0,0 +1,4 @@ +$$ = 0; + +$C0$.savestate = 0; +$C2$.reset = TGCConsole2.startAppearTimer; diff --git a/src/savestate/IGT.s b/src/savestate/IGT.s new file mode 100644 index 0000000..4211905 --- /dev/null +++ b/src/savestate/IGT.s @@ -0,0 +1,81 @@ +.set slot, 0x817F0034 + +.set rH, 3 +.set rL, 5 +.set rNowH, 9 +.set rNowL, 10 +.set rMar, 11 +.set r817F, 12 +.set crSave, 7 + +.savestate: +.checkController: + lis r12, mPadStatus@ha + lhz r12, mPadStatus@l(r12) + cmplwi crSave, r12, 0x1 + beq crSave, .checkController.done + cmplwi r12, 0x2 + bnelr+ +.checkController.done: + +.prepare: + lwz rMar, gpMarDirector$r13(r13) + mr. rMar, rMar + beqlr + lis r817F, 0x817F + +.OSGetTime: + mftbu rNowH + mftbl rNowL + mftbu r0 + cmpw rNowH, r0 + bne .OSGetTime +## now - base + offset +### now -= base + lwz rH, 0x110(rMar) + lwz rL, 0x114(rMar) + subfc rNowL, rL, rNowL + subfe rNowH, rH, rNowH +## now += offset + lwz rH, 0xF0(rMar) + lwz rL, 0xF4(rMar) + addc rNowL, rL, rNowL + adde rNowH, rH, rNowH + +/** + * SAVE: diff = now - base + * LOAD: base = now - diff + */ + bne crSave, .load.apply +.save.apply: +## load base + lwz rH, 0xC8(rMar) + lwz rL, 0xCC(rMar) +## diff = now - base + subfc rL, rL, rNowL + subfe rH, rH, rNowH +## store diff + stw rH, slot@l(r817F) + stw rL, slot+4@l(r817F) + blr + +.load.apply: +## load diff + lwz rH, slot@l(r817F) + lwz rL, slot+4@l(r817F) +## base = now - diff + subfc rL, rL, rNowL + subfe rH, rH, rNowH +## store base + stw rH, 0xC8(rMar) + stw rL, 0xCC(rMar) + blr + +/** reset stored time diff to 0 in TGCConsole2::startAppearTimer() */ +.reset: + lis r12, 0x817F + li r11, 0 + stw r11, slot@l(r12) + stw r11, slot+4@l(r12) +## orig + mflr r0 diff --git a/src/savestate/QFT.s b/src/savestate/QFT.s new file mode 100644 index 0000000..e3ada28 --- /dev/null +++ b/src/savestate/QFT.s @@ -0,0 +1,38 @@ +.set slot, 0x817F0030 + +.set r817F, 3 +.set rMar, 5 +.set crSave, 7 + +.prepare: + lwz rMar, gpMarDirector$r13(r13) + mr. rMar, rMar + beqlr + lis r817F, 0x817F + +.checkController: + lis r12, mPadStatus@ha + lhz r12, mPadStatus@l(r12) + cmplwi crSave, r12, 0x1 + beq crSave, .save + cmplwi r12, 0x2 + bnelr+ + +.load: +## restore Global QF + lwz r0, slot@l(r817F) + stw r0, 0x5C(rMar) +### also set QF Section Timer Last Freezed Time + stw r0, 0x3CC(r817F) +## unfreeze QFT +### QF Timer Duration of timer freeze (in frames) = 0 + li r0, 0 + stw r0, 0xBC(r817F) + #blr +## save after load is effectively nop + +.save: +### store Global QF + lwz r0, 0x5C(rMar) + stw r0, slot@l(r817F) + blr diff --git a/src/savestate/RedCoin.s b/src/savestate/RedCoin.s new file mode 100644 index 0000000..0878707 --- /dev/null +++ b/src/savestate/RedCoin.s @@ -0,0 +1,92 @@ +# (flag: u8, count: u8) +.set slot, 0x817F002C + +.set r817F, 3 +.set rFlag, 5 +.set rItemHead, 9 +.set rItemPtr, 10 +.set rFM, 11 +.set crSave, 7 + +.checkController: + lis r12, mPadStatus@ha + lhz r12, mPadStatus@l(r12) + cmplwi crSave, r12, 0x1 + beq- crSave, .checkController.done + cmplwi r12, 0x2 + bnelr+ +.checkController.done: + +.getItemInfo: + lwz r12, gpItemManager$r13(r13) + mr. r12, r12 + beqlr- +## [14] count +## [18] items + lwz rItemHead, 0x18(r12) + lwz rItemPtr, 0x14(r12) + slwi rItemPtr, rItemPtr, 2 + add rItemPtr, rItemHead, rItemPtr + +.init.regs: + lis r817F, 0x817F + lwz rFM, TFlagManager.smInstance$r13(r13) + +.loadState: +## r0 = (0, 0, flag, count) + lhz r0, slot@l(r817F) +## rFlag = (flag, 0, 0, 0) + rlwinm rFlag, r0, 16, 0, 7 +.loadState.flag: +## skip restoring flag if saving + beq crSave, .loadState.flag.done +## r0 = saved red coin count + rlwinm. r0, r0, 0, 0xFF +## restore to FlagManager + stw r0, 0xF4(rFM) # red coin count +## set flag = 0 if red coin switch pressed && saved count == 0 + bne .loadState.flag.done + lbz r0, 0xE5(rFM) # red coin switch pressed (0x02) + andi. r0, r0, 0x02 + beq .loadState.flag.done + li rFlag, 0 +.loadState.flag.done: + +.item.loop: + cmplw rItemPtr, rItemHead + ble- .item.loop.done +## r12 = item + lwzu r12, -4(rItemPtr) +## check vtable + lwz r0, 0(r12) + xoris r0, r0, TCoinRed.__vt@h + cmplwi r0, TCoinRed.__vt@l + bne+ .item.loop.next +## r0 = item->flag + lwz r0, 0xF0(r12) +### rotate rFlag to next slot + rlwinm rFlag, rFlag, 1, 0, 31 +.item.loop.load: +## store only + beq crSave, .item.loop.load.done +## set 0x1, 0x8 bit from saved flag + rlwimi r0, rFlag, 0, 0x1 + rlwimi r0, rFlag, 3, 0x8 +## write back to item->flag + stw r0, 0xF0(r12) +.item.loop.load.done: +## save item's 0x1 bit to rFlag +## effectively nop for load + rlwimi rFlag, r0, 0, 0x1 +.item.loop.next: + b .item.loop +.item.loop.done: + +.writeBack.save: + bnelr crSave +## save red coin flags + stb rFlag, slot@l(r817F) +## save red coin count + lwz r0, 0xF4(rFM) + stb r0, slot+1@l(r817F) + blr