Hello.
Need: define charactersI'd like to redefine a few characters (not a whole block, not the highest characters) using firmware calls.
In Soft968 appendix 7, control characters are explained, including character 25 (0x19) to redefine a character.
An array of control chars n*(25 + char number + 8 bytes of data) seems the most compact way to redefine chars cleanly using firmware.
It can be used even in CAT art IIRC.
Look before you postSoft968 section 4 explains the text VDU including:
QuoteWhen the user sets up a table of user defined matrices, by calling TXT SET M TABLE, it is initialized
with the current settings of the matrices from ROM or RAM. This means that extending the table does
not alter the current matrices. Contracting the table will make the characters lost revert to their default
matrices in ROM.
It does not state what
TXT SET M TABLE expects as argument.
Soft968 section 14 lists firmware jumpblocks, including
TXT SET MATRIX to redefine a character and
#BBAB TXT SET M TABLE with sole hint:
QuoteSet the user defined matrix table address.
Alas, it does not work so far. Even if I first call
SYMBOL AFTER 0 from BASIC.
I looked at Kevin Thacker's disassembly of ROM which includes
TXT SET M TABLE.
It looks like ROM checks if address passed in DE is smaller than 0x100. Perhaps argument is an actual address (if bigger or equal to 0x100 ) or a byte which may be just like BASIC's SYMBOL AFTER argument?
QuestionMy first question would be what firmware calls performs like
SYMBOL AFTER n ? Is &BBAB
TXT SET M TABLE with D=0 and E=argument correct?
Thank you.
Quote from: cpcitor on 19:58, 26 November 17
My first question would be what firmware calls performs like SYMBOL AFTER n ? Is &BBAB TXT SET M TABLE with D=0 and E=argument correct?
I tried that. Program crashes. Traced through ROM code thanks to Arnoldemu.
Code appears to do what's expected, then returns to main program.
Yet something becomes wrong in system state.
Disassembly is on http://cpctech.cpc-live.com/docs/os.asm look for "TXT SET M TABLE" or a line starting with 12fe.
It looks like the actual contract is:
* HL = area in RAM that will hold data
* if area is already populated, set D to non-zero. If D=0 then firmware copies font data from ROM to buffer at HL
* E = buffer size in character count
So, perhaps a proper way to do SYMBOL AFTER with firmware calls is:
* allocate a buffer with proper size (can be a C variable, whatever)
* call &BBAB
TXT SET M TABLE with HL=your buffer, E=char count, D depending on data contained in buffer
* then call a series of TXT SET MATRIX, or send a number of TXT OUTPUT with char 25 then character number then 8 bytes defining character.
Perhaps there are constraints about where the HL buffer should be (like, in the central 32k RAM).
The difference with BASIC is that you choose where the buffer is. This might be good news, since we then don't depend on BASIC-level hacks (remember the OPENOUT("d") hack to ensure where that buffer lands ?).
If might be handy to group your redefined characters at the end of the charset (close to 255). Then you don't have to ask the firmware to copy from ROM then poke your values. Just use a pre-filled const buffer, set D=1 to tell firmware not to copy, and you're done. You then don't even have to do any additional call to actually define your characters, they are in the buffer you provided. Also, you can then use the memory that BASIC usually pre-allocates to redefine characters 240-255 (128 bytes) and use it for something else.
Will test soon.
Quote from: cpcitor on 22:35, 26 November 17
Disassembly is on http://cpctech.cpc-live.com/docs/os.asm look for "TXT SET M TABLE" or a line starting with 12fe.
It looks like the actual contract is:
* HL = area in RAM that will hold data
* if area is already populated, set D to non-zero. If D=0 then firmware copies font data from ROM to buffer at HL
* E = buffer size in character count
Quote from: cpcitor on 22:35, 26 November 17
If might be handy to group your redefined characters at the end of the charset (close to 255). Then you don't have to ask the firmware to copy from ROM then poke your values. Just use a pre-filled const buffer, set D=1 to tell firmware not to copy, and you're done. You then don't even have to do any additional call to actually define your characters, they are in the buffer you provided. Also, you can then use the memory that BASIC usually pre-allocates to redefine characters 240-255 (128 bytes) and use it for something else.
Will test soon.
Just done that: pre-filled buffer, call with D=1. Program no longer crashes. :) Call to SET_M_TABLE has no observable effect. :(
I checked that values passed in HL, D and E are correct.
I traced in ROM code.
Firmware actually writes values to &b734-&b737, they make sense.
Yet characters drawn by firmware are the ones in ROM.
I even monitored RAM and it still keeps the values, so they are not reset by anything later.
I set E=&7F so that characters from &81 to &ff drawn by firmware use my table... they don't. ???
Default value at &b736 points indeed to data that is correct (&buffer at &A67C). See screenshot:
[attachimg=1]
If program has a BASIC loader, I know I can do e.g. "SYMBOL AFTER 129", but part of the exercise is to make the C firmware interface in cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain/tree/master/cpclib/cfwi/include/cfwi) more complete
I'm clueless. What can explain that SET_M_TABLE appears to do the job fully, yet characters don't take it into account. :-X
8) Full contract of firmware call TXT_SET_M_TABLE explained! 8)
Analysis of situation
Small correction: value in E is not buffer size, but the same value as would be used in SYMBOL AFTER: the index of the lowest character to use.
I observe that value in &b735 is 0 when I use my code, and FF when SYMBOL AFTER is run.
Indeed, TXT INITIALISE sets it to zero.
1077 af xor a
1078 3235b7 ld ($b735),a
Hmmm okay got it.
Value in &b735 is a flag. Only if lowest bit is set, firmware uses table. :doh:
Conclusion: full contract of firmware call TXT_SET_M_TABLE explained!
The full contract is:
* If you want to disable RAM-based characters (like SYMBOL AFTER 256), set D to a non-zero value. (Then values from other registers are stored by firmware but not used.)
* If you want to enable RAM-based characters, like SYMBOL AFTER nnn with nnn between 0 and 255 inclusive, then
* set D=0
* HL = area in RAM that will hold data
* E = indice of lowest character to be used in table (the value of nnn in SYMBOL AFTER nnn). In other words, table size is (256-E)*8 bytes long.
* Firmware copies font data from ROM to buffer at HL.
(It is still somehow possible to use a pre-filled buffer by setting D=0 then manually changing the flag, but then it's a hack, not the usage intended by firmware authors.)
Conclusion
It works!
[attachimg=1]
C firmware interface can now offer C-level structures to redefine characters with a proper C code.
(Not yet pushed to) https://github.com/cpcitor/cpc-dev-tool-chain/tree/master/cpclib/cfwi/include/cfwi