Ted jsem si teprve uvedomil, ze v te rutine draw_char je skryta vada. Protoze adresa fontu je zapsana pres promennou CHAR_ADR, aby tam nebyla magic cisla... .)
Pak tam nemuzeme natvrdo prirazovat do registru H registr C s tim, ze je tam nula. Protoze to tak uz nemusi byt. Kdybych potreboval zmenit fonty a videl na zacatku ze staci zmenit CHAR_ADR a je hotovo, tak bych mozna ani neprochazel kod a nehledal vyskyty, protoze kdyz to vytknu tak to mohu menit.
Spravne by to melo bys nejak takto:
;draw_char_save_bc draw_char: push hl ; uschovat HL na zásobník ifdef draw_char_save_bc push bc ; uschovat BC na zásobník endif ld bc, CHAR_ADR ; adresa, od níž začínají masky znaků if CHAR_ADR & 255 .warning Pouzivas adresu fontu nezarovnanou na segment, to neni nejlepsi napad. ld h, 0x00 ; C je nulové, protože CHAR_ADR=0x3c00 else ld h, c ; C je nulové, protože CHAR_ADR=0x..00 endif ld l, a ; kód znaku je nyní ve dvojici HL
K Atarist, muzes to mit ve stinovych registrech, ale taky to neco bude stat. Nejhorsi na tomhle je, ze dopredu nevis co vsechno budes jeste potrebovat. Muzes to delat i tak, ze to budes neustale prepisovat v prubehu jak se budou pozadavky menit a dokud te to bude bavit. (nastesti retroprogramovani je jen hobby programovani).
Kdyz se kouknes co to dela ted, a jestli je to uzitecne... tak to zatim neni lepsi nez pouzit ROM rutinu pro me. Tam budes mit jen problem s poslednim radkem (predposledni se da osetrit zmenou jedne ROM promenne).
Tiskneme font v matici 8x8 a nemenime atributy, takze je jasne kam by se to vyvijelo dal. A pokud chceme tisknout atributy, ma smysl to na zacatku pozicovat jako XY? Neni to lepsi pozicovat rovnou jako adresu atributu?
Pak potrebuji jinou rutinu calc_char_address. To uz nekdo musel resit... .)
0x5800..0x5AFF
-->
0x4000..0x57FF
00 01 00 11 11 00 Y5 Y4 Y3 Y2 Y1 X5 X4 X3 X2 X1
-->
00 01 00 Y5 Y4 00 00 00 Y3 Y2 Y1 X5 X4 X3 X2 X1
Vypada to, ze to staci segment vynasobit osmi a invertovat 7.bit/vynulovat 7. bit/pricist 0x80.
;[7:27] ld A, ? ; 1:4 add A, A ; 1:4 2x add A, A ; 1:4 4x add A, A ; 1:4 8x xor 0x80 ; 2:7 ld ?, A ; 1:4 Varianta pokud neni volne A ;[8:32] sla D ; 2:8 2x sla D ; 2:8 4x sla D ; 2:8 8x res 7, D ; 2:8
Kod upraveny tak, aby dekodoval v retezci nektere specialni znaky "\n", AT, ink, paper, flash, bright.
SCREEN_ADR equ $4000 CHAR_ADR equ $3c00 ENTRY_POINT equ $8000 ATTR_T equ $5C8F ZX_EOL equ 0x0D ; zx_constant end of line ZX_INK equ 0x10 ; zx_constant colour ZX_PAPER equ 0x11 ; zx_constant colour ZX_FLASH equ 0x12 ; zx_constant 0 or 1 ZX_BRIGHT equ 0x13 ; zx_constant 0 or 1 ZX_AT equ 0x16 ; zx_constant Y,X ZX_BLUE EQU %001 ; zx_constant ZX_YELLOW EQU %110 ; zx_constant org ENTRY_POINT ; Input: x = 0..31 ; y = 0..23 ; Output: ; ld de, 0x4000 + ((0x1F & y ) << 5) + ( 0x1F & x ) LD_R_XY2addr MACRO _r, _x, _y ld _r, 0x5800+((31&(_y))<<5)+(31&(_x)) ENDM start: LD_R_XY2addr DE,15,12 ld HL, TEXT ; 3:10 adresa prvního znaku v řetězci ; call print_string ; 3:17 tisk celého řetězce finish: ; jr finish ; 2:12 žádný návrat do systému print_string: ld A,(ATTR_T) ; 3:13 ld C, A ; 1:4 print_string_l: ld A, (HL) ; 1:7 načíst kód znaku z řetězce inc HL ; 1:6 přechod na další znak cp 0x20 ; 2:7 call nc, draw_char ; 3:10/17 jr nc, print_string_l ; 2:12 na další znak or A ; 1:4 test na kód znak s kódem 0 ret z ; 1:5/11 ukončit podprogram na konci řetězce call print_set ; 3:17 jr print_string_l ; 2:12 na další znak ; Input: A = spec char print_set: sub ZX_EOL ; 2:7 ret c ; 1:5/11 jr nz, print_set_ink ; 2:7/12 ld A, 0x1F ; 2:7 or E ; 1:4 ld E, A ; 1:4 nastaveni X na 31 inc DE ; 1:6 prechod na dalsi radek ret ; 1:10 print_set_ink: sub ZX_INK-ZX_EOL ; 2:7 jr nz, print_set_paper; 2:7/12 ld A, C ; 1:4 and 0xF8 ; 2:7 or (HL) ; 1:7 inc HL ; 1:6 přechod na další znak ld C, A ; 1:4 save new ink ret ; 1:10 print_set_paper: dec A ; 1:4 jr nz, print_set_flash; 2:7/12 ld A,(HL) ; 1:7 inc HL ; 1:6 přechod na další znak add A, A ; 1:4 2x add A, A ; 1:4 4x add A, A ; 1:4 8x xor C ; 1:4 and 0x38 ; 2:7 xor C ; 1:4 ld C, A ; 1:4 save new paper ret ; 1:10 print_set_flash: dec A ; 1:4 jr nz, print_set_brig ; 2:7/12 ld A, C ; 1:4 add A, A ; 1:4 or (HL) ; 1:7 inc HL ; 1:6 přechod na další znak rrca ; 1:4 ld C, A ; 1:4 save new flash ret ; 1:10 print_set_brig: dec A ; 1:4 jr nz, print_set_at ; 2:7/12 ld A,(HL) ; 1:7 inc HL ; 1:6 přechod na další znak rrca ; 1:4 rrca ; 1:4 xor C ; 1:4 and 0x40 ; 2:7 xor C ; 1:7 ld C, A ; 1:4 save new bright ret ; 1:10 print_set_at: sub ZX_AT-ZX_BRIGHT ; 1:4 ret nz ; 1:5/11 ld A,(HL) ; 1:7 new y inc HL ; 1:6 přechod na další znak ld D, 0x16 ; 2:7 add A, A ; 1:4 add A, A ; 1:4 add A, A ; 1:4 add A, A ; 1:4 rl D ; 2:8 add A, A ; 1:4 rl D ; 2:8 xor (HL) ; 1:7 new x inc HL ; 1:6 přechod na další znak ld E, A ; 1:4 ret ; 1:10 ; Input: A = char, DE = address, C = attr ; Output: DE = adress next char (overflow DE=0x5800) ; Poluttes: none draw_char: push AF ; 1:11 uschovat AF na zásobník push BC ; 1:11 uschovat BC na zásobník push HL ; 1:11 uschovat HL na zásobník ld L, A ; 1:4 kód znaku do L ld A, C ; 1:4 ld (DE),A ; 1:7 uložení atributu znaku ld BC, CHAR_ADR ; 3:10 adresa, od níž začínají masky znaků if CHAR_ADR & 255 .warning Pouzivas adresu fontu nezarovnanou na segment, to neni nejlepsi napad. ld H, 0x00 ; 1:4 C je nenulové else ld H, C ; 1:4 C je nulové, protože CHAR_ADR=0x..00 endif add HL, HL ; 1:11 2x add HL, HL ; 1:11 4x add HL, HL ; 1:11 8x add HL, BC ; 1:11 přičíst bázovou adresu masek znaků ld B, 8 ; 2:7 počitadlo zapsaných bajtů ld C, D ; 1:4 uschovat D sla D ; 2:8 2x sla D ; 2:8 4x sla D ; 2:8 8x res 7, D ; 2:8 loop: ld A,(HL) ; 1:7 načtení jednoho bajtu z masky ld (DE),A ; 1:7 zápis hodnoty na adresu (DE) inc L ; 1:4 posun na další bajt masky (nemusíme řešit přetečení do vyššího bajtu) inc D ; 1:4 posun na definici dalšího obrazového řádku djnz loop ; 2:8/13 vnitřní smyčka: blok s osmi zápisy ld D, C ; 1:4 obnovit obsah D inc DE ; 1:6 pop HL ; 1:10 obnovit obsah HL ze zásobníku pop BC ; 1:10 obnovit obsah BC ze zásobníku pop AF ; 1:10 obnovit obsah AF ze zásobníku ret ; 1:10 DE+=1 ; nulou ukončený řetězec TEXT: db "Hello, Speccy!", 0x0D,"dalsi radek na ",ZX_PAPER, ZX_YELLOW, "zlute...", ZX_AT,0,0,"pocatek", ZX_INK, ZX_BLUE," modrou!",ZX_AT,7,13,"ZX_AT 7,13 bright: ",ZX_BRIGHT,1,"ON",ZX_BRIGHT,0," OFF",ZX_AT,23,3,"ZX_AT 23,3 FLASH: ",ZX_FLASH,1,"ON",ZX_FLASH,0,"OFF",0
Stoji tam za povsimnuti jak je udelana ta SWITCH..CASE cast. Je to vnoreno do funkce aby se vyskakovalo pres RET. Hodnota podle ktere se to rozhoduje je v A a pokud mezi sebou vetve jsou vzdaleny jen o 1 tak staci "DEC A".
9. 3. 2023, 18:19 editováno autorem komentáře