Autore Topic: Bitmap Fading  (Letto 2862 volte)

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Bitmap Fading
« il: 21 Maggio 2005, 18:54:49 »
 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)
8) 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. ;)


Codice: [Seleziona]
;---------------------------------
; 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
-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -