Autore Topic: Scrolling Orizzontale  (Letto 5667 volte)

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« il: 19 Aprile 2010, 15:03:56 »
 Dopo aver letto un bel po di materiale mi sono cimentato nella stesura della mia prima routine di scrolling orizzontale.
Per il momento non sono ancora in grado di comprendere le tecniche avanzate basate puramente sull'uso del VIC-II (es: dma delay) ed ho realizzato il tutto con un meccanismo di double buffer e split copy della memoria video.
Si può scorrere lo schermo in una sola direzione muovendo il joy a dx.
La colorazione del bordo indica il raster time dalla routine che ovviamente aumenta quando si deve copiare la memoria video.
La copia della color memory è per il momento disabilitata (mi crea un po di problemi)

Vorrei inserire anche lo scroll a sx e, considerando che in un ipotetico gioco si fa molto di più che scrollare uno schermo, mi chiedevo se era possibile ottimizzare qualcosa per ridurre ulteriormente il raster time occupato...

Codice: [Seleziona]
processor 6502

; Costanti
rastline    = $fA;
screenD  = $0400;
screen0  = $3800;
screen1  = $3c00;
color  = $d800

; Variabili zero page
temp    = $FF
joy2    = $FE
cscr  = $FD

org $0801

    word eop
    word 7102
    byte $9e,"2061",0
eop word 0

org $080D;Inizio del programma

main
    sei
;Copio lo schermo di default
ldx #$00
lpCmpS
lda screenD,x
sta screen0,x
lda screenD+255,x
sta screen0+255,x
lda screenD+255*2,x
sta screen0+255*2,x
lda screenD+255*3,x
sta screen0+255*3,x
inx
cpx #$ff
bne lpCmpS

lda #$C4;Posizione di scrolling iniziale e scrolling HW nel mezzo
sta $D016

lda #$E4;Attivo schermo 0 (11100100 E4)

sta $d018
lda #$00;Indicatore dello schermo corrente
sta cscr


jsr initIRQ

    cli

jmp *  ;Loop infinito
    rts

initIRQ
lda #<routineIRQ;Indirizzo codice (parte alta)
sta $0314
lda #>routineIRQ;Indirizzo codice (parte bassa)
sta $0315

lda #rastline;Raster line di attivazione IRQ raster
    sta $d012
lda #$1b;Azzera il bit 7 che sarebbe il Raster Compare: (Bit 8) di $d012
sta $D011

lda #$7f;01111111 BIT 7 a 0
sta $dc0d;Azzera il bit 7 di CIA Interrupt Control Register (Read IRQs/Write Mask) per disattivarlo
sta $dd0d;Azzera il bit 7 di CIA Interrupt Control Register (Read NMls/Write Mask)  per disattivarlo
lda $dc0d  ;Non so a che derve !?!  
lda $dd0d  ;Non so a che derve !?!

lda #$01  ;Abilita IRQ  raster
    sta $d019  ;VIC Interrupt Flag Register (Bit = 1: IRQ Occurred)
    sta $d01a  ;IRQ Mask Register: 1 = Interrupt Enabled
rts

routineIRQ
inc $d019;Dico al vic che la routine è sata eseguita

;Colora una raster line per capire quanto raster consumo per scrollare
inc $d020;riga 1

; Leggo joy porta 2
lda $DC00  
sta joy2;Salvo lo stato del joy2
  
;scrolla schermo a SX di un carattere
lda joy2;Superfluo in questo punto
and #%00001000;dx
bne lpExit;Se zero salta
  ;Se diverso da Zero Scroll
;X HW Scroll bit 2-0
ldx $D016
dex

cpx #$C3; - Copiare la prima parte da schermo a 3
bne lpCont1;NO
lda cscr  
beq lpSCU;Screen 0
jsr scrollSsxU10
jmp lpCont1
lpSCU
jsr scrollSsxU01
lpCont1

cpx #$C1; - Copiare la seconda parte da schermo a 1
bne lpCont2;NO
lda cscr  
beq lpSCD;Screen 0
jsr scrollSsxD10
jmp lpCont2
lpSCD
jsr scrollSsxD01
lpCont2

cpx #$BF;Superato il limite?
bne lpContE;NO
ldx #$C7;Riporta il bit di scroll a 7
lda cscr;Switch screens
beq lpSW1;Screen 0
lda #$E4;Attivo schermo 0
sta $d018
lda #$00;Indicatore dello schermo corrente
sta cscr  
jmp lpSW0
lpSW1
lda #$F4;Attivo schermo 1 (11110100 F4)
sta $d018
lda #$01;Indicatore dello schermo corrente
sta cscr  
lpSW0
;jsr scrollCsx;Scrolla anche Color Memory

lpContE
stx $D016

lpExit
;Rimetto colore riga a posto
    dec $d020

;Queste ultime 6 righe determinano il ritorno del codice all'interrupt HANDLER
;Se voglio creare una routine che venga eseguita mentre il basic è attivo
;sostituisco le 6 righe con JMP $ea31
pla  ;Pull Accumulator from Stack
tay  ;transfer A to Y
pla  ;Pull Accumulator from Stack
tax  ;transfer A to X
pla  ;Pull Accumulator from Stack
;JMP $ea31
rti        ; return from interrupt

scrollSsxU01
YSU01 SET 0
    REPEAT 12
  XSU01 SET 0
  REPEAT 39
  lda screen0+XSU01+YSU01+1
  sta screen1+XSU01+YSU01
  XSU01 SET XSU01 + 1
  REPEND
YSU01 SET YSU01 + 40
REPEND
rts

scrollSsxD01
YSD01 SET 12*40
    REPEAT 13
  XSD01 SET 0
  REPEAT 39
  lda screen0+XSD01+YSD01+1
  sta screen1+XSD01+YSD01
  XSD01 SET XSD01 + 1
  REPEND
YSD01 SET YSD01 + 40
REPEND
rts

scrollSsxU10
YSU10 SET 0
    REPEAT 12
  XSU10 SET 0
  REPEAT 39
  lda screen1+XSU10+YSU10+1
  sta screen0+XSU10+YSU10
  XSU10 SET XSU10 + 1
  REPEND
YSU10 SET YSU10 + 40
REPEND
rts

scrollSsxD10
YSD10 SET 12*40
    REPEAT 13
  XSD10 SET 0
  REPEAT 39
  lda screen1+XSD10+YSD10+1
  sta screen0+XSD10+YSD10
  XSD10 SET XSD10 + 1
  REPEND
YSD10 SET YSD10 + 40
REPEND
rts

scrollCsx
YC SET 0
    REPEAT 25
  XC SET 0
  REPEAT 39
  lda color+XC+YC+1
  sta color+XC+YC
  XC SET XC + 1
  REPEND
YC SET YC + 40
REPEND
rts  

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #1 il: 21 Aprile 2010, 09:50:27 »
 Ho aggiunto anche lo scroll della color memory che però ho dovuto ridurre di complessita (20*25) per riuscire a far stare tutto nel raster time del bordo inferiore.

Ovviamente rimane aperta la mia richiesta di consigli riguardo l'ottimizzazione della routine oppure lo stravolgimento della stessa nel caso in cui ci siano delle scelte di fondo poco azzeccate...

Codice: [Seleziona]
processor 6502

; Costanti
rastline    = $fA;
screenD  = $0400;
screen0  = $3800+$8000;
screen1  = $3C00+$8000;
color  = $d800

; Variabili zero page
temp    = $FF
joy2    = $FE
cscr  = $FD

org $0801

    word eop
    word 7102
    byte $9e,"2061",0
eop word 0

org $080D;Inizio del programma

main
    sei

;Imposto color MAP
ldx #$00
lpCmpC
lda colormap20X25,x
sta color,x
lda colormap20X25+255,x
sta color+255,x
lda colormap20X25+255*2,x
sta color+255*2,x
lda colormap20X25+255*3,x
sta color+255*3,x
inx
cpx #$ff
bne lpCmpC

lda #$36;Libero A000-BFFF dalla BASIC ROM RAM (Freshness79)
sta $01

lda #$15;Seleziono banco 2 ($8000-$BFFF 00010101)  
sta $dd00

lda #$C4;Posizione di scrolling iniziale e scrolling HW nel mezzo
sta $D016

lda #$E4;Attivo schermo 0 (11100100 E4)
sta $d018

lda #$00;Indicatore dello schermo corrente
sta cscr

jsr initIRQ

    cli

jmp *  ;Loop infinito
    rts

initIRQ
lda #<routineIRQ;Indirizzo codice (parte alta)
sta $0314
lda #>routineIRQ;Indirizzo codice (parte bassa)
sta $0315

lda #rastline;Raster line di attivazione IRQ raster
    sta $d012
lda #$1b;Azzera il bit 7 che sarebbe il Raster Compare: (Bit 8) di $d012
sta $D011

lda #$7f;01111111 BIT 7 a 0
sta $dc0d;Azzera il bit 7 di CIA Interrupt Control Register (Read IRQs/Write Mask) per disattivarlo
sta $dd0d;Azzera il bit 7 di CIA Interrupt Control Register (Read NMls/Write Mask)  per disattivarlo
lda $dc0d  ;Non so a che derve !?!  
lda $dd0d  ;Non so a che derve !?!

lda #$01  ;Abilita IRQ  raster
    sta $d019  ;VIC Interrupt Flag Register (Bit = 1: IRQ Occurred)
    sta $d01a  ;IRQ Mask Register: 1 = Interrupt Enabled
rts

routineIRQ
inc $d019;Dico al vic che la routine è sata eseguita

;Colora una raster line per capire quanto raster consumo per scrollare
inc $d020;riga 1

; Leggo joy porta 2
lda $DC00  
sta joy2;Salvo lo stato del joy2
  
;scrolla schermo a SX di un carattere
lda joy2;Superfluo in questo punto
and #%00001000;dx
bne lpExit;Se zero salta
  ;Se diverso da Zero Scroll
;X HW Scroll bit 2-0
ldx $D016
dex

cpx #$C3; - Copiare la prima parte da schermo a 3
bne lpCont1;NO
lda cscr  
beq lpSCU;Screen 0
jsr scrollSsxU10
jmp lpCont1
lpSCU
jsr scrollSsxU01
lpCont1

cpx #$C1; - Copiare la seconda parte da schermo a 1
bne lpCont2;NO
lda cscr  
beq lpSCD;Screen 0
jsr scrollSsxD10
jmp lpCont2
lpSCD
jsr scrollSsxD01
lpCont2

cpx #$BF;Superato il limite?
bne lpContE;NO
ldx #$C7;Riporta il bit di scroll a 7
lda cscr;Switch screens
beq lpSW1;Screen 0
lda #$E4;Attivo schermo 0
sta $d018
lda #$00;Indicatore dello schermo corrente
sta cscr  
jsr scrollCsx10;Scrolla anche Color Memory
jmp lpContE

lpSW1
lda #$F4;Attivo schermo 1 (11110100 F4)
sta $d018
lda #$01;Indicatore dello schermo corrente
sta cscr  
jsr scrollCsx01;Scrolla anche Color Memory

lpContE
stx $D016  ;HW Scroll

lpExit
;Rimetto colore riga a posto
    dec $d020

;Queste ultime 6 righe determinano il ritorno del codice all'interrupt HANDLER
;Se voglio creare una routine che venga eseguita mentre il basic è attivo
;sostituisco le 6 righe con JMP $ea31
pla  ;Pull Accumulator from Stack
tay  ;transfer A to Y
pla  ;Pull Accumulator from Stack
tax  ;transfer A to X
pla  ;Pull Accumulator from Stack
;JMP $ea31
rti        ; return from interrupt

scrollSsxU01
YSU01 SET 0
    REPEAT 12
  XSU01 SET 0
  REPEAT 39
  lda screen0+XSU01+YSU01+1
  sta screen1+XSU01+YSU01
  XSU01 SET XSU01 + 1
  REPEND
YSU01 SET YSU01 + 40
REPEND
rts

scrollSsxD01
YSD01 SET 12*40
    REPEAT 13
  XSD01 SET 0
  REPEAT 39
  lda screen0+XSD01+YSD01+1
  sta screen1+XSD01+YSD01
  XSD01 SET XSD01 + 1
  REPEND
YSD01 SET YSD01 + 40
REPEND
rts

scrollSsxU10
YSU10 SET 0
    REPEAT 12
  XSU10 SET 0
  REPEAT 39
  lda screen1+XSU10+YSU10+1
  sta screen0+XSU10+YSU10
  XSU10 SET XSU10 + 1
  REPEND
YSU10 SET YSU10 + 40
REPEND
rts

scrollSsxD10
YSD10 SET 12*40
    REPEAT 13
  XSD10 SET 0
  REPEAT 39
  lda screen1+XSD10+YSD10+1
  sta screen0+XSD10+YSD10
  XSD10 SET XSD10 + 1
  REPEND
YSD10 SET YSD10 + 40
REPEND
rts

scrollCsx01
YC01 SET 0
    REPEAT 25
  XC01 SET 0
  REPEAT 19
  lda color+YC01*40+XC01*2+2
  sta color+YC01*40+XC01*2+1
  XC01 SET XC01 + 1
  REPEND
YC01 SET YC01 + 1
REPEND
rts  

scrollCsx10
YC10 SET 0
    REPEAT 25
  XC10 SET 0
  REPEAT 19
  lda color+YC10*40+XC10*2+1
  sta color+YC10*40+XC10*2
  XC10 SET XC10 + 1
  REPEND
YC10 SET YC10 + 1
REPEND
rts  

colormap20X25
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #2 il: 21 Aprile 2010, 15:39:13 »
 E' abbastanza semplice aggiungere anche l'altra direzione di scrolling ma utilizzando sempre le routine di copia "srotolate" mi ritrovo con quasi metà ram occupata! (da 093E a 9136)

Forse è meglio sacrificare qualcosa in termini di velocità (magari riducendo l'area di scroll) ed utilizzare un ciclo per evitare di consumare cosi tanta memoria?

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Scrolling Orizzontale
« Risposta #3 il: 21 Aprile 2010, 21:55:42 »
 Ciao AntonioMauro,
 come hai già sottolineato tu nel programma usi dei cicli srotolati: considerato il fatto che ha poco senso ottimizzare la parte di impostazione che viene eseguita alla chiamata del raster interrupt (a spanne saranno al max una 50ina di cicli in tutto, stando abbondanti), direi che per il metodo utilizzato - double buffering - non credo ci siano ulteriori possibili ottimizzazioni. Meno di una coppia lda-sta da 8 cicli é proprio impossibile andare.
D'altra parte, come hai fatto giustamente notare, questa implementazione é piuttosto esosa in termini di memoria.
Tenendo dunque presente che qualsiasi compromesso si voglia utilizzare i cicli totali sono necessariamente destinati ad aumentare, ti propongo la mia modifica (trovi i commenti nel codice).

Codice: [Seleziona]
processor 6502

; Costanti
rastline = $B0;
finescrline = $FA;
screenD = $0400;
screen0 = $3800+$8000;
screen1 = $3C00+$8000;
color = $d800

; Variabili zero page
temp = $FF
joy2 = $FE
cscr = $FD
finescroll = $FC
page = $FB

org $0801

word eop
word 7102
byte $9e,"2061",0
eop word 0

org $080D;Inizio del programma

main
sei

;Imposto color MAP
ldx #$00
lpCmpC
lda colormap20X25,x
sta color,x
lda colormap20X25+$100,x
sta color+$100,x
lda colormap20X25+$100*2,x
sta color+$100*2,x
lda colormap20X25+$100*3,x
sta color+$100*3,x
inx
bne lpCmpC

lda #$36;Libero A000-BFFF dalla BASIC ROM RAM (Freshness79)
sta $01

lda #$15;Seleziono banco 2 ($8000-$BFFF 00010101)
sta $dd00

lda #$C4;Posizione di scrolling iniziale e scrolling HW nel mezzo
sta $D016
sta finescroll

lda #$E4;Attivo schermo 0 (11100100 E4)
sta $d018
sta page

lda #$00;Indicatore dello schermo corrente
sta cscr

jsr initIRQ

cli

jmp *;Loop infinito
rts

initIRQ
lda #<routineIRQ;Indirizzo codice (parte alta)
sta $0314
lda #>routineIRQ;Indirizzo codice (parte bassa)
sta $0315

lda #rastline;Raster line di attivazione IRQ raster
sta $d012
lda #$1b;Azzera il bit 7 che sarebbe il Raster Compare: (Bit 8) di $d012
sta $D011

lda #$7f;01111111 BIT 7 a 0
sta $dc0d;Azzera il bit 7 di CIA Interrupt Control Register (Read IRQs/Write Mask) per disattivarlo
sta $dd0d;Azzera il bit 7 di CIA Interrupt Control Register (Read NMls/Write Mask) per disattivarlo
lda $dc0d;Non so a che derve !?!
lda $dd0d;Non so a che derve !?!

lda #$01;Abilita IRQ raster
sta $d019;VIC Interrupt Flag Register (Bit = 1: IRQ Occurred)
sta $d01a;IRQ Mask Register: 1 = Interrupt Enabled
rts

routineIRQ
inc $d019;Dico al vic che la routine è sata eseguita

;Colora una raster line per capire quanto raster consumo per scrollare
inc $d020;riga 1

; ************
; **MODIFICA**
; ************
; Imposto il prossimo raster IRQ

lda #<secondirq
sta $0314
lda #>secondirq
sta $0315
lda #finescrline
sta $d012

; Leggo joy porta 2
lda $DC00
sta joy2;Salvo lo stato del joy2

;scrolla schermo a SX di un carattere

lda joy2;Superfluo in questo punto
and #%00001000;dx
bne lpExit;Se zero salta
;Se diverso da Zero Scroll

;X HW Scroll bit 2-0
ldx $D016
dex

cpx #$C3; - Copiare la prima parte da schermo a 3
bne lpCont1;NO
lda cscr
beq lpSCU;Screen 0
jsr scrollSsxU10
jmp lpCont1
lpSCU
jsr scrollSsxU01
lpCont1

cpx #$C1; - Copiare la seconda parte da schermo a 1
bne lpCont2;NO
lda cscr
beq lpSCD;Screen 0
jsr scrollSsxD10
jmp lpCont2
lpSCD
jsr scrollSsxD01
lpCont2

cpx #$BF;Superato il limite?
bne lpContE;NO

; ************
; **MODIFICA**
; ************
; Basta una sola chiamata allo scroller
; della memoria colore
jsr scrollCsx;Scrolla anche Color Memory

ldx #$C7;Riporta il bit di scroll a 7
lda cscr;Switch screens
beq lpSW1;Screen 0
lda #$E4;Attivo schermo 0
sta page
lda #$00;Indicatore dello schermo corrente
sta cscr

jmp lpContE

lpSW1
lda #$F4;Attivo schermo 1 (11110100 F4)
sta page
lda #$01;Indicatore dello schermo corrente
sta cscr

lpContE
stx finescroll;HW Scroll

lpExit

;Rimetto colore riga a posto
dec $d020

;Queste ultime 6 righe determinano il ritorno del codice all'interrupt HANDLER
;Se voglio creare una routine che venga eseguita mentre il basic è attivo
;sostituisco le 6 righe con JMP $ea31
iret
pla;Pull Accumulator from Stack
tay;transfer A to Y
pla;Pull Accumulator from Stack
tax;transfer A to X
pla;Pull Accumulator from Stack
;JMP $ea31
rti; return from interrupt

; ************
; **MODIFICA**
; ************
; (Da qua in poi e' tutto modificato a parte la mappa)
; IRQ di aggiornamento registri VIC

secondirq
; IRQ Acknowledge

lsr $d019

; Setto il prossimo raster interrupt

lda #<routineIRQ
sta $0314
lda #>routineIRQ
sta $0315
lda #rastline
sta $d012

; Imposto scrolling fine e pagina video:
; farlo in questo secondo interrupt handler
; garantisce di non creare garbage nello schermo
; perche' siamo sul bordo

lda finescroll
sta $d016
lda page
sta $d018

bne iret

; Questa funzione ora copia in un blocco
; unico tutti i byte necessari

scrollCsx
C01 SET 0
REPEAT 1000
lda color+C01+1
sta color+C01
C01 SET C01 + 1
REPEND
rts

; Ho modificato queste 4 funzioni:
; sono tutte e 4 parametriche, dipendono da FRAGMENT.
; FRAGMENT indica in sostanza il numero di cicli
; che deve fare ciascuna funzione.
; Con FRAGMENT alto la copia di impiega di piu' ma la funzione
; occupa meno spazio; con FRAGMENT basso vale il contrario
; i valori possibili per FRAGMENT sono $80,$40 ed $20 (per valori
; piu' bassi bisogna risistemare la bpl perche' diventa
; impossibile tornare all'inizio del ciclo con un branch)
; NB: in effetti, per semplicita', vengono copiati 512 byte
; al posto di 500 in ogni funzione. Su questo c'e' spazio per
; ottimizzare.
; Tieni pero' presente che quando si lavora con l'indirizzamento
; X indexed e' meglio allinearsi alle pagine, il page overflow
; si paga con un ciclo in piu'

FRAGMENT SET $20


scrollSsxU01
ldy #FRAGMENT-1
BASEADU01 SET 0
maincopyloopU01
REPEAT $100/FRAGMENT
lda screen0+BASEADU01+1,y
sta screen1+BASEADU01,y
lda screen0+$100+BASEADU01+1,y
sta screen1+$100+BASEADU01,y
BASEADU01 SET BASEADU01 + FRAGMENT
REPEND
dey
bpl maincopyloopU01
rts


scrollSsxD01
ldy #FRAGMENT-1
BASEADD01 SET 0
maincopyloopD01
REPEAT $100/FRAGMENT
lda screen0+$200+BASEADD01+1,y
sta screen1+$200+BASEADD01,y
lda screen0+$300+BASEADD01+1,y
sta screen1+$300+BASEADD01,y
BASEADD01 SET BASEADD01 + FRAGMENT
REPEND
dey
bpl maincopyloopD01
rts


scrollSsxU10
ldy #FRAGMENT-1
BASEADU10 SET 0
maincopyloopU10
REPEAT $100/FRAGMENT
lda screen1+BASEADU10+1,y
sta screen0+BASEADU10,y
lda screen1+$100+BASEADU10+1,y
sta screen0+$100+BASEADU10,y
BASEADU10 SET BASEADU10 + FRAGMENT
REPEND
dey
bpl maincopyloopU10
rts


scrollSsxD10
ldy #FRAGMENT-1
BASEADD10 SET 0
maincopyloopD10
REPEAT $100/FRAGMENT
lda screen1+$200+BASEADD10+1,y
sta screen0+$200+BASEADD10,y
lda screen1+$300+BASEADD10+1,y
sta screen0+$300+BASEADD10,y
BASEADD10 SET BASEADD10 + FRAGMENT
REPEND
dey
bpl maincopyloopD10
rts


colormap20X25
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c
dc.b $01,$01,$02,$02,$03,$03,$04,$04,$05,$05,$06,$06,$07,$07,$08,$08,$09,$09,$0a,$0a,$0b,$0b,$0c,$0c,$0d,$0d,$0e,$0e,$0f,$0f,$0a,$0a,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #4 il: 22 Aprile 2010, 11:27:53 »
 Interessante la parametrizzazione velocità/ram delle funzioni di copia della ram!
Mi piace molto anche la scelta di spostare ad un secondo interrupt (sul bordo inferiore) delle modifiche dei registri per evitare flickering!
Cosa accade se la routine al primo interrupt impiega troppo tempo? Lo scroll scatterà al frame successivo oppure si va in crash?

ps Mi sembra che la routine di copia della memoria video perda qualcosa nella parte bassa dello schermo....

 

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Scrolling Orizzontale
« Risposta #5 il: 22 Aprile 2010, 12:25:21 »
 Ti rispondo per punti:
- L'importante é che il primo interrupt (quello più oneroso in termini di CPU) non impieghi più di un frame intero: anche se sfora nel bordo superiore del frame successivo non cambia nulla perché tanto il display dei caratteri del nuovo frame deve ancora partire. Il secondo interrupt viene chiamato a prescindere dal primo, quindi anche nel caso che il primo sia ancora in esecuzione, il secondo risulta nidificato nel primo.
- Quello che ho fatto io é copiare il byte successivo nel byte corrente: per avere uno scroller vero e proprio dovresti avere una mappa da cui prendere i valori da assegnare all'ultima colonna del video in maniera tale da fornire dati nuovi. In questo momento, infatti, quando un byte sparisce a sinistra, riappare a destra nella riga precedente, fino a scomparire definitivamente nell'angolo in alto a sinistra.
 

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #6 il: 22 Aprile 2010, 15:59:13 »
 Grazie della precisazione!

Per quanto riguarda la creazione e l'utilizzo di una mappa pensavo di utilizzare alcuni tools (win32) trovati su Covert BitOps ma sinceramente non ho ben capito in che formato vengono salvati i dati e come "trattarli" in 6502

Senbei

  • Neo-iscritto
  • *
  • Post: 22
    • http://www.fabioapps.com
  • Gioco Preferito: Starquake
Scrolling Orizzontale
« Risposta #7 il: 03 Maggio 2010, 14:46:13 »
 Aggiungo la mia tecnica per ottimizzare i tempi, premettendo che non ho analizzato a fondissimo il codice dei post precedenti, per cui se è già quello che fate scusate la ripetizione.

La mia tecnica serve per distribuire il lavoro in modo che ad ogni aggiornamento ci sia più o meno la stessa mole di lavoro.


Utilizzando due buffer io divido il lavoro dello spostamento dello schermo di un intero carattere a dx o sx in 8 routines. Ad ogni vertical blanking aggiorno solo 1/8 del buffer nascosto e sposto di 1 pixel coi registri del VIC. Ogni otto volte scambio i buffer.

Alternativamente, per tenere in considerazione anche lo spostamento della color RAM, che deve per forza essere fatta tutta assieme, si divide il lavoro in 7 parti in modo che al momento dello swap dei buffers ci sia solo la copia della color RAM da fare...

 

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #8 il: 10 Maggio 2010, 11:17:59 »
 Immagino che lo scrolling realizzato in questo modo deve per forza terminare tutto un char prima di poter invertire la direzione ed avere una velocità di 1px/frame...
Corretto?

Cosa usi per realizzare mappe,tiles,charset?
 

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Scrolling Orizzontale
« Risposta #9 il: 11 Maggio 2010, 02:44:46 »
 Ho provato per curiosità a lavorare sull'idea di senbei; trovo sia piuttosto efficiente. Posto qua sotto il codice di inizio thread rimaneggiato con la suddivisione del carico in 8 frame, come puoi notare il carico in effetti rimane sostanzialmente costante. Una volta fatta la direzione destra e' stato semplicissimo fare la sinistra.
Non ho aggiunto la copia della color RAM, ma basta mettere un paio di cicli completamente (o parzialmente) srotolati in corrispondenza dei cambi pagina.
Son comunque daccordo con senbei che, per fare un lavoro fatto bene, bisognerebbe dividere la copia della char RAM in 7 frame e lasciare l'ultimo per la color: il fatto é che dividere per 7 la copia di 1024 bytes é un po' scomodo.

Posto il codice:

Codice: [Seleziona]
processor 6502

; Costanti
rastline = $B0;
finescrline = $FA;
screenD = $0400;
screen0 = $3800+$8000;
screen1 = $3C00+$8000;
color = $d800

; Variabili zero page
temp = $FF
joy2 = $FE
cscr = $FD
finescroll = $FC
page = $FB

org $0801

word eop
word 7102
byte $9e,"2061",0
eop word 0

org $080D;Inizio del programma

main
sei

;Imposto color MAP
ldx #$00
lpCmpC
txa
sta screen0,x
sta screen0+$100,x
sta screen0+$200,x
sta screen0+$300,x
sta screen1+$001,x
sta screen1+$101,x
sta screen1+$201,x
sta screen1+$301,x
inx
bne lpCmpC
lda #$ff
sta screen1

lda #$36;Libero A000-BFFF dalla BASIC ROM RAM (Freshness79)
sta $01

lda #$15;Seleziono banco 2 ($8000-$BFFF 00010101)
sta $dd00

lda #$C7;Posizione di scrolling iniziale e scrolling HW nel punto piu' a destra
sta $D016
sta finescroll

lda #$E4;Attivo schermo 0 (11100100 E4)
sta $d018
sta page

lda #$00;Indicatore dello schermo corrente
sta cscr

jsr initIRQ

cli

jmp *;Loop infinito
rts

initIRQ
lda #<routineIRQ;Indirizzo codice (parte alta)
sta $0314
lda #>routineIRQ;Indirizzo codice (parte bassa)
sta $0315

lda #rastline;Raster line di attivazione IRQ raster
sta $d012
lda #$1b;Azzera il bit 7 che sarebbe il Raster Compare: (Bit 8) di $d012
sta $D011

lda #$7f;01111111 BIT 7 a 0
sta $dc0d;Azzera il bit 7 di CIA Interrupt Control Register (Read IRQs/Write Mask) per disattivarlo
sta $dd0d;Azzera il bit 7 di CIA Interrupt Control Register (Read NMls/Write Mask) per disattivarlo
lda $dc0d;Non so a che derve !?!
lda $dd0d;Non so a che derve !?!

lda #$01;Abilita IRQ raster
sta $d019;VIC Interrupt Flag Register (Bit = 1: IRQ Occurred)
sta $d01a;IRQ Mask Register: 1 = Interrupt Enabled
rts

routineIRQ
inc $d019;Dico al vic che la routine è sata eseguita

;Colora una raster line per capire quanto raster consumo per scrollare
inc $d020;riga 1

; ************
; **MODIFICA**
; ************
; Imposto il prossimo raster IRQ

lda #<secondirq
sta $0314
lda #>secondirq
sta $0315
lda #finescrline
sta $d012

; Leggo joy porta 2
lda $DC00
eor #%00001100; si lavora meglio in logica positiva.
and #%00001100; Seleziono le sole direzioni sx e dx
cmp #%00000100; spostamento a sinistra?
bne nextchk ; no
jmp sx  ; si, sposta a sinistra
nextchk
cmp #%00001000; spostamento a destra?
beq dx  ; si, sposta a destra
jmp lpExit ; nessun spostamento

dx
ldx $d016 ; leggo il finetune corrente
txa   ; lo salvo in X
and #$07 ; quindi lo maschero per recuperare i 3 bit utili
tay   ; e lo salvo in Y, questa e' la posizione corrente.
dex   ; Aggiorno X per ottenere il nuovo valore
txa   ; di scrolling fine
and #$07 ; dopo averlo opportunamente mascherato
ora #$C0 ; e "or-ato" lo salvo
sta finescroll; nella variabile che verra' poi usata nel secondo interrupt
lda cscr ; Che frame buffer
bne dx10 ; stiamo visualizzando?
dx01   ; il 1° quindi devo lavorare sul 2°
tya    ; uso il valore in Y precedentemente salvato per
lsr    ; calcolare l'high-byte dell'indirizzo dei due
ora #(screen0/$100); frame buffer. Ogni 2 pixel (lsr) salto da una pagina
sta dxfrom+2 ; a quella successiva. In 8 pixel passo progressivamente
eor #(screen0/$100); da $000, $100, $200 e $300 ("or-ati" alle rispettive
ora #(screen1/$100); basi dei due framebuffer).
sta dxto+2  ; Importante: il carry viene mantenuto per una successiva
bne dxcont  ; elaborazione
dx10   ; il 2° quindi devo lavorare sul 1°
tya    ; Stessa storia dell'altra opzione
lsr    ; solo con i buffer invertiti
ora #(screen1/$100)
sta dxfrom+2
eor #(screen1/$100)
ora #(screen0/$100)
sta dxto+2
dxcont
ror   ; uso il carry per avere il valore $00 o $80
and #$80 ; in questo modo ho la totale distribuzione del carico
sta dxto+1 ; negli 8 spostamenti: $000,$080,$100,$180,$200,$280,$300 e $380
clc   ; la sorgente (FROM) e' un carattere piu' a destra
adc #$01 ; rispetto alla destinazione per avere l'effettivo
sta dxfrom+1; spostamento.
ldx #$7f ; copio i dati con un ciclo (qua si potrebbe srotolare tutto e ottimizzare)
dxfrom
lda $ffff,x ; Indirizzo calcolato nei passaggi precedenti
dxto
sta $ffff,x ; IDEM
dex
bpl dxfrom

cpy #$00 ; Abbiamo saltato un intero carattere?
bne dxExit  ; No, possiamo uscire
lda cscr  ; si, aggiorniamo l'unico carattere che i vari cicli non hanno
bne dxlastcopy ; potuto sistemare ovvero l'ultimo in basso a destra
lda screen0  ; (che in realta' non si vede perche' lo schermo finisce a $3E8
sta screen1+$3FF; ma dopo un po' a forza di scrollare torna visibile)
bne dxexchange ; Ovviamente a modifica si fa in base al frame buffer attivo
dxlastcopy
lda screen1
sta screen0+$3FF
dxexchange
lda cscr ; Cambio di framebuffer
eor #$01
sta cscr
lda page ; Cambio di pagina video
eor #$10
sta page
dxExit
jmp lpExit  

; Gestione movimento a sinistra
; Sono indicate solamente le modifiche
; rispetto alla routine di destra
; il resto e' identico

sx
ldx $d016
txa
and #$07
tay
inx; ******* D016 viene incrementato
txa
and #$07
ora #$C0
sta finescroll
lda cscr
bne sx10
sx01
tya
lsr
ora #(screen0/$100)
sta sxfrom+2
eor #(screen0/$100)
ora #(screen1/$100)
sta sxto+2
bne sxcont
sx10
tya
lsr
ora #(screen1/$100)
sta sxfrom+2
eor #(screen1/$100)
ora #(screen0/$100)
sta sxto+2
sxcont
ror
and #$80
sta sxfrom+1; il FROM (sorgente) e' un carattere a sinistra
clc
adc #$01
sta sxto+1 ; rispetto al TO (destinazione)
ldx #$7f
sxfrom
lda $ffff,x
sxto
sta $ffff,x
dex
bpl sxfrom
cpy #$07 ; Se qua Y=7 significa che $D016=$C0 quindi bisogna cambiare page
bne lpExit
lda cscr
bne sxlastcopy
lda screen0+$3FF; copio l'ultimo byte del primo buffer
sta screen1  ; nel primo byte del secondo buffer
bne sxexchange
sxlastcopy
lda screen1+$3FF; copio l'ultimo byte del secondo buffer
sta screen0  ; nel primo byte del primo buffer
sxexchange  
lda cscr
eor #$01
sta cscr
lda page
eor #$10
sta page

lpExit

dec $d020

iret
pla;Pull Accumulator from Stack
tay;transfer A to Y
pla;Pull Accumulator from Stack
tax;transfer A to X
pla;Pull Accumulator from Stack
rti; return from interrupt

; ************
; **MODIFICA**
; ************
; (Da qua in poi e' tutto modificato a parte la mappa)
; IRQ di aggiornamento registri VIC

secondirq
; IRQ Acknowledge

lsr $d019

; Setto il prossimo raster interrupt

lda #<routineIRQ
sta $0314
lda #>routineIRQ
sta $0315
lda #rastline
sta $d012

; Imposto scrolling fine e pagina video:
; farlo in questo secondo interrupt handler
; garantisce di non creare garbage nello schermo
; perche' siamo sul bordo

lda finescroll
sta $d016
lda page
sta $d018
bne iret

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #10 il: 11 Maggio 2010, 14:56:21 »
 Ipotizzando l'utilizzo di tale tecnica con una mappa sarebbe necessario completare la sequenza di 7/8 scroll hw prima di poter invertire la direzione altrimenti ti troveresti con una parte di schermo contenente i dati scrollati a dx ed un'altra parte scrollati a sx.
E' corretto oppure mi sono perso qualcosa?

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Scrolling Orizzontale
« Risposta #11 il: 11 Maggio 2010, 16:15:35 »
L'inversione di direzione può avvenire in qualsiasi momento perché quando si arriva al cambio carattere lo schermo é sempre pronto.
La cosa funziona in questo modo: se ad esempio sono al 2° pixel ho 2 blocchi da 128 pronti per lo spostamento a sinistra e 6 blocchi da 128 pronti per quello a sinistra, spostandosi a destra o a sinistra aumentano in una o nell'altra direzione.
L'aggiornamento prendendo i valori da una mappa può avvenire usando sempre la colonna di caratteri che rimane normalmente coperto dal restringimento dell'area dello schermo.
In allegato la versione comprensiva dello spostamento della color map; non dovrebbe essere troppo difficile inserire il codice per gestire una mappa.
Appena ho un attimo cerco di buttar giù qualcosa.
« Ultima modifica: 22 Gennaio 2015, 00:15:57 da eregil »

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #12 il: 12 Maggio 2010, 12:47:36 »
 Me lo studio x benino!!

Scusa l'ignoranza ma ti posso chiedere la funzione di:
Codice: [Seleziona]
align $100prima dei dati della mappa di colore?
Ho letto che la direttiva ALIGN serve ad allineare il PC a N byte ma mi sfugge il perchè l'hai utilizzata....

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Scrolling Orizzontale
« Risposta #13 il: 12 Maggio 2010, 13:47:29 »
 In realtà quell'align non é strettamente necessario; in linea di massima lo metto sempre quando ho tabelle di grosse dimensioni perché quando si va ad utilizzare l'indirizzamento X-indexed si ha un ciclo di penalty per il page crossing.
Mi spiego meglio.
Supponi di avere una tabella di 256 valori che parte da $4380 e finisce a $447F, se ho bisogno di leggere utilizzando LDA $4380,X e scorrendo i vari valori, di fatto mi ritrovo che per X<$7F mi costa 4 cicli, per X>=$80 me ne costa 5 perché c'é il cambio di pagina (da $4300 a $4400). Supponendo di fare un ciclo che legge tutti i 256 valori ho un sovraccarico di 128 cicli che potevo facilmente evitare allineando la tabella.
Nel caso specifico i valori vengono copiati in realtà una volta sola quindi l'align non serve a molto, resta il fatto che facendo così l'intera tabella occupa 4 pagine invece di 5 e la copia (ok, l'unica copia) risulta in ogni caso più rapida.
LDA $aaaa,x e STA $aaaa,x danno il loro meglio quando lavorano in una pagina, quando cioé sono del tipo LDA $aa00,x e STA $aa00,x.

antoniomauro

  • Utente
  • **
  • Post: 91
  • Gioco Preferito: IK+
Scrolling Orizzontale
« Risposta #14 il: 12 Maggio 2010, 17:04:20 »
 Conoscevo il dazio da pagare in caso di cross-paging ma non mi è ancora chiaro come hai calcolato il valore  $100....
E' come dire al compilatore di spostare il PC $100 byte più avanti rispetto alla posizione corrente prima di memorizzare la tabella?