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:
bindicates a data block- The
@directive declares an ASM label at a given address - The
Ldirective 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 | ![]() |



































































































