Skip to content

Instantly share code, notes, and snippets.

@BitPatty
Forked from QbeRoot/qftimer.s
Created September 16, 2024 17:49
Show Gist options
  • Save BitPatty/008c328743d490be4b61f4fb09f61482 to your computer and use it in GitHub Desktop.
Save BitPatty/008c328743d490be4b61f4fb09f61482 to your computer and use it in GitHub Desktop.
Source for Quarterframe Timer
qftRect = 0x817F0094 # u32[4] coordinates of the textbox relative to the top left corner of the screen, in order: left X, top Y, right X, bottom Y
qftFormat = 0x817F00A4 # string printf format string of the timer, containing 3 specifiers for minutes, seconds and milliseconds in order
qftStop = 0x817F00B2 # bool if nonzero, the timer is stopped on the value of qftOffset, otherwise it continues to run
qftReset = 0x817F00B3 # bool if nonzero, the timer will restart from 0 in the next area, otherwise it will continue where it left off
qftOffset = 0x817F00B4 # u32 cumulative time spent in previous areas since the last reset, includes current area iff qftStop is true
qftFreezeTime = 0x817F00B8 # u32 fixed time to be displayed if qftFreezeFor > 0 and qftStop is false, only includes current area
qftFreezeFor = 0x817F00BC # u32 duration of a timer freeze (in frames)
qftTextBox = 0x817F0110 # J2DTextBox textbox used to render the timer (0x128 bytes), will be replaced with proper HUD elements before 1.0
# gpMarDirector->_5c is the total number of QFs elapsed in the current area, including pauses
# Assumptions:
# All qft* labels defined above have values within [0x817F0000, 0x817F7FFF]
# qftReset == qftStop + 1
# Constants are initialized by a Gecko code with the following values:
# *qftRect = [16, 416, 640, 480]
# *qftFormat = "%u:%02u.%03u"
# on HUD setup, init textbox and reset qftFreezeFor. to reset timer, qftStop 0; qftOffset = -4 (headstart to align with SGT)
@direct__12TMarDirectorFv + 0x88
stb r0, 0x260(r26) # replaced instruction
lis r7, 0x817F
lbz r0, qftReset@l(r7)
cmpwi r0, 0
li r4, 0
stw r4, qftFreezeFor@l(r7)
beq- noreset
sth r4, qftStop@l(r7) # unset qftStop and qftReset
li r0, -4
stw r0, qftOffset@l(r7)
noreset:
ori r3, r7, qftTextBox@l
ori r5, r7, qftRect@l
lwz r6, gpSystemFont-_SDA_BASE_(r13)
lwz r6, 0x48(r6)
ori r7, r7, qftFormat@l
li r8, 2
li r9, 0
lis r12, __ct__10J2DTextBoxFUlRC7JUTRectPC7ResFONTPCc18J2DTextBoxHBinding18J2DTextBoxVBinding@h
ori r12, r12, __ct__10J2DTextBoxFUlRC7JUTRectPC7ResFONTPCc18J2DTextBoxHBinding18J2DTextBoxVBinding@l
mtlr r12
blrl
# on HUD update, if qftFreezeFor > 0, decrement it and show qftFreezeTime + qftOffset, else show gpMarDirector->_5c + qftOffset
@perform__11TGCConsole2FUlPQ26JDrama9TGraphics + (0x43E4 on JP, 0x36DC on US, 0x379C on PAL, 0x3798 on JPA)
lis r3, 0x817F
lbz r4, qftStop@l(r3)
lwz r8, qftOffset@l(r3)
cmpwi r4, 0
bne+ bound
lwz r4, qftFreezeFor@l(r3)
cmpwi r4, 0
bne+ freeze
lwz r8, gpMarDirector-_SDA_BASE_(r13)
lwz r8, 0x5C(r8)
b offset
freeze:
subi r4, r4, 1
stw r4, qftFreezeFor@l(r3)
lwz r8, qftFreezeTime@l(r3)
offset:
lwz r0, qftOffset@l(r3)
add r8, r8, r0
bound:
lis r7, 0xA
ori r7, r7, 0xF9B0 # 99:59.994
cmpw r7, r8
bge+ update
mr r8, r7
stb r7, qftStop@l(r3)
stw r7, qftOffset@l(r3)
update:
mulli r8, r8, 1001
li r0, 120
divwu r8, r8, r0
li r0, 1000
divwu r7, r8, r0
mullw r0, r7, r0
sub r8, r8, r0
li r0, 60
divwu r6, r7, r0
mullw r0, r6, r0
sub r7, r7, r0
addi r5, r3, qftFormat@l
li r4, 15
lwz r3, 0x210(r3)
crclr 6
lis r12, snprintf@h
ori r12, r12, snprintf@l
mtlr r12
blrl
lis r3, 0x817F
ori r3, r3, qftTextBox@l
li r4, 0
li r5, 0
addi r6, r1, # 0xE90 on JP, 0xBD0 on US, 0xBE4 on PAL, 0xBEC on JPA
li r7, 0x81
lis r12, draw__9J2DScreenFiiPC14J2DGrafContext@h
ori r12, r12, draw__9J2DScreenFiiPC14J2DGrafContext@l
mtlr r12
blrl
lbz r0, 0x46(r31) # replaced instruction
# on area change, if qftStop and qftReset are both unset, qftOffset += gpMarDirector->_5c
@__dt__12TMarDirectorFv
lis r5, 0x817F
lhz r0, qftStop@l(r5) # read qftStop and qftReset
cmpwi r0, 0
bne- done
lwz r0, qftOffset@l(r5)
lwz r6, 0x5C(r3)
add r0, r0, r6
stw r0, qftOffset@l(r5)
done:
mflr r0 # replaced instruction
# on Shine Get, qftOffset += gpMarDirector->_5c, round qftOffset to the frame, stop and schedule a reset
@fireGetStar__12TMarDirectorFP6TShine + (0x48 on JP/US, 0x84 on PAL/JPA)
lis r5, 0x817F
lwz r6, qftOffset@l(r5)
lwz r0, 0x5C(r3)
add r6, r6, r0
addi r6, r6, 3+1
rlwinm r6, r6, 0, 0xFFFFFFFC
stw r6, qftOffset@l(r5)
li r6, -1 # replaced instruction
sth r6, qftStop@l(r5) # set qftStop and qftReset
# on Bowser defeat, qftOffset += gpMarDirector->_5c, round qftOffset to the frame, stop and schedule a reset
@startDemo__8TBathtubFv + (0x21C on JP/JPA, 0x218 on US/PAL)
lis r8, 0x817F
lwz r6, qftOffset@l(r8)
lwz r0, 0x5C(r3)
add r6, r6, r0
addi r6, r6, 3+1
rlwinm r6, r6, 0, 0xFFFFFFFC
stw r6, qftOffset@l(r8)
li r6, -1 # replaced instruction
sth r6, qftStop@l(r8) # set qftStop and qftReset
# on file select, schedule a reset
@changeScene__9TCardLoadFv + (0x1278 on JP, 0x1384 on US, 0x13B0 on PAL/JPA)
cmpwi r3, 1 # replaced instruction
lis r3, 0x817F
stb r5, qftReset@l(r3)
# on death, schedule a reset
@nextStateInitialize__12TMarDirectorFUc + (0x56C on JP, 0x5BC on US/PAL/JPA)
addi r4, r28, 1 # replaced instruction
lis r5, 0x817F
stb r4, qftReset@l(r5)
# on exit area, freeze on frame time until next area and schedule a reset
@changeState__12TMarDirectorFv + 0x328
lis r5, 0x817F
li r3, 1
stb r3, qftReset@l(r5)
lwz r3, 0x5C(r31)
addi r3, r3, 3
rlwinm r3, r3, 0, 0xFFFFFFFC
stw r3, qftFreezeTime@l(r5)
li r3, -1
stw r3, qftFreezeFor@l(r5)
# on loading zone activation, freeze on frame time until next area and cancel any scheduled reset
@setNextStage__12TMarDirectorFUsPQ26JDrama6TActor + 0x50
lis r5, 0x817F
stb r0, qftReset@l(r5)
lwz r0, 0x5C(r30)
addic r0, r0, 3+1
rlwinm r0, r0, 0, 0xFFFFFFFC
stw r0, qftFreezeTime@l(r5)
li r0, -1
stw r0, qftFreezeFor@l(r5)
# on red coin grab, freeze on QF time for 30 frames
@taken__8TCoinRedFP9THitActor + 0x4C
lwz r5, gpMarDirector-_SDA_BASE_(r13)
lwz r0, 0x5C(r5)
lis r5, 0x817F
stw r0, qftFreezeTime@l(r5)
li r0, 30
stw r0, qftFreezeFor@l(r5)
li r5, 0 # replaced instruction
# on blue coin grab, freeze on frame time for 30 frames
@taken__9TCoinBlueFP9THitActor + 0x24
mr r3, r0 # replaced instruction
lwz r5, 0x5C(r3)
addi r5, r5, 3
rlwinm r0, r5, 0, 0xFFFFFFFC
lis r5, 0x817F
stw r0, qftFreezeTime@l(r5)
li r0, 30
stw r0, qftFreezeFor@l(r5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment