Buonasera a tutti,
dopo aver scritto una routine di DMA Delay ho voluto cimentarmi nella naturale evoluzione di quell'effetto.
Il programma che allego in questo thread é un esempio di AGSP (Any Given Screen Position): questo effetto si ottiene usando DMA Delay per gli spostamenti orizzontali (modulo
ed il linecrunch per quelli verticali (modulo 7).
Analogamente al caso precedente, non viene effettuata alcuna modifica nei valori dello schermo, lo scrolling é totalmente hardware.
Questo effetto si presta molto bene alla realizzazione di platform, non fosse per quei maledettissimi 8 byte degli sprite pointers (per i quali esistono delle soluzioni compromesso).
Noterete che lo schermo risulta più piccolo del normale, ciò é dovuto al fatto che nella zona superiore vengono realizzati gli effetti e vengono coperti usando una delle modalità grafiche illegali (EBCM+BITMAP).
Cambiando colore al bordo ($d020) si può notare l'area interessata.
Per i più curiosi, commentando le linee 132,133,175,176,203 é possibile gestire "a mano" il riposizionamento dello schermo usando le seguenti variabili:
$F7: Posizione verticale (0-206)
$F9: Posizione orizzontale (0-39)
La posizione verticale é gestibile per linea, quella orizzontale per carattere.
Al solito, commenti, consigli ecc... son sempre i benvenuti!
Ecco il source:
; AGSP - By Freshness
;
; Grazie iAN, ci sono ancora alcuni FIX tuoi nella parte di
; inizializzazione dell'IRQ e nei comandi basic!
;
;
NOPOpcode = $EA
rastline = $2E;
ypospre = $F7; Posizione base pre-fixing
ypos = $F8; Posizione verticale
XValue = $F9; Shift verticale dovuto al DMA
Increment = $FA; Incremento verticale (0-7)
CrunchShf = $FB; Shift orizzontale dovuto al crunch
setDEN = $FC; Imposta il primo valore di $d011 per frame
sinuspos = $FD; Indice delle sinustable
xpos = $FE; Posizione orizzontale corrente
temp = $FF; Uso generico
*=$0801
word eoprg
word 2009
byte $9E,[intro]d,":",$8f,$0d,"AGSP BY FRESHNESS79"
byte 0
eoprg
word 0
intro
lda #$72 ; Attivazione schermo (D011 - bit DEN)
sta setDEN
lda #$00 ; Resetta la posizione della sinus table
sta $d020 ; Resetta il colore del bordo (nero),
sta XValue; Coordinata X fissa,
sta sinuspos; Indice sinustable,
sta Increment; Incremento coordinata Y
jsr initIRQ ; Inizializzazione raster IRQ
cli ; Interrupt attivati
rts
; ***************************************************
; * Routine di sincronizzazione a doppio raster IRQ *
; ***************************************************
; La prima chiamata IRQ e' su JMP, quindi l'incertezza e' di 1-3 cicli
; Il primo handler permette di ridurla a 1-2 cicli: IRQ arriva sulla NOP
; Il secondo handler infine grazie ad un confronto a fine raster elimina
; l'ultima possibile incertezza
fstirq ; 2E
lsr $d019 ; 6 + (36 Kernal IRQ) + (da 2 a 4 JMP)
inc $d012 ; 6 interrupt al prossimo raster
lda #<secirq ; 2 reimposto il vettore IRQ perche' punti
sta $0314 ; 4 al secondo handler
cli ; 2 attivo gli interrupt
nop ; 2 (63-65) <= IRQ
nop ; 2 (65-67) <= IRQ
nop
nop
nop
nop
brk ; Qua non ci si arriva mai, lascio BRK per test
secirq ; $2F
lda setDEN; 2w +38 (+0/1); Evita la badline
sta $d011 ; 4 nella prima linea (la $30)
sec ; 2 Serve per la sottrazione nel successivo ciclo
lda ypos ; 3 Imposta il contatore dello scroll
sta temp ; 3 verticale
ldx #$71 ; 2 Imposta il primo valore di crunching
ldy #$00 ; 2 Resetta numero di linee "crunched"
lda #$2F ; 2 Stabilizzazione raster
eor $d012 ; 4 - 63 se il ritardo dovuto alla NOP era 1 (uso EOR per mantenere il carry)
beq crunch ; 3 effettuo un branch per allinearmi
; linecrunch
; ----------
; Spostamento verticale a blocchi di 7 linee per ciclo
crunch ; Synced - line $30
stx $d011 ; 4 Ciclo 11: abortisce la badline (linecrunch)
ds $12,NOPOpcode; 36w (18 NOPs)
lda temp ; 3 Aggiorna contatore scroll
sbc #$07 ; 2 verticale
sta temp ; 3
bcc DmaDelay; 2/3 Se mancano meno di 7 linee va al Dma Delay
nop ; 2w
nop ; 2
iny ; 2
ldx lctable-1,y; 4 Carica il prossimo valore per il linecrunch
bne crunch; 3 - 63 cicli totali
; Dma Delay
; ----------
; Spostamento orizzontale da 0 a 39 caratteri
DmaDelay
inc $d011 ; 6 fa in modo che la prossima linea non sia una bad line
lda xpos ; 3 calcolo dei cicli da aspettare
lsr ; 2 usando i due branch
sta wdcc+1; 4
bcc wdcc ; 2/3 branch unitario (0/1)
wdcc
bpl * ; 3 branch multiplo di 2 (2-38)
ds $13,NOPOpcode; 19 NOPs
stx $d011 ; crea la bad line (DMA delay)
; Fine Tune Y
; ----------
; Spostamento verticale da 0 a 6 linee
FineTuneY ; ciclo 55 sempre!
sec ; 2
lda temp ; 3
sty temp ; 3 Conto delle righe saltate
sbc #$fa ; 2 Rimanenti righe da scrollare (scroll fine)
sbc temp ; 3 Sottraggo le linee dovute alle righe saltate
and #$07 ; 2
eor #$77 ; 2 La direzione é contraria quindi 7-X
sta $d011 ; 4 - 21 => 13
; Fine Tune X
; ----------
; Spostamento orizzontale da 0 a 7 pixel
FineTuneX
ldx sinuspos;sinuspos
lda sinuslow,x ; Parte meno significativa dello spostamento
sta $d016 ; orizzontale - scrolling fine
; Impostazioni di fine IRQ
lda #$56 ; Prossimo raster IRQ alla linea 83
sta $d012 ;
lsr $d019 ; Acknowledge del raster IRQ
lda #<irq3; Caricamento prossimo vettore IRQ
sta $0314 ; Salvataggio vettore IRQ
tsx ;
lda #$ff ;
sbx #$fa ;
txs ; ripristino dello stack pointer
jmp $ea81 ; Uscita dall'interruzione
; IRQ3
; ----
; Reimpostazione modalità testo
irq3
lda $d011 ; Carica l'attuale valore di $d011
and #$17 ; Elimina i bit della modalità illegale
ldy #$58 ; Attende la raster line $58
cpy $d012 ;
bne *-3 ;
sta $d011 ; Imposta $D011, da qua in poi si vede.
lda #rastline; Imposta il raster IRQ del frame
sta $d012 ; successivo
lsr $d019 ; Ack dell'interruzione
lda #<fstirq; Reimpostazione dell'IRQ handler,
sta $0314 ; si torna al primo
; UpdatePos
; ---------
; Aggiornamento variabili relative alla posizione orizzontale e verticale
UpdatePos
inc sinuspos; Incremento posizione sinus table
ldx sinuspos; Carico in X l'indice
lda sinusspeed,x; L'incremento é precalcolato e
sta Increment; viene preso da una sinustable
lda ypospre; Incremento posizione verticale
clc ;
adc Increment;
sta ypospre ;
cmp #$cf ; Supera la dimensione massima? (200+7)
bcc EndUpdate
sbc #$cf ; Si, sottrai 207, si riparte da 0
sta ypospre ;
lda CrunchShf; Aumenta di 16 lo shift dovuto al linecrunch
adc #$0f ; Carry abilitato quindi +$10
sta CrunchShf;
cmp #$28 ; Lo shift ha superato i 40 caratteri?
bcc EndUpdate
sbc #$28 ; Si, sottrai 40, si riparte da 0
sta CrunchShf;
lda ypospre; Shifta di 8 linee la posizione verticale
adc #$07 ; Carry abilitato quindi +$07
sta ypospre
; EndUpdate
; ---------
; Calcola l'effettivo valore della posizione verticale ed orizzontale
EndUpdate
lda CrunchShf; Aggiunge lo shift dovuto al linecrunch
adc sinushigh,x ; all'attuale valore della sinustable
adc XValue; Coordinata fissa
cmp #$28 ; Confronta con 40
ldy #$00 ;
bcc HNoFix; Se supera 40, sottrai 40 ed segna 8 linee
sbc #$28 ; da skippare nel linecrunch
ldy #$08 ;
HNoFix
sta xpos ; Imposta il valore per il DMA Delay (X Coord)
clc ;
tya ; Fixa il valore della coordinata verticale con
adc ypospre; l'eventuale valore dovuto al DMA Delay
sta ypos ;
jmp $ea31 ; Vai all'handler standard
; ************
; * Init IRQ *
; ************
;
; Disattivazione dell'interrupt standard,
; Impostazione della prima rasterline e dell'indirizzo
; del primo handler della routine di interrupt
; attivazione dei raster interrupt
initIRQ
sei
lda #$7f
sta $dc0d
sta $dd0d
lda $dc0d;non dc0c ! - Fix iANCoog
lda $dd0d;non dd0c !
lda #$00
sta $d011
lda #rastline
sta $d012
lda #<fstirq
sta $0314
lda #>fstirq
sta $0315
lda #$01
sta $d01a
lsr $d019
rts
lctable
byte $72,$73,$74,$75,$76,$77,$70,$71,$72,$73,$74,$75,$76,$77,$70,$71
byte $72,$73,$74,$75,$76,$77,$70,$71,$72,$73,$74,$75,$76,$77,$70,$71
align $100
sinuslow
byte $07,$04,$00,$04,$00,$04,$00,$04,$00,$05,$01,$05,$01,$06,$02,$06
byte $03,$07,$04,$00,$05,$01,$06,$02,$07,$04,$01,$06,$03,$00,$05,$02
byte $07,$04,$02,$07,$05,$02,$00,$06,$03,$01,$07,$05,$03,$01,$00,$06
byte $05,$03,$02,$01,$07,$06,$05,$04,$04,$03,$02,$02,$01,$01,$01,$01
byte $00,$01,$01,$01,$01,$02,$02,$03,$04,$04,$05,$06,$07,$01,$02,$03
byte $05,$06,$00,$01,$03,$05,$07,$01,$03,$06,$00,$02,$05,$07,$02,$04
byte $07,$02,$05,$00,$03,$06,$01,$04,$07,$02,$06,$01,$05,$00,$04,$07
byte $03,$06,$02,$06,$01,$05,$01,$05,$00,$04,$00,$04,$00,$04,$00,$04
byte $07,$03,$07,$03,$07,$03,$07,$03,$07,$02,$06,$02,$06,$01,$05,$01
byte $04,$00,$03,$07,$02,$06,$01,$05,$00,$03,$06,$01,$04,$07,$02,$05
byte $00,$03,$05,$00,$02,$05,$07,$01,$04,$06,$00,$02,$04,$06,$07,$01
byte $02,$04,$05,$06,$00,$01,$02,$03,$03,$04,$05,$05,$06,$06,$06,$06
byte $06,$06,$06,$06,$06,$05,$05,$04,$03,$03,$02,$01,$00,$06,$05,$04
byte $02,$01,$07,$06,$04,$02,$00,$06,$04,$01,$07,$05,$02,$00,$05,$03
byte $00,$05,$02,$07,$04,$01,$06,$03,$00,$05,$01,$06,$02,$07,$03,$00
byte $04,$01,$05,$01,$06,$02,$06,$02,$07,$03,$07,$03,$07,$03,$07,$03
sinushigh
byte $14,$14,$14,$15,$15,$16,$16,$17,$17,$18,$18,$19,$19,$1A,$1A,$1B
byte $1B,$1C,$1C,$1C,$1D,$1D,$1E,$1E,$1F,$1F,$1F,$20,$20,$20,$21,$21
byte $22,$22,$22,$23,$23,$23,$23,$24,$24,$24,$25,$25,$25,$25,$25,$26
byte $26,$26,$26,$26,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27
byte $27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$27,$26,$26,$26
byte $26,$26,$25,$25,$25,$25,$25,$24,$24,$24,$23,$23,$23,$23,$22,$22
byte $22,$21,$21,$20,$20,$20,$1F,$1F,$1F,$1E,$1E,$1D,$1D,$1C,$1C,$1C
byte $1B,$1B,$1A,$1A,$19,$19,$18,$18,$17,$17,$16,$16,$15,$15,$14,$14
byte $14,$13,$13,$12,$12,$11,$11,$10,$10,$0F,$0F,$0E,$0E,$0D,$0D,$0C
byte $0C,$0B,$0B,$0B,$0A,$0A,$09,$09,$08,$08,$08,$07,$07,$07,$06,$06
byte $05,$05,$05,$04,$04,$04,$04,$03,$03,$03,$02,$02,$02,$02,$02,$01
byte $01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$01,$01
byte $01,$01,$02,$02,$02,$02,$02,$03,$03,$03,$04,$04,$04,$04,$05,$05
byte $05,$06,$06,$07,$07,$07,$08,$08,$08,$09,$09,$0A,$0A,$0B,$0B,$0B
byte $0C,$0C,$0D,$0D,$0E,$0E,$0F,$0F,$10,$10,$11,$11,$12,$12,$13,$13
sinusspeed
dc.b $4,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$2,$2
dc.b $2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$1,$1
dc.b $1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1
dc.b $1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1
dc.b $1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1
dc.b $1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1,$1
dc.b $1,$1,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2,$2
dc.b $2,$2,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3,$3
dc.b $4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$5,$5
dc.b $5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$6,$6
dc.b $6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6
dc.b $6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6
dc.b $6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6
dc.b $6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6,$6
dc.b $6,$6,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5,$5
dc.b $5,$5,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4,$4