Autore Topic: Specchiare Uno Sprite Sull'asse X  (Letto 2651 volte)

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Specchiare Uno Sprite Sull'asse X
« il: 02 Agosto 2006, 14:40:38 »
 Uno degli ultimi post di Pippo79 mi ha fatto studiare il problema dello specchiamento degli sprites. Ice00 in AnnGonng e Elav gia' aveva scritto una routine per gli sprites multicolor, quindi sono passato al problema (relativamente) piu' semplice degli sprites hires.

Uno sprite e' composto da 63 bytes che formano una griglia di 24x21 punti, ogni riga e' formata da 3 byte (8x3=24)
Per specchiare sull'asse X uno sprite hires occorre far si' che ogni bit che si trova a destra finisca a sinistra. Per fare questo gli operatori di bitshift sono li' apposta.
Si shifta a destra un bit con LSR, il bit 0 finisce nel Carry, e con ROL possiamo portarlo nel byte di destinazione. Ovviamente si puo' fare anche passandoli al contrario, il bit piu' a sinistra con asl va nel carry e lo riportiamo nella destinazione con un ROR.
Codice: [Seleziona]
01010101 >>>C
            |
00000000 <<<C
ripetendo questo per 8 volte abbiamo ribaltato un byte.
Codice: [Seleziona]
00000001
00000010
00000101
...
10101010
Dopo di che' bisogna ripetere il tutto per il 2o e 3o byte, facendo attenzione a far si' che la il 1o byte sorgente finisca nel 3o della destinazione, il 2o nel 2o e il 3o nel 1o. Il tutto ripetuto per ognuna delle 21 righe dello sprite.

Codice: [Seleziona]
;------------------------------------------------------------
; mirror one hires sprite
; iAN CooG/HokutoForce
;------------------------------------------------------------
       *=$801
debug = 0
src = $fb
dst = $fd
zps = $02
app = $03
zpd = $04
cnt = $05
;------------------------------------------------------------
        word eop
        word 7102
        byte $9e,[start]d,0
eop
        word 0
;------------------------------------------------------------
start
        lda #$01
        sta $D027          ;both sprites white
        sta $D028
        jsr $e544
        ldy #[sprite1/$40]
        sty $07f8          ;sprite1 pointer
        iny
        sty $07f9          ;sprite2 pointer
        lda #$03
        sta $d015          ;spr1+2 active
        lda #100
        sta $d000          ;position sprites @ 100,100
        sta $d001
        sta $d003
        lda #124            ;spr2 adjacent to spr1
        sta $d002

        lda #<sprite1      ;set pointers in zeropage
        sta src
        lda #>sprite1
        sta src+1
        lda #<sprite2
        sta dst
        lda #>sprite2
        sta dst+1

        jsr MirrorHiresSprite
        rts
;------------------------------------------------------------
.if debug == 1
w8sp
        jsr w8sp2
        bne w8sp
w8sp1
        jsr w8sp2
        beq w8sp1
        lda #0
        sta $c6
w8sp2
        lda $dc00
        and $dc01
        and #$10
        rts
.endif
;------------------------------------------------------------
MirrorHiresSprite

        lda #$02  ;destination must be copied backward every 3 bytes
        sta zpd    ; 012 -> 210, 345 -> 543 etc

        ldy #$00
        sty zps
        sty app
        sty cnt

lp1     ldy zps
        cpy #$3f  ; 1sprite is made of 63 bytes
        beq exit
.if debug == 1
        jsr w8sp  ;4 debug, every byte
.endif
        lda (src),y

        ldx #7    ;mirror one byte, hires sprite
lp2
        lsr        ;put the rightmost bit of spr1 to carry
        rol app    ;put carry to the rightmost bit of sp2 then shift to left
        dex
        bpl lp2

        lda app
        ldy zpd    ; now set current byte in spr2 with app
        sta (dst),y
        inc zps    ;next source index
        dec zpd    ;previous dest index

        inc cnt
        lda cnt
        cmp #03    ; processed 3 bytes? goto next row
        bne lp1
      ;jsr w8sp  ;4 debug, every row
        lda #0
        sta cnt

        lda zpd
        clc
        adc #6    ; 3rd byte of next row at dest
        sta zpd
        bne lp1    ; jmp is also ok but 3 bytes
exit
        rts
;------------------------------------------------------------
        *= $08c0
sprite1
        byte %11110011,%11101111,%10100000
        byte %00001000,%00000000,%00100000
        byte %11110011,%10001110,%00100000
        byte %10001010,%00001000,%00100000
        byte %10001011,%11101000,%00111110
        byte %00000000,%00000000,%00000000
        byte %00011111,%00111001,%11100000
        byte %00000000,%00000100,%00010000
        byte %00011100,%01000000,%00010000
        byte %00010000,%01000100,%00010000
        byte %00011111,%00111000,%00010000
        byte %00000000,%00000000,%00000000
        byte %01010101,%01010101,%01010101
        byte %00000000,%00000000,%00000000
        byte %11111001,%00010100,%01111010
        byte %00000100,%00010000,%10000010
        byte %00000101,%11110100,%01110010
        byte %00000101,%00010100,%00001010
        byte %00000101,%00010100,%00001000
        byte %00000101,%00010100,%00001010
        byte %00000101,%00010101,%11110010
        byte 0
sprite2
;------------------------------------------------------------

Il problema degli sprites multicolor invece e' rappresentato dal fatto che i bit devono essere shiftati a coppie, pena l'inversione dei colori.
Studiando il sorgente di Elav ne ho tratto uno schema esemplificativo, per vedere come le coppie di bit viaggiavano da un byte all'altro.
Codice: [Seleziona]
; mirror di 1 byte in un multicolor sprite
;esempio, 00-10-01-11
                          ;    A     C   temp2      temp3
                          ; 00100111 0  00000000   00000000
;1a coppia
      lsr                 ; 00010011>1  00000000   00000000
      rol  temp3          ; 00010011 0  00000000   00000001<C
      lsr                 ; 00001001>1  00000000   00000001
      rol  temp2          ; 00001001 0  00000001<C 00000001
      lsr  temp3          ; 00001001 1  00000001   00000000>C
      rol  temp2          ; 00001001 0  00000011<C 00000000
;2a coppia
      lsr                 ; 00000100>1  00000011   00000000
      rol  temp3          ; 00000100 0  00000011   00000001<C
      lsr                 ; 00000010 0  00000011   00000001
      rol  temp2          ; 00000010 0  00000110<C 00000001
      lsr  temp3          ; 00000010 1  00000110   00000000>C
      rol  temp2          ; 00000010 0  00001101<C 00000000
;3a coppia
      lsr                 ; 00000001 0  00001101   00000000
      rol  temp3          ; 00000001 0  00001101   00000000<C
      lsr                 ; 00000000>1  00001101   00000000
      rol  temp2          ; 00000000 0  00011011<C 00000000
      lsr  temp3          ; 00000000 0  00011011   00000000>C
      rol  temp2          ; 00000000 0  00110110   00000000
;4a coppia
      lsr                 ; 00000000 0  00110110   00000000
      rol  temp3          ; 00000000 0  00110110   00000000<C
      lsr                 ; 00000000 0  00110110   00000000
      rol  temp2          ; 00000000 0  01101100   00000000
      lsr  temp3          ; 00000000 0  01101100   00000000>C
      rol  temp2          ; 00000000 0  11011000   00000000
                                        ;mirrored

-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -

Alberto

  • Utente
  • **
  • Post: 589
  • Gioco Preferito: Grand Prix Circuit
Specchiare Uno Sprite Sull'asse X
« Risposta #1 il: 02 Agosto 2006, 21:30:14 »
 Tutorial molto interessante,specie per chi volesse cominciare a smanettare con la grafica... ;)  

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Specchiare Uno Sprite Sull'asse X
« Risposta #2 il: 19 Agosto 2006, 04:53:10 »
 Speravo che qualcuno almeno facesse la domanda: e per specchiare sull'asse Y?
Sperando di suscitare l'interesse posto anche il programma che fa entrambi gli specchiamenti.
Il codice e' anche ottimizzato dove possibile.
Codice: [Seleziona]
;------------------------------------------------------------
; mirror one hires sprite on X & Y axis
; iAN CooG/HokutoForce
;------------------------------------------------------------
       *=$801
debug = 1
src = $fb
dst = $fd
zps = $02
app = $03
zpd = $04
cnt = $05
sprptr= $07f8
SPR0X = $d000
SPR0Y = $d001
SPR1X = $d002
SPR1Y = $d003
SPR2X = $d004
SPR2Y = $d005
SPR3X = $d006
SPR3Y = $d007
SPRact  = $d015
SPR1col = $D027

;------------------------------------------------------------
        word eop
        word 7102
        byte $9e,[start]d,0
eop
        word 0
;------------------------------------------------------------
start
        jsr $e544
        dex

        ldy #[sprite1/$40]
setsprptr
        tya
        sta sprptr,x
        lda #1
        sta SPR1col,x
        iny
        inx
        cpx #4
        bne setsprptr

        lda #%00001111
        sta SPRact

        lda #100
        sta SPR0X
        sta SPR0Y
        sta SPR1Y
        sta SPR2X
        lda #124
        sta SPR2Y
        sta SPR1X
        sta SPR3X
        sta SPR3Y

        lda #<sprite1
        sta src
        lda #<sprite3
        sta dst
        lda #>sprite1
        sta src+1
       ;lda #>sprite3
        sta dst+1

        jsr MirrorHiresSpriteY

        lda #<sprite1
        sta src
        lda #<sprite2
        sta dst
        lda #>sprite1
        sta src+1
       ;lda #>sprite2
        sta dst+1

        jsr MirrorHiresSpriteX

        lda #<sprite2
        sta src
        lda #<sprite4
        sta dst
        lda #>sprite2
        sta src+1
       ;lda #>sprite4
        sta dst+1

        jmp MirrorHiresSpriteY
       ;rts
;------------------------------------------------------------
.if debug == 1
w8sp
        jsr w8sp2
        bne w8sp
w8sp1
        jsr w8sp2
        beq w8sp1
        lda #0
        sta $c6
w8sp2
        lda $dc00
        and $dc01
        and #$10
        rts
.endif
;------------------------------------------------------------
subroutine
MirrorHiresSpriteX

        lda #$02   ;destination must be copied backward every 3 bytes
        sta zpd    ; 012 -> 210, 345 -> 543 etc

        ldy #$00
        sty zps
        sty app
        sty cnt


.lp1    ldy zps
        cpy #$3f   ; 1sprite is made of 63 bytes
        beq .exit
;.if debug == 1
       ;jsr w8sp   ;4 debug, every byte
;.endif
        lda (src),y

        ldx #7     ;mirror one byte, hires sprite
.lp2
        lsr        ;put the rightmost bit of spr1 to carry
        rol app    ;put carry to the rightmost bit of sp2 then shift to left
        dex
        bpl .lp2

        lda app
        ldy zpd    ; now set current byte in spr2 with app
        sta (dst),y
        inc zps    ;next source index
        dec zpd    ;previous dest index

        inc cnt
        lda cnt
        cmp #03    ; processed 3 bytes? goto next row
        bne .lp1
.if debug == 1
        jsr w8sp   ;4 debug, every row
.endif
        lda #0
        sta cnt

        lda zpd
        clc
        adc #6     ; 3rd byte of next row at dest
        sta zpd
        bne .lp1    ; jmp is also ok but 3 bytes
.exit
        rts
;------------------------------------------------------------
subroutine
MirrorHiresSpriteY
        lda #[20*3]; dest index set to last row, 1st byte
        sta zpd
        ldy #0
        sty zps

.lp1
        ldx #3
.lp2
        ldy zps
        cpy #$3f
        beq .exit
        lda (src),y
        ldy zpd
        sta (dst),y
        inc zps
        inc zpd
        dex
        bne .lp2
.if debug == 1
        jsr w8sp   ;4 debug, every byte
.endif
        lda zpd
        sec
        sbc #6
        sta zpd
        bpl .lp1
.exit
        rts
;------------------------------------------------------------
        *= $0900
sprite1
        byte %11110011,%11101111,%10100000
        byte %00001000,%00000000,%00100000
        byte %11110011,%10001110,%00100000
        byte %10001010,%00001000,%00100000
        byte %10001011,%11101000,%00111110
        byte %00000000,%00000000,%00000000
        byte %00011111,%00111001,%11100000
        byte %00000000,%00000100,%00010000
        byte %00011100,%01000000,%00010000
        byte %00010000,%01000100,%00010000
        byte %00011111,%00111000,%00010000
        byte %00000000,%00000000,%00000000
        byte %01010101,%01010101,%01010101
        byte %00000000,%00000000,%00000000
        byte %11111001,%00010100,%01111010
        byte %00000100,%00010000,%10000010
        byte %00000101,%11110100,%01110010
        byte %00000101,%00010100,%00001010
        byte %00000101,%00010100,%00001000
        byte %00000101,%00010100,%00001010
        byte %00000101,%00010101,%11110010
        byte 0
sprite2
        ds $40,0
sprite3
        ds $40,0
sprite4
        ds $40,0
;------------------------------------------------------------

-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Specchiare Uno Sprite Sull'asse X
« Risposta #3 il: 21 Agosto 2006, 03:40:03 »
Ecco il prg compilato
« Ultima modifica: 21 Gennaio 2015, 22:25:00 da eregil »
-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -