Dashboard
The first routine to be called from the “real” entrypoint is $8FC3
:
c $84D0 Game Entry Point
@ $84D0 label=GameEntryPoint
...
$84EC,$03 Call #R$8FC3.
Which is an odd looking routine, everyone does things slightly differently so this isn’t a hard-and-fast rule … but, noting that this happens a LOT:
CALL $8F8E
And as it’s referencing an address in the screen buffer, this suggests this is drawing something (or writing it), and given the game has only just loaded, it’s likely going to be part of the title screen.
c$8FC3 LD DE,$9030 ; #REGde=#R$9030.
$8FC6 LD HL,$5080 ; #REGhl=#N$5080.
$8FC9 LD BC,$2145 ; #REGbc=#N$2145.
$8FCC CALL $8F8E ; Call #R$8F8E.
Looking at $9030
, this doesn’t look like code at all - it gives the
appearance of being UDG reference data:
; Data block at 9030
b$9030 DEFB $7C,$7E,$7E,$7E,$7E,$7E,$7E,$7E
$9038 DEFB $7E,$7E,$7E,$24,$7E,$7E,$7E,$7E
$9040 DEFB $7E,$7E,$7E,$7E,$7E,$24,$7E,$7E
$9048 DEFB $7E,$7E,$7E,$7E,$7E,$7E,$7E,$7B
$9050 DEFB $7C,$20,$5E,$5C,$20,$4C,$49,$56
$9058 DEFB $45,$53,$20,$7B,$3C,$3E,$20,$49
$9060 DEFB $54,$45,$4D,$53,$20,$7B,$26,$28
$9068 DEFB $20,$54,$49,$4D,$45,$20,$20,$7B
$9070 DEFB $7C,$20,$5F,$5D,$20,$20,$20,$20
$9078 DEFB $20,$20,$20,$7B,$3D,$3F,$20,$20
$9080 DEFB $20,$20,$20,$20,$20,$7B,$27,$29
$9088 DEFB $20,$20,$20,$3A,$20,$20,$20,$7B
$9090 DEFB $7C,$7D,$7D,$7D,$7D,$7D,$7D,$7D
$9098 DEFB $7D,$7D,$7D,$2A,$7D,$7D,$7D,$7D
$90A0 DEFB $7D,$7D,$7D,$7D,$7D,$2A,$7D,$7D
$90A8 DEFB $7D,$7D,$7D,$7D,$7D,$7D,$7D,$7B
So, given that the custom font begins at: $EBE0
:
$EBE0 + ($7C * $08) = $EFC0
$EBE0 + ($7D * $08) = $EFC8
$EBE0 + ($7E * $08) = $EFD0
Which relate to:
Reference | Address | Font UDG |
---|---|---|
$7C | $EFC0 | ![]() |
$7D | $EFC8 | ![]() |
$7E | $EFD0 | ![]() |
We don’t have to manually go through each one, or even disassemble the whole thing to find out what it does. Skoolkit helpfully allows us to run the code and see what happens:
N $8FC3 #PUSHS #UDGTABLE {
. #SIM(start=$8FC3,stop=$902F)#SCR$02{$00,$140,$200,$40}(dashboard)
. } UDGTABLE# #POPS
Just watch out that #SIM
is simulating running the code, so it is actively
changing the screen buffer RAM in the current snapshot. This would then change
any other screenshots after this point except, I’m using the #PUSHS
(PUSH
Snapshot) and #POPS
(POP Snapshot) commands to keep the current snapshot
clean.
The resulting image from the code is:
Some Things To Note:
#PUSHS
/#POPS
: Given we’re writing over the snapshot, we’re changing it. These commands push the snapshot onto the stack, and pop it back off again#SIM
allows us to simulate the routine, given the start and stop points#UDGTABLE
creates a table which won’t render in ASM mode (as images can only be shown when using HTML#SCR
takes a screenshot of the screen buffer (nameddashboard.png
in this instance)
Populated Dashboard
Now we’re aware of what this function is for, when we see this:
$84EC CALL $8FC3 ; Call #R$8FC3.
$84EF CALL $90AA ; Call #R$90AA.
We now know this is the dashboard routine, plus after checking - the following routine populates the dashboard stats. Hence, we can make another screenshot:
N $90B0 #PUSHS #UDGTABLE {
. #SIM(start=$84EC,stop=$84F2)#SCR$02{$00,$140,$200,$40}(dashboard-populated)
. } UDGTABLE# #POPS
And now we can start to label where the “Lives”/ “Items”/ “Time” values are
stored in memory. Which is which can be gained by either guessing for now or
altering the #SIM
command to stop earlier in order to check which value is
drawn first … second … third. Then we can determine which is which, as
it’ll be based on which section it appears in.