Názory k článku Vývoj pro ZX Spectrum: výpis informací na obrazovku

  • Článek je starý, nové názory již nelze přidávat.
  • 21. 2. 2023 4:40

    _dw

    Diky za clanek.

    Pokusil jsem se prepsat program do "Forthu" a zkompilovat.

    ZX_CONSTANT
     ORG 0x8000
    INIT(60000)
    PRINT_Z({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"})
    STOP

    Prvni slovo "aktivuje" konstanty typu ZX_...
    INIT a STOP obaluji program a nastavuji zasobnik navratovych adres a vraci registry pro basic.

    Program musi uchovavat HL protoze je v nem TOS (top of stack).
    DE, protoze je v nem NOS (next of stack).
    Dalsi cell je v (SP) atd.
    HL' protoze obsahuje index RAS (return adres stack).
    Ostatni se da pouzit volne.

    PRINT_Z je psane trosku jinak, protoze je delane jako funkce, za to o trosicku rychleji, protoze v kazdem cyklu neresi ret z a neztraci 5 taktu.

    Mimochodem, retezce ukoncene nulou jsou podle nekterych programatoru ve Forthu spatne reseni. To je trochu flamewar tema. Ja si myslim, ze pokud se nesnazime s nema nejak pracovat a jen je tiskneme tak jsou v pohode.

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'ZX_CONSTANT ORG 0x8000 INIT(60000) PRINT_Z({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"}) STOP'
    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_INVERSE           EQU 0x14     ; zx_constant   0 or 1
    ZX_OVER              EQU 0x15     ; zx_constant   0 or 1
    ZX_AT                EQU 0x16     ; zx_constant   Y,X
    ZX_TAB               EQU 0x17     ; zx_constant   # spaces
    
    ZX_BLACK             EQU %000     ; zx_constant
    ZX_BLUE              EQU %001     ; zx_constant
    ZX_RED               EQU %010     ; zx_constant
    ZX_MAGENTA           EQU %011     ; zx_constant
    ZX_GREEN             EQU %100     ; zx_constant
    ZX_CYAN              EQU %101     ; zx_constant
    ZX_YELLOW            EQU %110     ; zx_constant
    ZX_WHITE             EQU %111     ; zx_constant
     ORG 0x8000
    ;   ===  b e g i n  ===
        ld  (Stop+1), SP    ; 4:20      init   storing the original SP value when the "bye" word is used
        ld    L, 0x1A       ; 2:7       init   Upper screen
        call 0x1605         ; 3:17      init   Open channel
        ld   HL, 0xEA60     ; 3:10      init   Return address stack = 60000
        exx                 ; 1:4       init
        ld   BC, string101  ; 3:10      print_z   Address of null-terminated string101
        call PRINT_STRING_Z ; 3:17      print_z
    Stop:                   ;           stop
        ld   SP, 0x0000     ; 3:10      stop   restoring the original SP value when the "bye" word is used
        ld   HL, 0x2758     ; 3:10      stop
        exx                 ; 1:4       stop
        ret                 ; 1:10      stop
    ;   =====  e n d  =====
    ;------------------------------------------------------------------------------
    ; Print C-style stringZ
    ; In: BC = addr
    ; Out: BC = addr zero + 1
        rst  0x10           ; 1:11      print_string_z putchar with ZX 48K ROM in, this will print char in A
    PRINT_STRING_Z:         ;           print_string_z
        ld    A,(BC)        ; 1:7       print_string_z
        inc  BC             ; 1:6       print_string_z
        or    A             ; 1:4       print_string_z
        jp   nz, $-4        ; 3:10      print_string_z
        ret                 ; 1:10      print_string_z
    
    STRING_SECTION:
    string101:
        db ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!", 0x00
    size101              EQU $ - string101
    ; seconds: 0           ;[35:167]

    Dalsi varianta je pouzit retezec, ktery bude ukoncen tak ze posledni bajt bude mit 7. bit nastaveny na 1, takze se usetri bajt na retezec. Pouzije se slovo PRINT_I.

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'ZX_CONSTANT ORG 0x8000 INIT(60000) PRINT_I({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"}) STOP'
    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_INVERSE           EQU 0x14     ; zx_constant   0 or 1
    ZX_OVER              EQU 0x15     ; zx_constant   0 or 1
    ZX_AT                EQU 0x16     ; zx_constant   Y,X
    ZX_TAB               EQU 0x17     ; zx_constant   # spaces
    
    ZX_BLACK             EQU %000     ; zx_constant
    ZX_BLUE              EQU %001     ; zx_constant
    ZX_RED               EQU %010     ; zx_constant
    ZX_MAGENTA           EQU %011     ; zx_constant
    ZX_GREEN             EQU %100     ; zx_constant
    ZX_CYAN              EQU %101     ; zx_constant
    ZX_YELLOW            EQU %110     ; zx_constant
    ZX_WHITE             EQU %111     ; zx_constant
     ORG 0x8000
    ;   ===  b e g i n  ===
        ld  (Stop+1), SP    ; 4:20      init   storing the original SP value when the "bye" word is used
        ld    L, 0x1A       ; 2:7       init   Upper screen
        call 0x1605         ; 3:17      init   Open channel
        ld   HL, 0xEA60     ; 3:10      init   Return address stack = 60000
        exx                 ; 1:4       init
        ld   BC, string101  ; 3:10      print_i   Address of string101 ending with inverted most significant bit
        call PRINT_STRING_I ; 3:17      print_i
    Stop:                   ;           stop
        ld   SP, 0x0000     ; 3:10      stop   restoring the original SP value when the "bye" word is used
        ld   HL, 0x2758     ; 3:10      stop
        exx                 ; 1:4       stop
        ret                 ; 1:10      stop
    ;   =====  e n d  =====
    ;------------------------------------------------------------------------------
    ; Print string ending with inverted most significant bit
    ; In: BC = addr string_imsb
    ; Out: BC = addr last_char + 1
        rst  0x10           ; 1:11      print_string_i putchar with ZX 48K ROM in, this will print char in A
    PRINT_STRING_I:         ;           print_string_i
        ld    A,(BC)        ; 1:7       print_string_i
        inc  BC             ; 1:6       print_string_i
        or    A             ; 1:4       print_string_i
        jp    p, $-4        ; 3:10      print_string_i
        and  0x7f           ; 2:7       print_string_i
        rst  0x10           ; 1:11      print_string_i putchar with ZX 48K ROM in, this will print char in A
        ret                 ; 1:10      print_string_i
    
    STRING_SECTION:
    string101:
        db ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!" + 0x80
    size101              EQU $ - string101
    ; seconds: 0           ;[38:185]

    Posledni varianta je zakladni PRINT, ktere vola ROM rutinu pro tisk retezce, ktera vyzaduje pokazde nastavit delku tisknuteho retezce, takze opakovane volani zabira nejvic mista.

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ls -l root_str*.bin
    -rw-rw-r-- 1 dworkin dworkin 50 Feb 21 02:59 root_str.bin
    -rw-rw-r-- 1 dworkin dworkin 56 Feb 21 02:58 root_stri.bin
    -rw-rw-r-- 1 dworkin dworkin 54 Feb 21 02:58 root_strz.bin
    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$

    PS: Preklad je napsan v pouhem makru (M4) a vsechny PRINT se snazi najit shodne retezce pokud se pouziji, aby se ulozil jen jeden. Proto ty slova vypadaji "trosku" jinak nez ve Forthu.

    PRINT({"Retezec"}) misto ." Retezec"
    PUSH(10) misto 10
    ADD misto +

  • 21. 2. 2023 9:57

    atarist

    jj takze pro Forth porad plati, ze je to +- maximalne dvakrat delsi, nez ciste ASM. A to nemyslim zle, to je naopak skvely vysledek na vysokourovnovy jazyk.

  • 21. 2. 2023 4:44

    _dw

    Vypadla me ta varianta s PRINT

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'ZX_CONSTANT ORG 0x8000 INIT(60000) PRINT({ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"}) STOP'
    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_INVERSE           EQU 0x14     ; zx_constant   0 or 1
    ZX_OVER              EQU 0x15     ; zx_constant   0 or 1
    ZX_AT                EQU 0x16     ; zx_constant   Y,X
    ZX_TAB               EQU 0x17     ; zx_constant   # spaces
    
    ZX_BLACK             EQU %000     ; zx_constant
    ZX_BLUE              EQU %001     ; zx_constant
    ZX_RED               EQU %010     ; zx_constant
    ZX_MAGENTA           EQU %011     ; zx_constant
    ZX_GREEN             EQU %100     ; zx_constant
    ZX_CYAN              EQU %101     ; zx_constant
    ZX_YELLOW            EQU %110     ; zx_constant
    ZX_WHITE             EQU %111     ; zx_constant
     ORG 0x8000
    ;   ===  b e g i n  ===
        ld  (Stop+1), SP    ; 4:20      init   storing the original SP value when the "bye" word is used
        ld    L, 0x1A       ; 2:7       init   Upper screen
        call 0x1605         ; 3:17      init   Open channel
        ld   HL, 0xEA60     ; 3:10      init   Return address stack = 60000
        exx                 ; 1:4       init
        push DE             ; 1:11      print
        ld   BC, size101    ; 3:10      print     Length of string101
        ld   DE, string101  ; 3:10      print     Address of string101
        call 0x203C         ; 3:17      print     Print our string with ZX 48K ROM
        pop  DE             ; 1:10      print
    Stop:                   ;           stop
        ld   SP, 0x0000     ; 3:10      stop   restoring the original SP value when the "bye" word is used
        ld   HL, 0x2758     ; 3:10      stop
        exx                 ; 1:4       stop
        ret                 ; 1:10      stop
    ;   =====  e n d  =====
    
    STRING_SECTION:
    string101:
        db ZX_PAPER, ZX_RED, "Hello", ZX_INK, ZX_WHITE, "Speccy", ZX_FLASH, 1, "!"
    size101              EQU $ - string101
    ; seconds: 1           ;[32:150]
  • 21. 2. 2023 9:24

    občasný počítačový údržbář

    Pěkně napsané využití tisku znaků přes ROM.

    Osobně jsem ZX ROM pro tisk znaků přestal používat už dávno, protože obvykle chci vypisovat mnohem rychleji, často bez barev a skoro vždy na všech 24 řádků, nejenom na 22, což by asi v článku mohlo být zmíněno. Vidím tam jen zmínku o otevření kanálu 2, ale nikoli jeho omezení. Resp. to, že omezení podprogramu RST16 je stejné, jako omezení příkazu PRINT v BASICu.

    Taky mi tam chybí zmínka o velmi často používaném způsobu ukončení řetězce bitem 7 v 1, které dává smysl pokud používám jen ASCII se znaky 32 až 127, ušetří se tím byte v každém řetězci a zároveň je stále jednoduché a rychlé bit 7 testovat.

    Na druhou stranu ukončení nulou mi dává možnost být rozmařilý a s použitím vlastního fontu vypisovat kompatibilním kódováním ISO8859-2 :) Ale i k tomu potřebuju vlastní kód, který nemá omezení nad 127, neřeší semigrafiku a tokeny BASICových příkazů.

    Jo, je těžké do omezeného prostoru napsat vše :) I malý, starý a dobře prozkoumaný počítač má možnosti téměř neomezené :)

  • 21. 2. 2023 9:40

    Pavel Tišnovský
    Zlatý podporovatel

    Díky za doplnění. Jinak například to nastavení sedmého bitu se dalo využít při tvorbě textovek (pokud už neměl člověk nějakou komprimaci), protože například názvy všech předmětů mohly být v jednom řetězci a "oddělené" jen nejvyšším bitem na začátku každého jména. Dobré řešení třeba v BASICech, které neměly pole stringů (+ se na každý předmět ušetřil minimálně jeden bajt).

  • 21. 2. 2023 10:07

    občasný počítačový údržbář

    Nastavení sedmého bitu používá mimochodem i samotná ZX ROM - viz tokeny příkazů od dekadické adresy 150. Akorát ten bit 7 je na posledním znaku, ne na prvním.

    Prohledávání a detokenizaci mám např. ve svých ovladačích k tiskárnám, když jsem chtěl tisknout nejenom text pomocí LPRINT (ekvivalent PRINT #3), ale i výpis BASICového programu pomocí LLIST (ekvivalent LIST #3).

  • 21. 2. 2023 16:23

    jm

    Hezká je textovka "...a to snad ne", kde se používá pětibitové kódování, ve kterém se nejčastější znaky kódují jedním pětibitem a tuším dvě speciální hodnoty slouží jako escape, co volí jednu z dalších dvou tabulek znaků.

    Pak je tam taky krásně jednoduše řešená herní logika, kdy se akorát při průchodu obrazovkami různě překlápí bity ve stavovém stroji a podle nich se volí, která varianta textu se zobrazí.

  • 21. 2. 2023 18:23

    Pavel Tišnovský
    Zlatý podporovatel

    jj dá se na to jít různě. Klidně, pokud budou popisky lokací rozeznávat do 256 slov, kódovat slova jedním bajtem atd. (to asi platí víc pro angličtinu, kde může být počet slov a jejich tvarů o dost nižší). Nebo nějaký Huffmanův kód, což (pokud si to dobře pamatuju) měly textovky od Levelu-9.

  • 21. 2. 2023 10:15

    Pavel Tišnovský
    Zlatý podporovatel

    Jinak zařízení/kanály (někde se používá i termín stream - a to v polovině osmdesátých let) zkusím popsat podrobněji, protože je to zajímavý a nadčasový koncept.

  • 21. 2. 2023 15:58

    Korporátní lopata

    Jj, v praxi člověk používal vlastní rutinu pro tisk, většinou i uměla řídící znak AT, barvy a konec textu a přetéct do dalšího řádku.
    Docela hezké byly proporciální tisky v některých textovkách.

  • 21. 2. 2023 15:20

    JirSOft

    Moc pěkný článek, dík!

    Jen možná došlo k záměnám: místo neproporcionální (=monospaced) text mělo být asi proporcionální...

  • 21. 2. 2023 19:57

    Pavel Tišnovský
    Zlatý podporovatel

    třeba takto se dá vytisknout zpráva několikrát, pokaždé jinou barvou:

    ENTRY_POINT      equ $8000
    ROM_OPEN_CHANNEL equ $1601
    ROM_PRINT        equ $203C
    ATTR_T           equ 23695
        org ENTRY_POINT
    
    start:
        ld   A,2              ; číslo kanálu
        call ROM_OPEN_CHANNEL ; otevření kanálu číslo 2 (screen)
    
        ld   B, 64            ; barva tisku
        ld   HL, ATTR_T       ; adresa systémové proměnné ATTR_T
    
    loop:
        ld   (HL), B          ; změna barvy tisku
        push BC               ; uchovat BC
        ld   DE, TEXT         ; adresa prvního znaku v řetězci
        ld   BC, TEXT_LENGTH  ; délka textu
        call ROM_PRINT        ; volání subrutiny v ROM
        pop  BC               ; obnovit BC
        djnz loop             ; tisk další barvou
        ret                   ; ukončit program
    
    ; řetězec
    TEXT:   db "Hello, speccy!"