Detective Work
As we know that the routine is writing to CHARS, this is going to be custom font data.
The +$0100
thing I mentioned previously, you can see if you visit the link
above, that even the ZX Spectrum ROM sets CHARS to be $3C00
, yet the real
address for the CHARSET is at $3D00
.
The reason for it is pretty simple; the first 32 characters are control characters and so have no visible output. 32 x 8 = 256 (or $100 in hex). So these characters are just skipped over.
Font
As for disassembling the font, we can enter something like this:
b $ECE0 Custom Font
@ $ECE0 label=CustomFont
$ECE0,$08 #UDG(#PC,attr=$47)
L $ECE0,$08,$64
Originally I guessed $60 for the number of times to loop, and just increased it manually until I found what appeared to be the end of the data (when it stopped displaying cleanly).
Some Things To Note:
b
indicates a data block- The
@
directive declares an ASM label at a given address - The
L
directive defines a control file loop that repeats a sequence of other control directives
Output
This will create some nice output of the font images in a table:
Address | Font UDG |
---|---|
$ECE0 | ![]() |
$ECE8 | ![]() |
$ECF0 | ![]() |
$ECF8 | ![]() |
$ED00 | ![]() |
$ED08 | ![]() |
$ED10 | ![]() |
$ED18 | ![]() |
$ED20 | ![]() |
$ED28 | ![]() |
$ED30 | ![]() |
$ED38 | ![]() |
$ED40 | ![]() |
$ED48 | ![]() |
$ED50 | ![]() |
$ED58 | ![]() |
$ED60 | ![]() |
$ED68 | ![]() |
$ED70 | ![]() |
$ED78 | ![]() |
$ED80 | ![]() |
$ED88 | ![]() |
$ED90 | ![]() |
$ED98 | ![]() |
$EDA0 | ![]() |
$EDA8 | ![]() |
$EDB0 | ![]() |
$EDB8 | ![]() |
$EDC0 | ![]() |
$EDC8 | ![]() |
$EDD0 | ![]() |
$EDD8 | ![]() |
$EDE0 | ![]() |
$EDE8 | ![]() |
$EDF0 | ![]() |
$EDF8 | ![]() |
$EE00 | ![]() |
$EE08 | ![]() |
$EE10 | ![]() |
$EE18 | ![]() |
$EE20 | ![]() |
$EE28 | ![]() |
$EE30 | ![]() |
$EE38 | ![]() |
$EE40 | ![]() |
$EE48 | ![]() |
$EE50 | ![]() |
$EE58 | ![]() |
$EE60 | ![]() |
$EE68 | ![]() |
$EE70 | ![]() |
$EE78 | ![]() |
$EE80 | ![]() |
$EE88 | ![]() |
$EE90 | ![]() |
$EE98 | ![]() |
$EEA0 | ![]() |
$EEA8 | ![]() |
$EEB0 | ![]() |
$EEB8 | ![]() |
$EEC0 | ![]() |
$EEC8 | ![]() |
$EED0 | ![]() |
$EED8 | ![]() |
$EEE0 | ![]() |
$EEE8 | ![]() |
$EEF0 | ![]() |
$EEF8 | ![]() |
$EF00 | ![]() |
$EF08 | ![]() |
$EF10 | ![]() |
$EF18 | ![]() |
$EF20 | ![]() |
$EF28 | ![]() |
$EF30 | ![]() |
$EF38 | ![]() |
$EF40 | ![]() |
$EF48 | ![]() |
$EF50 | ![]() |
$EF58 | ![]() |
$EF60 | ![]() |
$EF68 | ![]() |
$EF70 | ![]() |
$EF78 | ![]() |
$EF80 | ![]() |
$EF88 | ![]() |
$EF90 | ![]() |
$EF98 | ![]() |
$EFA0 | ![]() |
$EFA8 | ![]() |
$EFB0 | ![]() |
$EFB8 | ![]() |
$EFC0 | ![]() |
$EFC8 | ![]() |
$EFD0 | ![]() |
$EFD8 | ![]() |
$EFE0 | ![]() |
$EFE8 | ![]() |
$EFF0 | ![]() |
$EFF8 | ![]() |