Ready64 Forum
Commodore 64 => Programmazione, Grafica e Musica => Topic aperto da: iAN CooG - 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.
01010101 >>>C
|
00000000 <<<C
ripetendo questo per 8 volte abbiamo ribaltato un byte.
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.
;------------------------------------------------------------
; 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.
; 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
-
Tutorial molto interessante,specie per chi volesse cominciare a smanettare con la grafica... ;)
-
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.
;------------------------------------------------------------
; 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
;------------------------------------------------------------
-
Ecco il prg compilato