Názor k článku Ovládání hráčů ve hře klávesnicí nebo joystickem na ZX Spectru od _dw - Tady mas hned 2 varianty kdy se pouziva...

  • Článek je starý, nové názory již nelze přidávat.
  • 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