File Name: | Integrated Speedrun Timer v1.2 |
Submitted: | by BlueToad |
Authors: | BlueToad |
Type: | Level, Game Mode |
Includes GFX: | No |
Includes Hijack: | No |
Featured: | No |
Description: | This is an UberASM which draws a timer on the status bar, which counts for how much time you have been in the level. It will pause whenever the game freezes, is paused or when a message box is active. When the level is completed it will stop and change palette to denote that the level has ended. Requires Super Status Bar patch. You can also disable the timer in upto 5 levels. This might be useful when you don't want the timer running in Yoshi's House, or during the intro message, for instance. Uses 6 bytes of free RAM. Use it as level ASM or use it in Game Mode 14 to apply to all levels. Requested by DoktorGroove. Screenshot 1: Showing the timer itself. Screenshots 2, 3, and 4: Timer stops and changes palette when a goal tape is touched, a palace switch is hit, or when a boss is defeated. Screenshot 5: Timer freezes when animations and sprites are frozen. Screenshot 6 and 7: Timer does not show up during No Yoshi intros. Screenshot 8: When started from the midway point, the timer does not show up. v1.1 update 9/8/2021: optimized a lot of the code, and made it use one less byte of free RAM. v1.2 update 11/8/2021: optimized the code a bit more, and fixed a bug about the timer appearing in No Yoshi intros. |
Tags: | hud, speedrun, status bar, time, timer |
Screenshots: | ![]() ![]() ![]() |
The first optimisation which could be done is the level check: Currently, the timer only allows you to make exceptions for up to five different levels (more specifically, sublevels, not translevels so you can't make an exception to a greater HUB area). A table is a better choice even if a bit more wasteful for a smaller amount of levels.
The second optimisation is the return parameter of freezecheck: You're using scratch RAM to denote whether to run the timer or not. The problem is that there is a better way in for m of the zero or carry flag and then immediately return from the routine should the timer not run or be displayed.
A third optimisation is the check of the midway flag:
Code
LDX $13BF ; Index LDA $1EA2,X ;Check midway touched. STA $01 ORA #$40 CMP $01 BNE + STZ $00 + ;If touched, don't do anything.
Please use
AND
or BIT
for that, using ORA and scratch RAM is plain overkill.For the fourth and optimisation, I criticise the way on how you handle the timer:
Code
INC !FR1 ;Increment correctly INC !FR1 LDA #$04 CMP !FR1 BEQ decback LDA #$09 CMP !FR1 BEQ decback JMP cont decback: DEC !FR1 cont: LDA #$0A ; Check overflow for centisecond. CMP !FR1 BEQ centi JMP skip centi: STZ !FR1 INC !FR2 ; Check overflow for 10*centisecond. LDA #$0A CMP !FR2 BEQ deci JMP skip deci: STZ !FR2 INC !FR3 LDA #$0A ; Second CMP !FR3 BEQ sec JMP skip sec: STZ !FR3 INC !FR4 LDA #$06 ; 10Second CMP !FR4 BEQ tensec JMP skip tensec: STZ !FR4 INC !FR5 LDA #$0A ; Minute CMP !FR5 BEQ min JMP skip min: STZ !FR5 INC !FR6 LDA #$0A ; 10Minute CMP !FR6 BEQ tenmin JMP skip tenmin: STZ !FR6
You use six bytes of freeRAM, one for each digit. The thing is that SMW only does this for the level timer (for some weird reason) but not for any other counter because not only are these easier to handle but these also save on freeRAM (and those which you have chosen are very often used). SMW provides a Hex2Dec routine at $00974C which allows you to convert the digits into a decimal representation.
For centiseconds, you can simply use the centiseconds as a frame counter (i.e. it counts from 0 to 59) but multiply the number by 99/59 which can be easily done with the multiplication and division registers.
Lastly, the position of the timer is hardcoded and can't be changed with a define. This essentially prevents most users from setting the timer at any position unless they know what they're doing and it also prevents them from changing the freeRAM destination of the status bar so they're stuck with the default LoROM address.
In addition, it would be nice if you made the resource SA-1 compatible which simply means in this case, stick a
|!addr
after every absolute WRAM access (i.e. $0000-$1FFF) and, as mentioned before, turn the status bar destination into a define so you can use the SA-1 freeRAM.