Okay, I wanted to do some investigating on score lag, so I did some trace logging and it turns out that Mister was totally right. The score IS calculated every frame, and it's a monster of a code believe me. Basically, the program repeatedly subtracts powers of ten from the score until it gets zero. The programmers were really dumb, For example, once you have subtracted the hudreds of thousands, the tens of thousands, the thousands, hundreds and tens, you would think that whatever remains you would just put in the last digit. well no. After you get to the ones, the program subtracts one after one after one, while incrementing the score on screen one by one.
Here's the kicker: the 65c816 CPU has a decimal mode, so you can calculate decimal arithmetic on any BCD numbers. so there's no need for a HEX-DEC conversion. It also takes no longer to do decimal arithmetic than binary arithmetic on the 65c816. Simply set the decimal flag beforehand, and unset it afterwards. simple!
Stupid? yes. Anyway, here is the code for the HEX-DEC score conversion for SMW:
Language: asm
;initial values for variables:
;(4 bytes) $0000 = score
;X = 14 <- okay what the hell
;Y = 0
;P = nvMXdiZc
;$8FFA,y (4 bytes) = 100,000 for y = 0, 10,000 for y = 4 , 1,000 for y = 8 ect.
009012 sep #$20
009014 stz $0F15,x
009017 rep #$20
009019 lda $02
00901B sec
00901C sbc $8FFC,y
00901F sta $06
009021 lda $00
009023 sbc $8FFA,y
009026 sta $04
009028 bcc $9039
00902A lda $06
00902C sta $02
00902E lda $04
009030 sta $00
009032 sep #$20
009034 inc $0F15,x
009037 bra $9017
009039 inx
00903A iny
00903B iny
00903C iny
00903D iny
00903E cpy #$18
009040 bne $9012
009042 sep #$20
009044 rts
Okay, doesn't look too bad does it? Here is a pseudocode version of the same process (simplified, not exact)
Language: cpp
void hexDecScore(int score)
{
int *x;
int y = 5;
int scorecheck;
while(true)
{
int ten_to_y = 10 ^ y;
*x = 0;
while(true)
{
scorecheck = score - ten_to_y;
if(scorecheck < 0) break;
score = scorecheck;
*x = *x++;
}
x = x++;
y = y--;
if(y == 0) break;
}
}
again, seems pretty easy, but when you realise that this process repeats itself over and over again, and this subroutine is called EVERY FRAME, you can see where it gets bad. The following is taken directly from a log file in a hex editor:
009012 sep #$20
009014 stz $0f15,x
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
009039 inx
00903a iny
00903b iny
00903c iny
00903d iny
00903e cpy #$18
009040 bne $9012
009012 sep #$20
009014 stz $0f15,x
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
009039 inx
00903a iny
00903b iny
00903c iny
00903d iny
00903e cpy #$18
009040 bne $9012
009012 sep #$20
009014 stz $0f15,x
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
009039 inx
00903a iny
00903b iny
00903c iny
00903d iny
00903e cpy #$18
009040 bne $9012
009012 sep #$20
009014 stz $0f15,x
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
009039 inx
00903a iny
00903b iny
00903c iny
00903d iny
00903e cpy #$18
009040 bne $9012
009012 sep #$20
009014 stz $0f15,x
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
009039 inx
00903a iny
00903b iny
00903c iny
00903d iny
00903e cpy #$18
009040 bne $9012
009012 sep #$20
009014 stz $0f15,x
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
00902a lda $06
00902c sta $02
00902e lda $04
009030 sta $00
009032 sep #$20
009034 inc $0f15,x
009037 bra $9017
009017 rep #$20
009019 lda $02
00901b sec
00901c sbc $8ffc,y
00901f sta $06
009021 lda $00
009023 sbc $8ffa,y
009026 sta $04
009028 bcc $9039
009039 inx
00903a iny
00903b iny
00903c iny
00903d iny
00903e cpy #$18
009040 bne $9012
009042 sep #$20
009044 rts
ALL that JUST to convert the score. and remember, that is done EVERY FRAME!
In other words, if you actually look at the code, it's not the number of digits below 4, it's the total sum of all the digits that makes the really big difference.
As for coins and lives, the HEX-DEC conversion is much simpler. Subtract 10 until your number is below 10, then the remainder is the second digit. Therefore, the second digit doesn't affect lag at all, because it requires the same amount of calculations no matter what.
So there's 59 cycles for every extra number above 0, plus the overhead that you would have anyway, even if you did have a score of zero. so in my TAS I have 37576, which is 28 digits which is 1793 cycles taken up by the score every frame. 60 FPS makes 107580 cycles every second taken up by the score. The 65c816 processor runs at 3.58 MHz, so that's 3% of processor time taken up purely by calculating the score, which is pretty substantial when you think about it.
As far as end of level lag is concerned, I think it's because your score is being tallied as well as the timer countdown, so there are two simultaneous HEX-DEC conversions going on. Ideally, you want 0, this will always get you the least amount of calculations. You can't really manipulate the timer, so that leaves the score.
The best case scenario is to have more low digits for the more significant digits of the score, the reason being, is that these numbers will remain low for the majority of the timer countdown (discount this if your timer is still not counting down by the time the screen starts increasing it's brightness), whereas say, the hundreds digit goes 1,2,3,4,5,6,7,8,9,0,1... ect, which gives a mean of about 4.5 no matter what digit you started with. For example even if your hundreds digit is a 9, even if you only have 20 seconds on the clock, it will average to 4.5. during the countdown. However, before and afterwards, you might have trouble. Also, the tens digit of the score is very important, because it doesn't change until right at the end. Make sure that it's a 5 or 0, depending on the timer, so that you get a good value for the finish, when it draws the circle.
If your timer isn't counting down by the time the screen becomes brighter, then all you have to worry about is what the score is before the countdown, and what it is afterwards. The point in time where lag reduction is really important is when the game is drawing the circle around mario. I believe this process is very computationally expensive, and low score should help in relieving some of the stress on the CPU. Make sure that the sum of your score digits and the second digit in your lives, coins, and stars is as low as possible to get the least amount of lag.
EDIT: more code snippets
HEX-DEC star conversion:
Language: asm
009051 sep #$20
009053 stz $0F15,x
009056 rep #$20
009058 lda $02
00905A sec
00905B sbc $8FFC,y
00905E sta $06
009060 bcc $906D
009062 lda $06
009064 sta $02
009066 sep #$20
009068 inc $0F15,x
00906B bra $9056
00906D inx
00906E iny
00906F iny
009070 iny
009071 iny
009072 cpy #$18
009074 bne $9051
009076 sep #$20
009078 rts
and HED-DEC for coins:
Language: asm
009045 ldx #$00
009047 cmp #$0A
009049 bcc $9050
00904B sbc #$0A
00904D inx
00904E bra $9047
009047 cmp #$0A
009049 bcc $9050
009050 rts
so for coins, only the first digit counts for lag, but for stars, the second digit does too...