Un immagine tipo koala e' composta da:
8000 bytes = bitmap
1000 bytes = mem schermo ($0400)
1000 bytes = mem colore ($D800)
1 byte = colore schermo ($D021)
I colori per un bitmap multicolor sono sia nella normale mem colore a $D800
che nella memoria video, con le particolarita' che la mem a $d800 viene usata
solo nel nibble basso (valori da 0 a 15, la parte alta va ignorata) mentre
quella video usa entrambi i nibble.
Il fading di una schermata puo' essere ottenuta facendo passare tutti i colori
da "chiaro" a "scuro" fino ad arrivare al "nero" che per nostra fortuna e'
il valore 0.
Ad esempio il bianco ($1) puo' diventare grigio chiaro ($f), poi grigio ($c),
grigio scuro ($b) e infine nero ($0).
Preparare una tabella di conversione di 16 byte che contenga il colore in cui
ogni valore dovra' assumere si puo' fare cosi:
pos 0 metto 0 (nero deve rimanere nero)
pos 1 metto f (bianco diventa grigio chiaro)
pos 2 metto e (rosso diventa rosa)
pos 3 metto 1 (cyan diventa bianco)
...
pos f metto d (grigio chiaro diventa grigio)
Applicare questo alla memoria a $d800 e' semplice
1) prendere il valore a (locazione_corrente)
2) considerare solo il nibble basso (AND #$0f)
3) usare il valore come posizione nella tabella di conversione e prenderne il
contenuto
4) rimpiazzare a (locazione_corrente) il nuovo valore
5) incrementare locazione_corrente e tornare a 1 finche' non sono fatti tutti
i 1000 byte.
La mem a $0400 e' piu' complicata perche' dovremmo spezzare i nibble alti e
bassi:
1) prendere il valore a (locazione_corrente)
2) considerare solo il nibble basso (AND #$0f)
3) usare il valore come posizione nella tabella di conversione e prenderne il
contenuto
4) tenere il valore in (variabile_temp)
5) prendere il valore a (locazione_corrente)
6) considerare solo il nibble alto con uno shift a destra di 4 bit
(es: $f0 -> $0f)
7) come 3)
riportare il valore nel nibble alto con uno shift a sx ($0b -> $b0)
9) sommare valore con (variabile_temp)
a) rimpiazzare a (locazione_corrente) il nuovo valore
B) incrementare locazione_corrente e tornare a 1 finche' non sono fatti tutti
i 1000 byte.
Ho constatato che tutto questo riduce la performance di molto.
L'ideale sarebbe quello di avere una tabella di 256 elementi con tutti i valori
possibili in entrambi i nibble.
La versione precedente di questa routine l'avevo preparata con tutta la
tabella gia' pronta, poi ho voluto provare a generarla a runtime lasciando solo
i primi 16 come valori iniziali per poter generare i rimanenti 240.
La si puo' vedere remmata com'era e come diventera' una volta generata.
Per il resto, la routine di fading vera e propria utilizza cicli di 200 byte
anziche' 256 per evitare che i singoli cicli finiscano a meta' di una riga.
200 byte sono esattamente 5 righe, e 200x5= 1000, adatto per evitare sprechi,
come invece si otterrebbe con 256x4=1024, 24 byte di dati in piu' elaborati
per niente
Un ringraziamento a Zeitgeist/Civitas, il suo articolo a riguardo mi e'
servito per creare una routine simile che uso sempre nei miei cracks.
;---------------------------------
; Bitmap fade out
; iAN CooG/HokutoForce
;---------------------------------
*= $c000
colorsoffs = $D800
screenoffs = $0400
counter = $fb
buff = $fb
temp = $fc
skip = $fd
;nopme jsr preparefade; 1st time
;lda #$2c
;sta nopme
fadegfx
lda #$10
sta counter
fadeloop
jsr resetcolptrs
loopcnt
;lda $d012;for debug
;bne *-3
cnt1
LDA colorsoffs,X
and #$0f
beq cnt3 ;*+8
TAY
LDA fadetable,Y
cnt2
STA colorsoffs,X
cnt3
LDA screenoffs,X
beq cnt5
TAY
LDA fadetable,Y
cnt4
STA screenoffs,X
cnt5
INX
cpx #200
BNE loopcnt
lda cnt1+1
clc
adc #200
sta cnt1+1
bcc *+5
inc cnt1+2
lda cnt2+1
clc
adc #200
sta cnt2+1
bcc *+5
inc cnt2+2
lda cnt3+1
clc
adc #200
sta cnt3+1
bcc *+5
inc cnt3+2
lda cnt4+1
clc
adc #200
sta cnt4+1
bcc *+5
inc cnt4+2
ldx #0
dec $02
bne loopcnt
screencol
;LDA $d021
;and #$0f
;beq *+9
;TAY
;LDA fadetable,Y
;STA $d021
DEC counter
Bne fadeloop
;lda #$10
;sta counter
RTS
resetcolptrs
lda #0
sta cnt1+1
sta cnt2+1
sta cnt3+1
sta cnt4+1
lda #>colorsoffs
sta cnt1+2
sta cnt2+2
lda #>screenoffs
sta cnt3+2
sta cnt4+2
ldy #5
sty $02
ldx #0
RTS
;-----------------------------------------
preparefade
ldy #$0f
lda #$FF
sta skip;array position
prp2
ldx #$0f
prp1
lda fadetable,y
asl
asl
asl
asl
sta buff
lda fadetable,x
ora buff
stx temp
ldx skip
sta fadetable,x
ldx temp
dec skip
dex
bpl prp1
dey
bne prp2
rts
;greyscale
fadetable
; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; a; b; c; d; e; f
byte $00,$0F,$0B,$0F,$07,$0F,$0C,$0F,$07,$0C,$07,$00,$0B,$07,$0C,$0C ; 0
;byte $F0,$FF,$FB,$FF,$F7,$FF,$FC,$FF,$F7,$FC,$F7,$F0,$FB,$F7,$FC,$FC ; 1
;byte $B0,$BF,$BB,$BF,$B7,$BF,$BC,$BF,$B7,$BC,$B7,$B0,$BB,$B7,$BC,$BC ; 2
;byte $F0,$FF,$FB,$FF,$F7,$FF,$FC,$FF,$F7,$FC,$F7,$F0,$FB,$F7,$FC,$FC ; 3
;byte $70,$7F,$7B,$7F,$77,$7F,$7C,$7F,$77,$7C,$77,$70,$7B,$77,$7C,$7C ; 4
;byte $F0,$FF,$FB,$FF,$F7,$FF,$FC,$FF,$F7,$FC,$F7,$F0,$FB,$F7,$FC,$FC ; 5
;byte $C0,$CF,$CB,$CF,$C7,$CF,$CC,$CF,$C7,$CC,$C7,$C0,$CB,$C7,$CC,$CC ; 6
;byte $F0,$FF,$FB,$FF,$F7,$FF,$FC,$FF,$F7,$FC,$F7,$F0,$FB,$F7,$FC,$FC ; 7
;byte $70,$7F,$7B,$7F,$77,$7F,$7C,$7F,$77,$7C,$77,$70,$7B,$77,$7C,$7C ; 8
;byte $C0,$CF,$CB,$CF,$C7,$CF,$CC,$CF,$C7,$CC,$C7,$C0,$CB,$C7,$CC,$CC ; 9
;byte $70,$7F,$7B,$7F,$77,$7F,$7C,$7F,$77,$7C,$77,$70,$7B,$77,$7C,$7C ; a
;byte $00,$0F,$0B,$0F,$07,$0F,$0C,$0F,$07,$0C,$07,$00,$0B,$07,$0C,$0C ; b
;byte $B0,$BF,$BB,$BF,$B7,$BF,$BC,$BF,$B7,$BC,$B7,$B0,$BB,$B7,$BC,$BC ; c
;byte $70,$7F,$7B,$7F,$77,$7F,$7C,$7F,$77,$7C,$77,$70,$7B,$77,$7C,$7C ; d
;byte $C0,$CF,$CB,$CF,$C7,$CF,$CC,$CF,$C7,$CC,$C7,$C0,$CB,$C7,$CC,$CC ; e
;byte $C0,$CF,$CB,$CF,$C7,$CF,$CC,$CF,$C7,$CC,$C7,$C0,$CB,$C7,$CC,$CC ; f