Hlavní navigace

Názory k článku Ovládání hráčů ve hře klávesnicí nebo joystickem na ZX Spectru

  • Článek je starý, nové názory již nelze přidávat.
  • 25. 5. 2023 1:32

    _dw

    Me to ukazuje u kapitoly 4 a 6 velikost programu o bajt vice.

    Poznámka: velikost přeloženého strojového kódu klesla na 78 bajtů oproti původním 86 bajtům.

    Viz ty vypisy:

    8056:C9         RET
    8057:           END 8000
    Emiting TAP basic loader
    Emiting TAP from 8000 to 8056
    804E:C9         RET
    804F:           END 8000
    Emiting TAP basic loader
    Emiting TAP from 8000 to 804E

    Zacina to na nule.

    Dalsi 4 bajty jde srazit prepsanim tech make add a sub:

    add_to_hl MACRO value
            ld  b, 0           ; 2:7
            ld  c, value       ; 2:7
            add hl, bc         ; 1:11
    ENDM
    
    sub_from_hl MACRO value
            ld  b, 0           ; 2:7
            ld  c, value       ; 2:7
            or  a              ; 1:4    vynulovat carry
            sbc hl, bc         ; 2:15
    ENDM
    add_to_hl MACRO value
            ld bc, value       ; 3:10
            add hl, bc         ; 1:11
    ENDM
    
    sub_from_hl MACRO value
            ld bc,-(value)     ; 3:10
            add hl, bc         ; 1:11
    ENDM

    To divne -(value) je kvuli tomu kdyby se to volalo treba jako "sub_from_hl 16+16". Vyhrano ale nemame, protoze to jde jeste zkazit uvodnim minuskem, napriklad "sub_from_hl -2+34" se prelozi jako -36 -> pricte 36.

  • 25. 5. 2023 1:46

    _dw

    Jak se koukam na ten cely kod tak je tam vlastne chyba. Misto BC pro pricteni se melo radeji pouzivat DE. Protoze pri testu stisku klavesy "Q" uz cteme z portu 0x20 pripadne 0xE0.

    A podle chytejsich lidi nez ja... (zdravim Busyho .) ) pouziti neceho jineho nez 0xFE muze delat kolize s pripojenymi dalsimi zarizenimi.

  • 25. 5. 2023 2:26

    _dw

    K te hadance pro kapitolu 9.
    Poznámka: relativně jednoduchým přeskládáním kódu a modifikací instrukcí pro rotaci lze program nepatrně zkrátit i nepatrně urychlit. Přijdete na to, v jakém místě kódu?

    V registru A mame po cteni z portu: A=???67890, kde misto cislic je 0 kdy je klavesa stisknuta a nebo 1 kdyz neni.

    Nic me nenapada, spis mam pocit, ze jsi tam mel puvodne misto:

    left_not_pressed:
            keypress KB_ROW_4_PORT         ; test stisku klávesy 6,7,8 (joystick dolů, nahoru a doprava)
            rra                            ; třetí bit do příznaku carry
            rra
            rra
            jr c, right_not_pressed        ; přeskok dalších instrukcí, pokud klávesa není stisknuta
            changeAttribute ORIG_BLOCK     ; smazat hráče na původní pozici
            inc hl                         ; posun doprava o jeden bajt
            changeAttribute RED_BLOCK      ; vykreslit hráče na nové pozici
    
    right_not_pressed:
            rra                            ; čtvrtý bit do příznaku carry
            jr c, down_not_pressed         ; přeskok dalších instrukcí, pokud klávesa není stisknuta
            changeAttribute ORIG_BLOCK     ; smazat hráče na původní pozici
            sub_from_hl 32                 ; posun nahoru (o 32 bajtů)
            changeAttribute RED_BLOCK      ; vykreslit hráče na nové pozici
    
    down_not_pressed:
            rra                            ; pátý bit do příznaku carry
            jr c, up_not_pressed           ; přeskok dalších instrukcí, pokud klávesa není stisknuta
            changeAttribute ORIG_BLOCK     ; smazat hráče na původní pozici
            add_to_hl 32                   ; posun dolů (o 32 bajtů)
            changeAttribute RED_BLOCK      ; vykreslit hráče na nové pozici

    Neco jako:

    left_not_pressed:
            keypress KB_ROW_4_PORT         ; test stisku klávesy 6,7,8 (joystick dolů, nahoru a doprava)
            bit 2,a                        ; 2:8 třetí (imho je to druhy bit a pocita se od nuly) bit do příznaku zero
            jr nz, right_not_pressed       ; přeskok dalších instrukcí, pokud klávesa není stisknuta
            changeAttribute ORIG_BLOCK     ; smazat hráče na původní pozici
            inc hl                         ; posun doprava o jeden bajt
            changeAttribute RED_BLOCK      ; vykreslit hráče na nové pozici
    
    right_not_pressed:
            bit 3,a                        ; čtvrtý (imho je to treti bit a pocita se od nuly) bit do příznaku zero
            jr nz, down_not_pressed        ; 2:8 přeskok dalších instrukcí, pokud klávesa není stisknuta
            changeAttribute ORIG_BLOCK     ; smazat hráče na původní pozici
            sub_from_hl 32                 ; posun nahoru (o 32 bajtů)
            changeAttribute RED_BLOCK      ; vykreslit hráče na nové pozici
    
    down_not_pressed:
            and 0x10                       ; 2:7 pátý (imho ctvrty) bit do příznaku zero
            jr nz, up_not_pressed          ; přeskok dalších instrukcí, pokud klávesa není stisknuta
            changeAttribute ORIG_BLOCK     ; smazat hráče na původní pozici
            add_to_hl 32                   ; posun dolů (o 32 bajtů)
            changeAttribute RED_BLOCK      ; vykreslit hráče na nové pozici

    Takze ukazujes reseni hadanky.

    ...ale zkratit by to asi slo, kdyz se nebude resit prekresleni postavicky po kazdem pohybu (mysleno jako 2x pri sikmem posunu), ale az ve vysledku. Neco jako zmena do DE a na konci "ex HL,DE". Odpadne 6x changeAttribute kazda za 2 bajty. A potrebujeme 3 bajty na kopii do DE a prohozeni. Plus neco bude stat zmenit add_to_ a sub_to_ na 8 bitovou aritmetiku.

  • 25. 5. 2023 8:21

    atarist

    Kdyz nebudu pocitat Kempston, znamena to, ze ty dalsi interfajsy vlastne "oruji" nebo "anduji" stejne vodice, jako klavesnice? Myslim to tak, ze treba kdyz na klavesnici zmacknu 3 a nebo pouziju interface joystick ve stejnem smeru, tak to hra nepozna?

    Ale mozna to spis vypada na "andovani" protoze inverzni logika - tj. stisk klavesy bude "rusit" ovladani joystickem a naopak, takze to (ASI) nejde pouzit soucasne, ze? (minimalne kvuli ghostingu)

  • 25. 5. 2023 22:29

    xbastaj

    Děkuju za další lekci. Zkouším si to psát po svém, neřeším tolik jestli ušetřím pár byte, ale preferuju abych to měl přehledný. Mám rád když je oddělený testování klavesnice od akcí, kterou má stisk klávesy vyvolat, takže jsem použil podobně jako minule (děkuji ".DW" za připomínky a rady, už jsem si opravil chyby co jsem tam měl) podprogramy "vpravo", "vlevo", "nahoru", "dolu".
    Chtěl jsem tam taky mít dorazy na kraje obrazovky. První co mne napadlo mít v DE souřadnice Y,X a před každou změnou atributu vypočítat adresu atributu do HL.

    att_adr:                        ;vypocet adresy atributu 32*D+E
            push bc
            ld h,0
            ld l,d                  ;Y
            add hl,hl               ;Y*2
            add hl,hl               ;Y*4
            add hl,hl               ;Y*8
            add hl,hl               ;Y*16
            add hl,hl               ;Y*32
            ld bc, ATTRIBUTE_ADR
            add hl,bc               ;ADR+32*Y
            ld b,0
            ld c,e                  ;X
            add hl,bc               ;ADR+32*Y+X
            pop bc
            ret

    Funguje to, nevím jestli by to šlo napsat elegantněji (na nic lepšího jsem zatím nepřišel), ale přijde mi to dost brutální dělat po každé takovýhle výpočet.
    Druhý nápad byl tedy, že budu při pohybu současně přičítat/odčítat 1 v D/E a zároveň modifikovat HL (trik s přičítáním -32 mne napadl taky hned - na atmelu zas chybí instrukce pro přičtení konstanty, tak se musí odečítat záporná hodnota). Je to sice kratší, ale zas se mi moc nelíbí, že musím současně aktualizovat dvoje souřadnice.
    Verze pro Sinclair / Interface 2:

    ENTRY_POINT      equ $8000
    ROM_OPEN_CHANNEL equ $1601
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    
    
    X0               equ 15
    Y0               equ 10
    XMIN             equ 0
    XMAX             equ 31
    YMIN             equ 0
    YMAX             equ 23
    
    KB_R0            equ $fe
    KB_R1            equ $fd
    KB_R2            equ $fb
    KB_R3            equ $f7
    KB_R4            equ $ef
    KB_R5            equ $df
    KB_R6            equ $bf
    KB_R7            equ $7f
    
    Color0           equ $38
    Color1           equ $48
    Color2           equ $50
    
    INIPOS           equ ATTRIBUTE_ADR+32*Y0+X0
    ;-------------------------------------------------------------------------------
    CH_ATTR macro  attr
            ld  (hl), attr
    endm
    
    KEYB    macro port
            ld  c, $fe           ;adresa portu
            ld  b, port          ;adresa radku
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    
    endm
    
    ;-------------------------------------------------------------------------------
    
            org ENTRY_POINT
    
    start:  call ROM_CLS
    
            ld d,Y0
            ld e,X0
            ld hl,INIPOS
            CH_ATTR Color1
    
    ;-------------------------------------------------------------------------------
    main:   call delay
    
            KEYB KB_R3
    
            rra                ;1
            call nc,vlevo
            rra                ;2
            call nc,dolu
            rra                ;3
            call nc,nahoru
            rra                ;4
            call nc,vpravo
            rra                ;5
            call nc,palba
            call c,klid
            jp main
    
    ;-------------------------------------------------------------------------------
    vpravo: push AF
            CH_ATTR Color0
            ld a,e
            cp XMAX
            jr Z,vp0
            inc e
            inc hl
    vp0:    CH_ATTR Color1
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    vlevo:  push AF
            CH_ATTR Color0
            ld a,e
            cp XMIN
            jr Z,vl0
            dec e
            dec hl
    vl0:    CH_ATTR Color1
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    dolu:   push AF
            CH_ATTR Color0
            ld a,d
            cp YMAX
            jr Z,do0
            inc d
            ld bc,32
            add hl,bc
    do0:    CH_ATTR Color1
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    nahoru: push AF
            CH_ATTR Color0
            ld a,d
            cp YMIN
            jr Z,na0
            dec d
            ld bc,-32
            add hl,bc
    na0:    CH_ATTR Color1
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    palba:  push AF
            CH_ATTR Color2
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    klid:   push AF
            CH_ATTR Color1
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    delay:  push bc                 ;zpozdeni
            push de
            ld d,60
            ld e,0
    d01:    dec e
            jr nz, d01
            dec d
            jr nz, d01
            pop de
            pop bc
            ret
    
    end ENTRY_POINT
  • 26. 5. 2023 11:11

    xbastaj

    Hned jak jsem to tu večer dopsal, vypnul jsem počítač a v koupelně mne napadlo jak to udělt líp: pro test pravého/levého okraje by mělo stačit testovat dolních 5 bitů L jestli jsou 00000/11111. Pro horní okraj musí být HL menší než ATTRIBUTE_ADR+32 a pro dolní okraj větší než ATTRIBUTE_ADR+23*32 (trochu se budu muset "poprat" s 16b porovnáváním). Dál mám v hlavě verzi pro dva hráče. Odpoledne až budu doma z práce otestuju.

    Mám další otázku: jak je to s kompatibilitou 8080 - Z80 - 8086?

    Vím že programy pro 8080 bez problému fungují i na Z80 (před časem jsem četl články od NOSTALCOMPa a ten dělal PMI 80 na univerzálních deskách, procesorovou pak udělal jak s 8080 tak s 8085 a i s Z80 a v sw změnil jedinou věc a to nápis po startu z PMI80 na PMI85 či PMIZ8). Co se týká assembleru tak předpokládám, že existuje translátor který dokáže ze zkratek 8080 udělat zkratky pro Z80.
    8086 by měla být kopatibilní na úrovni zdrojového kodu, úplně jsem to nezkoumal, ale myslím že pro každou instrukci 8080 se najde ekvivalent pro 8086 (jen nevyužiju potenciál 16b procesoru).
    Jak to je mezi Z80 a 8086?

  • 26. 5. 2023 11:33

    atarist

    No na urovni assembleru to pujde asi +- dobre prevest, pokud se to popere s EXX a dalsima vecma, co x86 nema (treba call + condition), vubec z tohoto pohledu je x86 vlastne horsi :). Jinak x86 znam myslim dost dobre, tak by se dalo zapracovat na prevodni tabulce.

  • 26. 5. 2023 18:25

    xbastaj

    Tak jsem si "pohrál" a tady je výsledek pro dva hráče. Dorazy testuju přímo v HL. No a protože jsou hráči dva, jsou jejich souřadnice primárně uloženy v proměnných HracA_XY a HracB_XY.

    ENTRY_POINT      equ $8000
    ROM_OPEN_CHANNEL equ $1601
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    ;-------------------------------------------------------------------------------
    X0A              equ 10        ;pocatecni souradnice
    Y0A              equ 10
    X0B              equ 20
    Y0B              equ 10
    
    XMIN             equ 0         ;meze
    XMAX             equ 31
    YMIN             equ ATTRIBUTE_ADR
    YMAX             equ ATTRIBUTE_ADR+23*32
    
    KB_R0            equ $fe       ;radky klavesnice
    KB_R1            equ $fd
    KB_R2            equ $fb
    KB_R3            equ $f7
    KB_R4            equ $ef
    KB_R5            equ $df
    KB_R6            equ $bf
    KB_R7            equ $7f
    
    Color0           equ $38 ;bila
    Color1A          equ $48 ;modra
    Color2A          equ $58 ;magenta
    Color1B          equ $60 ;zelena
    Color2B          equ $70 ;zluta
    Color3           equ $50 ;cervena
    
    INIPOS_A         equ ATTRIBUTE_ADR+32*Y0A+X0A
    INIPOS_B         equ ATTRIBUTE_ADR+32*Y0B+X0B
    
    ;-------------------------------------------------------------------------------
    CH_ATTR macro  attr
            ld  (hl), attr
    endm
    
    KEYB    macro port
            ld  c, $fe           ;adresa portu
            ld  b, port          ;adresa radku
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    endm
    
    LOAD_HracXY macro            ;nacteni pozice hrace z pameti do HL
            ld l,(IX)
            ld h,(IX+1)
    endm
    
    STORE_HracXY macro          ;ulozeni pozice hrace z HL do pameti
            ld (IX),l
            ld (IX+1),h
    endm
    
    ;-------------------------------------------------------------------------------
            org ENTRY_POINT
    
    start:  call ROM_CLS       ;vymazani obrazovky
    
            ld ix,HracA_XY     ;pocatecni zobrazeni hrace A
            LOAD_HracXY
            CH_ATTR Color1A
    
            ld ix,HracB_XY     ;pocatecni zobrazeni hrace B
            LOAD_HracXY
            CH_ATTR Color1B
    
    ;-------------------------------------------------------------------------------
    main:   call delay         ;zpozdeni
    
            ld ix,HracA_XY     ;adresa pozice hrace A
            KEYB KB_R3         ;test joysticku A
            ld e,Color1A       ;barva hrace A
            rra                ;1
            call nc,vlevo
            rra                ;2
            call nc,dolu
            rra                ;3
            call nc,nahoru
            rra                ;4
            call nc,vpravo
            rra                ;5
            ld e,Color2A       ;barva pri strelbe
            call nc,palba
            ld e,Color1A       ;barva hrace A
            call c,klid
    
            ld ix,HracB_XY     ;adresa pozice hrace B
            KEYB KB_R4         ;test joysticku B
            ld e,Color1B       ;barva hrace B
            rla
            rla
            rla
            rla                ;6
            call nc,vlevo
            rla                ;7
            call nc,dolu
            rla                ;8
            call nc,nahoru
            rla                ;9
            call nc,vpravo
            rla                ;0
            ld e,Color2B       ;barva pri strelbe
            call nc,palba
            ld e,Color1B       ;barva hrace B
            call c,klid
    
            call kolize        ;test kolize hracu
    
            jp main            ;hlavni cyklus
    
    ;-------------------------------------------------------------------------------
    vpravo: push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            ld a,l              ;test okraje
            cpl
            and 0x1F            ;poslednich 5 bitu 11111
            jr Z,vp0            ;nebude zmena pozice
            inc hl              ;nova pozice
    vp0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    vlevo:  push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            ld a,l              ;test okraje
            and 0x1F            ;poslednich 5 bitu 00000
            jr Z,vl0            ;nebude zmena pozice
            dec hl              ;nova pozice
    vl0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    dolu:   push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            push HL             ;zalohovani pozice
            ld a,l
            and 0xE0            ;nulovani poslednich 5 bitu
            ld l,a
            ld bc,YMAX          ;nastaveni maxima
            sbc hl,bc           ;otestovani hodnoty
            pop HL
            jr Z,do0            ;nebude zmena pozice
            ld bc,32            ;nova pozice
            add hl,bc
    do0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    nahoru: push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            push HL             ;zalohovani pozice
            ld a,l
            and 0xE0            ;nulovani poslednich 5 bitu
            ld l,a
            ld bc,YMIN          ;nastaveni maxima
            sbc hl,bc           ;otestovani hodnoty
            pop HL
            jr Z,na0            ;nebude zmena pozice
            ld bc,-32           ;nova pozice
            add hl,bc
    na0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    palba:  push AF             ;zmena barvy pri strelbe
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR e
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    klid:   push AF             ;zmena barvy kdyz se nestrili
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR e
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    kolize: push AF
            ld ix,HracA_XY
            LOAD_HracXY         ;nacteni pozice hrace A
            ld b,h              ;kopie do BC
            ld c,l
            ld ix,HracB_XY
            LOAD_HracXY         ;nacteni pozice hrace B
            or a                ;nulovani cary
            sbc hl,bc           ;porovnani
            jr nz,ko0           ;neni kolize
            LOAD_HracXY
            CH_ATTR Color3      ;nastaveni barvy kolize
    ko0:    pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    delay:  push bc            ;zpozdeni
            push de
            ld d,60
            ld e,0
    d01:    dec e
            jr nz, d01
            dec d
            jr nz, d01
            pop de
            pop bc
            ret
    
    ;-------------------------------------------------------------------------------
    HracA_XY: dw INIPOS_A     ;pozice hrace A v pameti
    HracB_XY: dw INIPOS_B     ;pozice hrace B v pameti
    
    end ENTRY_POINT
    
    ENTRY_POINT      equ $8000
    ROM_OPEN_CHANNEL equ $1601
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    ;-------------------------------------------------------------------------------
    X0A              equ 10        ;pocatecni souradnice
    Y0A              equ 10
    X0B              equ 20
    Y0B              equ 10
    
    XMIN             equ 0         ;meze
    XMAX             equ 31
    YMIN             equ ATTRIBUTE_ADR
    YMAX             equ ATTRIBUTE_ADR+23*32
    
    KB_R0            equ $fe       ;radky klavesnice
    KB_R1            equ $fd
    KB_R2            equ $fb
    KB_R3            equ $f7
    KB_R4            equ $ef
    KB_R5            equ $df
    KB_R6            equ $bf
    KB_R7            equ $7f
    
    Color0           equ $38 ;bila
    Color1A          equ $48 ;modra
    Color2A          equ $58 ;magenta
    Color1B          equ $60 ;zelena
    Color2B          equ $70 ;zluta
    Color3           equ $50 ;cervena
    
    INIPOS_A         equ ATTRIBUTE_ADR+32*Y0A+X0A
    INIPOS_B         equ ATTRIBUTE_ADR+32*Y0B+X0B
    
    ;-------------------------------------------------------------------------------
    CH_ATTR macro  attr
            ld  (hl), attr
    endm
    
    KEYB    macro port
            ld  c, $fe           ;adresa portu
            ld  b, port          ;adresa radku
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    endm
    
    LOAD_HracXY macro            ;nacteni pozice hrace z pameti do HL
            ld l,(IX)
            ld h,(IX+1)
    endm
    
    STORE_HracXY macro          ;ulozeni pozice hrace z HL do pameti
            ld (IX),l
            ld (IX+1),h
    endm
    
    ;-------------------------------------------------------------------------------
            org ENTRY_POINT
    
    start:  call ROM_CLS       ;vymazani obrazovky
    
            ld ix,HracA_XY     ;pocatecni zobrazeni hrace A
            LOAD_HracXY
            CH_ATTR Color1A
    
            ld ix,HracB_XY     ;pocatecni zobrazeni hrace B
            LOAD_HracXY
            CH_ATTR Color1B
    
    ;-------------------------------------------------------------------------------
    main:   call delay         ;zpozdeni
    
            ld ix,HracA_XY     ;adresa pozice hrace A
            KEYB KB_R3         ;test joysticku A
            ld e,Color1A       ;barva hrace A
            rra                ;1
            call nc,vlevo
            rra                ;2
            call nc,dolu
            rra                ;3
            call nc,nahoru
            rra                ;4
            call nc,vpravo
            rra                ;5
            ld e,Color2A       ;barva pri strelbe
            call nc,palba
            ld e,Color1A       ;barva hrace A
            call c,klid
    
            ld ix,HracB_XY     ;adresa pozice hrace B
            KEYB KB_R4         ;test joysticku B
            ld e,Color1B       ;barva hrace B
            rla
            rla
            rla
            rla                ;6
            call nc,vlevo
            rla                ;7
            call nc,dolu
            rla                ;8
            call nc,nahoru
            rla                ;9
            call nc,vpravo
            rla                ;0
            ld e,Color2B       ;barva pri strelbe
            call nc,palba
            ld e,Color1B       ;barva hrace B
            call c,klid
    
            call kolize        ;test kolize hracu
    
            jp main            ;hlavni cyklus
    
    ;-------------------------------------------------------------------------------
    vpravo: push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            ld a,l              ;test okraje
            cpl
            and 0x1F            ;poslednich 5 bitu 11111
            jr Z,vp0            ;nebude zmena pozice
            inc hl              ;nova pozice
    vp0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    vlevo:  push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            ld a,l              ;test okraje
            and 0x1F            ;poslednich 5 bitu 00000
            jr Z,vl0            ;nebude zmena pozice
            dec hl              ;nova pozice
    vl0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    dolu:   push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            push HL             ;zalohovani pozice
            ld a,l
            and 0xE0            ;nulovani poslednich 5 bitu
            ld l,a
            ld bc,YMAX          ;nastaveni maxima
            sbc hl,bc           ;otestovani hodnoty
            pop HL
            jr Z,do0            ;nebude zmena pozice
            ld bc,32            ;nova pozice
            add hl,bc
    do0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    nahoru: push AF
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR Color0      ;barva pozadi
            push HL             ;zalohovani pozice
            ld a,l
            and 0xE0            ;nulovani poslednich 5 bitu
            ld l,a
            ld bc,YMIN          ;nastaveni maxima
            sbc hl,bc           ;otestovani hodnoty
            pop HL
            jr Z,na0            ;nebude zmena pozice
            ld bc,-32           ;nova pozice
            add hl,bc
    na0:    CH_ATTR e           ;barva hrace
            STORE_HracXY        ;ulozeni pozice hrace
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    palba:  push AF             ;zmena barvy pri strelbe
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR e
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    klid:   push AF             ;zmena barvy kdyz se nestrili
            LOAD_HracXY         ;nacteni pozice hrace
            CH_ATTR e
            pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    kolize: push AF
            ld ix,HracA_XY
            LOAD_HracXY         ;nacteni pozice hrace A
            ld b,h              ;kopie do BC
            ld c,l
            ld ix,HracB_XY
            LOAD_HracXY         ;nacteni pozice hrace B
            or a                ;nulovani cary
            sbc hl,bc           ;porovnani
            jr nz,ko0           ;neni kolize
            LOAD_HracXY
            CH_ATTR Color3      ;nastaveni barvy kolize
    ko0:    pop AF
            ret
    
    ;-------------------------------------------------------------------------------
    delay:  push bc            ;zpozdeni
            push de
            ld d,60
            ld e,0
    d01:    dec e
            jr nz, d01
            dec d
            jr nz, d01
            pop de
            pop bc
            ret
    
    ;-------------------------------------------------------------------------------
    HracA_XY: dw INIPOS_A     ;pozice hrace A v pameti
    HracB_XY: dw INIPOS_B     ;pozice hrace B v pameti
    
    end ENTRY_POINT
  • 26. 5. 2023 22:21

    _dw

    A pro dva hrace to jde napsat i takto:

    ENTRY_POINT      equ $8000
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    
    X0A              equ 10        ;pocatecni souradnice
    Y0A              equ 10
    X0B              equ 20
    Y0B              equ 10
    
    KB_R0            equ $fefe  ;BC=0xFEFE ->A=...VCXZc
    KB_R1            equ $fdfe  ;BC=0xFDFE ->A=...GFDSA
    KB_R2            equ $fbfe  ;BC=0xFBFE ->A=...TREWQ
    KB_R3            equ $f7fe  ;BC=0xF7FE ->A=...54321
    KB_R4            equ $effe  ;BC=0xEFFE ->A=...67890
    KB_R5            equ $dffe  ;BC=0xDFFE ->A=...YUIOP
    KB_R6            equ $bffe  ;BC=0xBFFE ->A=...HJKLe
    KB_R7            equ $7ffe  ;BC=0x7FFE ->A=...BNMs_
    
    Color0           equ $38 ;bila
    Color1A          equ $48 ;modra
    Color2A          equ $58 ;magenta
    Color1B          equ $60 ;zelena
    Color2B          equ $70 ;zluta
    Color3           equ $50 ;cervena
    
    
    INIPOS_A         equ ATTRIBUTE_ADR+32*Y0A+X0A
    INIPOS_B         equ ATTRIBUTE_ADR+32*Y0B+X0B
    ;-------------------------------------------------------------------------------
    KEYB    macro port
            ld bc, 256*port+$fe  ;adresa radku & adresa portu
    endm
    
    ;-------------------------------------------------------------------------------
    
            org ENTRY_POINT
    
    start:  call ROM_CLS
    
            ld hl,INIPOS_B
            ld (hl),Color1B
            ex de,hl
            ld hl,INIPOS_A
            ld (hl),Color1A
    
    ;-------------------------------------------------------------------------------
    main:   halt
            halt
    
            ld bc, KB_R3
            in  a, (c)         ;vlastní čtení z portu (5 bitů)
            call move
            ld a,Color1A       ;klid
            jr c,$+4
            ld a,Color2A       ;palba
            ld (hl),a          ;1:7
    
            ex de,hl
            ld bc, KB_R4
            in  a, (c)         ;vlastní čtení z portu (5 bitů)
            ld  c,a
            ld  b,5
    invert_loop:
            rr c
            adc a,a
            djnz invert_loop
    
            call move
            ld a,Color1B       ;klid
            jr c,$+4
            ld a,Color2B       ;palba
            ld (hl),a          ;1:7
            ex de,hl
    
            or a
            sbc hl,de
            add hl,de
            jr nz,$+4
            ld (hl),Color3     ; kolize
    
            jp main
    
    ;-------------------------------------------------------------------------------
    
    
    ; in:
    ;       A=read port
    ;       HL= ATTRIBUTE_ADR
    move:
            push hl
            ld   bc,  0x0020   ;3:10 = 32
    vlevo:
            rra                ;1
            jr c,vpravo
    
    if 1
            ; 31x 43 taktu, 1x 44 taktu
            push af            ;1:11
            ld a,%00011111     ;2:7
            and l              ;1:4
            jr z,$+3           ;2:7/12
            dec l              ;1:4
            pop  af            ;1:10
    else
            ; 50% 24 taktu, 3% 43 taktu, 47% 42 taktu
            dec l              ;1:4  ...0 0000-1?
            bit 4,l            ;2:8
            jr  z,vpravo       ;2:7/12
            inc l              ;1:4  ...1 ....+1?
            bit 4,l            ;2:8
            jr  z,vpravo       ;2:7/12
            dec l              ;1:4
    endif
    
    vpravo:
            rra                ;4
            jr c,dolu
    
    if 1
            push af            ;1:11
      if 1
            ; o trochu rychlejsi, protoze 31x 47 taktu, 1x48 taktu
            ld  a,%00011111    ;2:7
            inc l              ;1:4
            and l              ;1:4
            jr nz,$+3          ;2:7/12
            dec l              ;1:4
      else
            ; o trochu pomalejsi, protoze 31x 48 taktu, 1x47 taktu
            ld  a,%11100000    ;2:7
            or  l              ;1:4
            inc a              ;1:4
            jr  z,$+3          ;2:7/12
            inc l              ;1:4
      endif
            pop  af            ;1:10
    else
            ; 50% 24 taktu, 3% 43 taktu, 47% 42 taktu
            inc l              ;1:4  ...1 1111+1?
            bit 4,l            ;2:8
            jr nz,dolu         ;2:7/12
            dec l              ;1:4  ...0 ....-1?
            bit 4,l            ;2:8
            jr nz,dolu         ;2:7/12
            inc l              ;1:4
    endif
    
    dolu:
            rra                ;2
            jr c,nahoru
    
    ; last row 0x5AE0..0x5AFF => 0101 1010 111. ....
            add hl,bc          ;1:11    fail:0x5B ...1011; ok:0x58 ...1000,0x59 ...1001,0x5A ...1010
            inc h              ;1:4
            bit 2,h            ;2:8
            jr  z,nahoru-1     ;2:7/12
            sbc hl,bc          ;2:15
            dec h              ;1:4
    nahoru:
            rra                ;3
            jr c,palba
    
    ; first row 0x5800..0x581F => 0101 1000 000. ....
            sbc hl,bc          ;2:15    no carry! fail:0x57 ...0(1)11; ok:0x58 ...1(0)00,0x59 ...1(0)01,0x5A ...1(0)10
            bit 2,h            ;2:8
            jr   z,palba      ;2:7/12
            add hl,bc          ;1:11
    
    palba:
            rra                ;5
            ex (sp),hl         ;1:19
            ld (hl),Color0     ;2:10
            pop hl             ;1:11
            ret
    
    ;-------------------------------------------------------------------------------
    
    
    end ENTRY_POINT

    Je to 122 bajtu z puvodnich 313. Opet tam mas tu chybu ze mas jinak poprehazene klavesy a pohyby.

    A tady jsem se sam spalil! Protoze jsem jen prohodil u druheho hrace puvodne jen radek ktery se cte a zbytek nechal shodny jenze...

    V clanku to neni zdurazneno ale na te strance:
    https://worldofspectrum.org/faq/reference/peripherals.htm
    je uvedeno ze:
    Sinclair

    The 'left' Sinclair joystick maps the joystick directions and the fire button to the 1 (left), 2 (right), 3 (down), 4 (up) and 5 (fire) keys on the ZX Spectrum keyboard, and can thus be read via port 0xf7fe; see the Port 0xfe section for full details. For any of the joystick interfaces which map to keys, any game offering the appropriate form of joystick control can instead be played with the listed keys.

    The 'right' Sinclair joystick maps to keys 6 (left), 7 (right), 8 (down), 9 (up) and 0 (fire) and can therefore be read via port 0xeffe.

    Vypada to logicky az do chvile kdy zjistis, ze se ti ty bity mapuji takto

    KB_R3            equ $f7fe  ;BC=0xF7FE ->A=...54321
    KB_R4            equ $effe  ;BC=0xEFFE ->A=...67890

    Je to inverzne! Tak jsem to jen narychlo ohackoval ze prohazuji 5 bitu nez volam rutinu co resi druheho hrace.

  • 26. 5. 2023 22:15

    _dw

    Tady mas hned 2 varianty kdy se pouziva pro drzeni souradnic jen adresa

    Prvni je delsi 91 bajtu a pouziva 8 bitovou aritmetiku. Plus prohazuje puvodni a nove souradnice pres "ex DE,HL"

    ENTRY_POINT      equ $8000
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    
    X0               equ 15
    Y0               equ 10
    
    KB_R0            equ $fe  ;BC=0xFEFE ->A=...VCXZc
    KB_R1            equ $fd  ;BC=0xFDFE ->A=...GFDSA
    KB_R2            equ $fb  ;BC=0xFBFE ->A=...TREWQ
    KB_R3            equ $f7  ;BC=0xF7FE ->A=...54321
    KB_R4            equ $ef  ;BC=0xEFFE ->A=...67890
    KB_R5            equ $df  ;BC=0xDFFE ->A=...YUIOP
    KB_R6            equ $bf  ;BC=0xBFFE ->A=...HJKLe
    KB_R7            equ $7f  ;BC=0x7FFE ->A=...BNMs_
    
    Color0           equ $38
    Color1           equ $48
    Color2           equ $50
    
    INIPOS           equ ATTRIBUTE_ADR+32*Y0+X0
    ;-------------------------------------------------------------------------------
    KEYB    macro port
            ld bc, 256*port+$fe  ;adresa radku & adresa portu
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    endm
    
    ;-------------------------------------------------------------------------------
    
            org ENTRY_POINT
    
    start:  call ROM_CLS
    
            ld hl,INIPOS
            ld (hl),Color1
    ;-------------------------------------------------------------------------------
    main:   halt
            halt
    
            KEYB KB_R3
    
            ld  d, h
            ld  e, l
    vlevo:
            rra                ;1
            ld c,a
    
            jr c,vpravo
            ld a,%00011111
            and e
            jr z,vpravo
            dec e
    
    vpravo:
            rr c               ;4
            jr c,dolu
    
            ld a,%11100000
            or e
            inc a
            jr z,dolu
            inc e
    dolu:
            rr c               ;2
            jr c,nahoru
    
    ; last row 0x5AE0..0x5AFF => 0101 1010 111. ....
    
            ld  a,%00011111    ;2:7
            or  e              ;1:4
            xor d              ;1:4
            xor ~0x5A          ;2:7
            jr  z, nahoru      ;2:7/12
    
            ld  a,%00100000    ;2:7
            add a,e            ;1:4
            ld  e,a            ;1:4
            adc a,d            ;1:4
            sub e              ;1:4
            ld  d,a            ;1:4
    nahoru:
            rr c               ;3
            jr c,palba
    
    ; first row 0x5800..0x581F => 0101 1000 000. ....
    
            ld  a,%11100000    ;2:7
            and e              ;1:4
            xor d              ;1:4
            xor 0x58           ;2:7
            jr  z, palba      ;2:7/12
    
            ld  a,e            ;1:4
            sub %00100000      ;2:7
            ld  e,a            ;1:4
            jr nc,palba        ;2:7/12
            dec d              ;1:4
    
    
    palba:
            rr c               ;5
            ld a,Color1        ;klid
            jr c,klid
            ld a,Color2        ;palba
    klid:
            ld (hl),Color0
            ld (de),a
            ex DE,HL
            jp main
    
    ;-------------------------------------------------------------------------------
    
    end ENTRY_POINT

    Druha kratsi (79 bajtu) varianta to dela pres 16 bitovou aritmetiku a kdyz to je kratsi tak 8 bitovou aritmetiku (viz "if 1"). Plus souradnice drzi jen v HL a prohazuje si to se zasobnikem.

    ENTRY_POINT      equ $8000
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    
    X0               equ 15
    Y0               equ 10
    
    KB_R0            equ $fe  ;BC=0xFEFE ->A=...VCXZc
    KB_R1            equ $fd  ;BC=0xFDFE ->A=...GFDSA
    KB_R2            equ $fb  ;BC=0xFBFE ->A=...TREWQ
    KB_R3            equ $f7  ;BC=0xF7FE ->A=...54321
    KB_R4            equ $ef  ;BC=0xEFFE ->A=...67890
    KB_R5            equ $df  ;BC=0xDFFE ->A=...YUIOP
    KB_R6            equ $bf  ;BC=0xBFFE ->A=...HJKLe
    KB_R7            equ $7f  ;BC=0x7FFE ->A=...BNMs_
    
    
    Color0           equ $38
    Color1           equ $48
    Color2           equ $50
    
    INIPOS           equ ATTRIBUTE_ADR+32*Y0+X0
    ;-------------------------------------------------------------------------------
    KEYB    macro port
            ld bc, 256*port+$fe  ;adresa radku & adresa portu
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    endm
    
    ;-------------------------------------------------------------------------------
    
            org ENTRY_POINT
    
    start:  call ROM_CLS
    
            ld hl,INIPOS
            ld (hl),Color1
    ;-------------------------------------------------------------------------------
    main:   halt
            halt
    
            KEYB KB_R3
    
            push hl
            ld   bc,  0x0020   ;3:10 = 32
    vlevo:
            rra                ;1
            jr c,vpravo
    
    if 1
            ; 31x 43 taktu, 1x 44 taktu
            push af            ;1:11
            ld a,%00011111     ;2:7
            and l              ;1:4
            jr z,$+3           ;2:7/12
            dec l              ;1:4
            pop  af            ;1:10
    else
            ; 50% 24 taktu, 3% 43 taktu, 47% 42 taktu
            dec l              ;1:4  ...0 0000-1?
            bit 4,l            ;2:8
            jr  z,vpravo       ;2:7/12
            inc l              ;1:4  ...1 ....+1?
            bit 4,l            ;2:8
            jr  z,vpravo       ;2:7/12
            dec l              ;1:4
    endif
    
    vpravo:
            rra                ;4
            jr c,dolu
    
    if 1
            push af            ;1:11
      if 1
            ; o trochu rychlejsi, protoze 31x 47 taktu, 1x48 taktu
            ld  a,%00011111    ;2:7
            inc l              ;1:4
            and l              ;1:4
            jr nz,$+3          ;2:7/12
            dec l              ;1:4
      else
            ; o trochu pomalejsi, protoze 31x 48 taktu, 1x47 taktu
            ld  a,%11100000    ;2:7
            or  l              ;1:4
            inc a              ;1:4
            jr  z,$+3          ;2:7/12
            inc l              ;1:4
      endif
            pop  af            ;1:10
    else
            ; 50% 24 taktu, 3% 43 taktu, 47% 42 taktu
            inc l              ;1:4  ...1 1111+1?
            bit 4,l            ;2:8
            jr nz,dolu         ;2:7/12
            dec l              ;1:4  ...0 ....-1?
            bit 4,l            ;2:8
            jr nz,dolu         ;2:7/12
            inc l              ;1:4
    endif
    
    dolu:
            rra                ;2
            jr c,nahoru
    
    ; last row 0x5AE0..0x5AFF => 0101 1010 111. ....
            add hl,bc          ;1:11    fail:0x5B ...1011; ok:0x58 ...1000,0x59 ...1001,0x5A ...1010
            inc h              ;1:4
            bit 2,h            ;2:8
            jr  z,nahoru-1     ;2:7/12
            sbc hl,bc          ;2:15
            dec h              ;1:4
    nahoru:
            rra                ;3
            jr c,palba
    
    ; first row 0x5800..0x581F => 0101 1000 000. ....
            sbc hl,bc          ;2:15    no carry! fail:0x57 ...0(1)11; ok:0x58 ...1(0)00,0x59 ...1(0)01,0x5A ...1(0)10
            bit 2,h            ;2:8
            jr   z,palba      ;2:7/12
            add hl,bc          ;1:11
    
    palba:
            rra                ;5
            ld a,Color1        ;klid
            jr c,klid
            ld a,Color2        ;palba
    klid:
            ex (sp),hl         ;1:19
            ld (hl),Color0     ;2:10
            pop hl             ;1:11
            ld (hl),a          ;1:7
            jp main
    
    ;-------------------------------------------------------------------------------
    
    end ENTRY_POINT

    Mrkni se na stranky: https://worldofspectrum.org/faq/reference/peripherals.htm pod Sinclair mas napsane:
    Sinclair

    The 'left' Sinclair joystick maps the joystick directions and the fire button to the 1 (left), 2 (right), 3 (down), 4 (up) and 5 (fire) keys on the ZX Spectrum keyboard, and can thus be read via port 0xf7fe;

    Ty pouzivas spatne rozlozeni.

    Dale:

    KEYB    macro port
            ld  c, $fe           ;adresa portu
            ld  b, port          ;adresa radku
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    endm

    Muzes zkratit:

    KEYB    macro port
            ld  bc, 256*port+$fe ;adresa radku a portu
            in  a, (c)           ;vlastní čtení z portu (5 bitů)
    endm

    Dale:

    att_adr:                        ;vypocet adresy atributu 32*D+E
            push bc
            ld h,0
            ld l,d                  ;Y
            add hl,hl               ;Y*2
            add hl,hl               ;Y*4
            add hl,hl               ;Y*8
            add hl,hl               ;Y*16
            add hl,hl               ;Y*32
            ld bc, ATTRIBUTE_ADR
            add hl,bc               ;ADR+32*Y
            ld b,0
            ld c,e                  ;X
            add hl,bc               ;ADR+32*Y+X
            pop bc
            ret

    Bych asi resil jinak, prvne me trklo ze tam 2x pouzivas konstantu nuly, kdyz to preskladas tak podruhe muzes pouzit registr obsahujici nulu.
    ALe po dalsim preskladani zjistis ze ADR=0x5800
    takze ADR+X udelas kdyz misto spodnich 8 bitu tam das E

    att_adr:                        ;vypocet adresy atributu 32*D+E
            push bc
            ld h,0
            ld l,d                  ;Y
            add hl,hl               ;Y*2
            add hl,hl               ;Y*4
            add hl,hl               ;Y*8
            add hl,hl               ;Y*16
            add hl,hl               ;Y*32
            ld b, high ATTRIBUTE_ADR
            ld c,e                  ;X
            add hl,bc               ;ADR+32*Y+X
            pop bc
            ret

    slo by to zrychlit kdyz 3x zamenis "add hl,hl ;1:11" za "add a,a;1:4" ale bude to stat 1 bajt navic:

    att_adr:                        ;vypocet adresy atributu 32*D+E
            push bc
            ld a,d                  ;Y
            add  a,a                ;Y*2   0..+2..46
            add  a,a                ;Y*4   0..+4..92
            add  a,a                ;Y*8   0..+8..184
            ld h,0
            ld l,a                  ;hl=8*Y
            add hl,hl               ;Y*16
            add hl,hl               ;Y*32
            ld b, high ATTRIBUTE_ADR
            ld c,e                  ;X
            add hl,bc               ;ADR+32*Y+X
            pop bc
            ret
  • 26. 5. 2023 22:49

    _dw

    A pro tu druhou variantu vlastne ani BC uz nepotrebujes a vyjde ti to rychleji pres 8 bitove scitani:

    att_adr:                        ;vypocet adresy atributu 32*D+E
            ld a,d                  ;Y
            add  a,a                ;Y*2   0..+2..46
            add  a,a                ;Y*4   0..+4..92
            add  a,a                ;Y*8   0..+8..184
            ld h,0
            ld l,a                  ;hl=8*Y
            add hl,hl               ;Y*16
            add hl,hl               ;Y*32
            ld a,l                  ;hl=8*Y
            add a,e                 ;lo(Y*32+E)
            ld l,a                  ;
            ld a, high ATTRIBUTE_ADR
            adc a,h
            ld h,a                  ;
            ret
  • 26. 5. 2023 22:56

    _dw

    A dalsi iterace je o bajt kratsi a jeste rychleji...:

    att_adr:                        ;vypocet adresy atributu 32*D+E
            ld a,d                  ;Y
            add  a,a                ;Y*2   0..+2..46
            add  a,a                ;Y*4   0..+4..92
            add  a,a                ;Y*8   0..+8..184
            ld h,0x58>>2            ;
            ld l,a                  ;
            add hl,hl               ;ATTRIBUTE_ADR/2+Y*16
            add hl,hl               ;ATTRIBUTE_ADR+Y*32
            ld a,l                  ;hl=8*Y
            add a,e                 ;lo(Y*32+E)
            ld l,a                  ;
            adc a,h                 ;1:4
            sub l                   ;1:4
            ld h,a                  ;1:4
            ret

    ...a jeste rychleji...:

    att_adr:                        ;vypocet adresy atributu 32*D+E
            ld a,d                  ;Y
            add  a,a                ;Y*2   0..+2..46
            add  a,a                ;Y*4   0..+4..92
            add  a,a                ;Y*8   0..+8..184
            ld h,0x58>>2            ;
            ld l,a                  ;
            add hl,hl               ;ATTRIBUTE_ADR/2+Y*16
            add hl,hl               ;ATTRIBUTE_ADR+Y*32
            ld a,l                  ;hl=8*Y
            add a,e                 ;lo(Y*32+E)
            ld l,a                  ;
            jr nc,$+3               ;2:7/12
            inc h                   ;1:4
            ret

    a nakonec jeste rychleji protoze je to ve funkci a s mene bajty:
    ...a jeste rychleji...:

    att_adr:                        ;vypocet adresy atributu 32*D+E
            ld a,d                  ;Y
            add  a,a                ;Y*2   0..+2..46
            add  a,a                ;Y*4   0..+4..92
            add  a,a                ;Y*8   0..+8..184
            ld h,0x58>>2            ;
            ld l,a                  ;
            add hl,hl               ;ATTRIBUTE_ADR/2+Y*16
            add hl,hl               ;ATTRIBUTE_ADR+Y*32
            ld a,l                  ;hl=8*Y
            add a,e                 ;lo(Y*32+E)
            ld l,a                  ;
            ret nc                ;1:5/11
            inc h                   ;1:4
            ret

    26. 5. 2023, 22:58 editováno autorem komentáře

  • 26. 5. 2023 23:27

    xbastaj

    Tahle procedura vypadá elegantně. Nemám tolik zkušeností s Z80 (a ani celkově s takhle brutální minimalizací kodu na jakémkoliv procesoru). Pořád tu objevuju další a další instrukce a třeba jsem nevěděl, že můžu použít direktivu high / low (přitom na AVR se požívají prakticky neustále). U těch ostatních programů po tvojí úpravě jsou místa kde se už ztrácím jak to vlastně funguje.
    To rozložení kláves jsem si opravil (myslel jsem, že je to stejný jako u "kurzorovýho Joysticku"). Taky mne překvapilo, že ta druhá část je inverzně. V tom jak to mám napsaný bylo přeházení kláves jednoduchý, stačilo přeházet návěští u CALLů.

  • 27. 5. 2023 7:02

    _dw

    Upravil jsem ten kod na minimalisticky "Dyna Blaster". Kod trosku nabobtnal na 210 bajtu, ale uplne jsem to nehrotil s optimalizaci.

    ENTRY_POINT      equ $8000
    ATTRIBUTE_ADR    equ $5800
    ROM_CLS          equ $0DAF
    
    X0A              equ 32/2-6        ;pocatecni souradnice
    Y0A              equ 23/2
    X0B              equ 32/2+5
    Y0B              equ 23/2
    
    KB_R0            equ $fefe  ;BC=0xFEFE ->A=...VCXZc
    KB_R1            equ $fdfe  ;BC=0xFDFE ->A=...GFDSA
    KB_R2            equ $fbfe  ;BC=0xFBFE ->A=...TREWQ
    KB_R3            equ $f7fe  ;BC=0xF7FE ->A=...54321
    KB_R4            equ $effe  ;BC=0xEFFE ->A=...67890
    KB_R5            equ $dffe  ;BC=0xDFFE ->A=...YUIOP
    KB_R6            equ $bffe  ;BC=0xBFFE ->A=...HJKLe
    KB_R7            equ $7ffe  ;BC=0x7FFE ->A=...BNMs_
    
    
    player_a         equ 3
    bomb             equ 4
    player_b         equ 5
    timer            equ 6
    
    
    INIPOS_A         equ ATTRIBUTE_ADR+32*Y0A+X0A
    INIPOS_B         equ ATTRIBUTE_ADR+32*Y0B+X0B
    
    ;-------------------------------------------------------------------------------
    
            org ENTRY_POINT
    
            ld  A, %00101000    ; 2:7
    start:
            rra                 ; 1:4
            rra                 ; 1:4
            rra                 ; 1:4
            out (254),A         ; 2:11      zx_border   0=blk,1=blu,2=red,3=mag,4=grn,5=cyn,6=yel,7=wht
    
            xor a
            ld (0x5C8D),a
            call ROM_CLS
    
            ld hl,INIPOS_B
            ex de,hl
            ld hl,INIPOS_A
    
    
    
    ;-------------------------------------------------------------------------------
    main:
            ld   bc, KB_R4     ;3:10
            in    a,(c)        ;2:12 vlastní čtení z portu (5 bitů)
            push af            ;1:10
            ld    b,high KB_R3 ;2:7
            in    a,(c)        ;2:12 vlastní čtení z portu (5 bitů)
            ld   bc, 0x0020    ;3:10 = 32
    
            push hl            ;1:11
            call vlevo_rra     ;3:17
            call vpravo_rra    ;3:17
            call dolu_rra      ;3:17
            call nahoru_rra    ;3:17
            call palba_rra     ;3:17
            ex  (sp),hl        ;1:19
            res player_a,(hl)  ;2:15
            pop  hl            ;1:10
            set player_a,(hl)  ;2:15
    
            ex   de,hl
            pop  af            ;1:10
            push hl            ;1:11
            call palba_rra     ;3:17
            call nahoru_rra    ;3:17
            call dolu_rra      ;3:17
            call vpravo_rra    ;3:17
            call vlevo_rra     ;3:17
            ex (sp),hl         ;1:19
            res player_b,(hl)  ;2:15
            pop hl             ;1:10
            set player_b,(hl)  ;2:15
    
    
            push hl            ;1:11
            ld   hl,ATTRIBUTE_ADR+3*256-1;3:10
    check_timer:
            ld    a,(hl)       ;1:7
            bit timer,a        ;2:8
            jr    z,no_timer   ;2:7/12
    
            bit bomb,a         ;2:8
            jr   nz,explosion  ;2:7/12
    
    flash:
            and %00000111      ;2:7         mask_time
            jr   z,save        ;2:7/12
            or  %11000000      ;2:7
            jr  dec_a          ;2:7/12
    
    explosion:
            and %00000111      ;2:7         mask_time
            jr  nz,dec_timer   ;2:7/12
            ld    a,%11000111  ;2:7         init flash
    
            push hl
            call vlevo
            ld  (hl),a
            pop  hl
    
            push hl
            call vpravo
            ld  (hl),a
            pop  hl
    
            push hl
            call dolu
            ld  (hl),a
            pop  hl
    
            push hl
            call nahoru
            ld  (hl),a
            pop  hl
    
    
            jr save            ;2:12
    
    dec_timer:
            ld    a,(hl)       ;1:7
    dec_a:
            dec   a            ;1:4
    save:
            ld  (hl),a         ;1:7
    no_timer:
            dec  hl            ;1:6
            bit   2,h          ;2:8    0x57 1001 0111
            jr    z,check_timer;2:7/12
            pop  hl            ;1:10
    
    ; check live
            ld   a,(hl)        ;1:7
            ex   de,hl         ;1:4
            or (hl)            ;1:7
            and %00101000      ;2:7
            cp  %00101000      ;2:7
            jp   nz,start      ;3:10
    
            halt
            halt
            jp main
    
    ;-------------------------------------------------------------------------------
    
    if 0
    read_row:
            ld  c, 0xFE        ;2:7
            in  a, (c)         ;2:12 vlastní čtení z portu (5 bitů)
            ld   bc,  0x0020   ;3:10 = 32
            ret                ;1:10
    endif
    ;-------------------------------------------------------------------------------
    
    vlevo_rra:
            rra                ;1:4
            ret c              ;1:5/11
    vlevo:
            push af            ;1:11
            ld a,%00011111     ;2:7
            and l              ;1:4
            jr z,$+3           ;2:7/12
            dec l              ;1:4
            pop  af            ;1:10
            ret                ;1:10
    
    ;-------------------------------------------------------------------------------
    
    vpravo_rra:
            rra                ;1:4
            ret c              ;1:5/11
    vpravo:
            push af            ;1:11
            ld  a,%00011111    ;2:7
            inc l              ;1:4
            and l              ;1:4
            jr nz,$+3          ;2:7/12
            dec l              ;1:4
            pop  af            ;1:10
            ret                ;1:10
    
    ;-------------------------------------------------------------------------------
    
    dolu_rra:
            rra                ;1:4
            ret c              ;1:5/11
    dolu:
    ; last row 0x5AE0..0x5AFF => 0101 1010 111. ....
            add hl,bc          ;1:11    fail:0x5B ...1011; ok:0x58 ...1000,0x59 ...1001,0x5A ...1010
            inc h              ;1:4
            bit 2,h            ;2:8
            jr  z,$+4          ;2:7/12
            sbc hl,bc          ;2:15
            dec h              ;1:4
            ret                ;1:10
    
    ;-------------------------------------------------------------------------------
    
    nahoru_rra:
            rra                ;1:4
            ret c              ;1:5/11
    nahoru:
    ; first row 0x5800..0x581F => 0101 1000 000. ....
            sbc hl,bc          ;2:15    no carry! fail:0x57 ...0(1)11; ok:0x58 ...1(0)00,0x59 ...1(0)01,0x5A ...1(0)10
            bit 2,h            ;2:8
            ret z              ;1:5/11
            add hl,bc          ;1:11
            ret                ;1:10
    
    ;-------------------------------------------------------------------------------
    
    palba_rra:
            rra                ;1:4
            ret c              ;1:5/11
    palba:
            push af            ;1:11
            ld   a,%01010111   ;2:7
            or (hl)            ;1:7
            ld (hl),a          ;1:7
            pop  af            ;1:10
            ret                ;1:10
    
    end ENTRY_POINT

    Tezko rici jak je to "hratelne" bez 2 hracu a joysticku. Na emulatoru me moje klavesnice nepodporuje pro prvniho hrace fire+sikmy pohyb, krome vlevo dolu.