Autore Topic: Dma Delay  (Letto 2971 volte)

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Dma Delay
« il: 28 Aprile 2009, 01:14:42 »
Se ne parlava l'altro giorno in chat e visto che non avevo mai provato a ricreare questo effetto, stasera ho provato a scrivere un paio di righe.
L'effetto DMA delay, per chi non ne fosse al corrente, si basa sulla creazione "artificiosa" di una bad line durante la visualizzazione di una linea.
A seconda del momento in cui si crea la badline, il counter interno del VIC sarà soggetto ad un diverso offset: questo 'difetto' nell'allineamento, unito all'uso dello scrolling fine $D016,  permette maggiore libertà nel movimento orizzontale di tutto lo schermo. Nel semplice esempio che propongo in effetti nessun carattere viene cambiato o spostato nella mappa dello schermo: tutto il movimento é creato con i registri del VIC.
Segue come sempre il source:

Codice: [Seleziona]
NOPopcode = $EA
temp  = $FE
setDEN  = $FA
rastline = $FB
sinuspos = $FD

         
  *=$0801
        word eoprg
        word 2009
        byte $9E,[intro]d
        petc ":rem dma delay"
        byte 0
eoprg
        word 0
        *=$0840

intro   
  lda #$10  ; Attivazione schermo (D011 - bit DEN)
  sta setDEN
  lda #$2e  ; Linea $30 (-2 per la stabilizzazione)
  sta rastline
  lda #$00  ; Resetta la posizione della sinus table
  sta sinuspos 
  jsr initIRQ  ; Inizializzazione raster IRQ
  cli    ; Interrupt attivati
  rts     
 
 
; ***************************************************
; * Routine di sincronizzazione a doppio raster IRQ *
; ***************************************************
; La prima chiamata IRQ é su JMP, quindi l'incertezza é 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  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 perché punti
  sta $0314  ; 4 al secondo handler 
  cli    ; 2 attivo gli interrupt
  tsx    ; 2
  stx temp  ; 3
  nop    ; 2 (63-65) <= IRQ
  nop    ; 2 (65-67) <= IRQ
  brk    ; Qua non ci si arriva mai, lascio BRK per test
secirq ldx sinuspos ; 3 + (36 Kernal IRQ) + (da 2 a 3 NOP) 
  lda sinushigh,x ; 4   Carico la parte più significativa dello spostamento
  lsr    ; 2   orizzontale, nel carry metto il bit meno significativo
  sta brnch+1  ; 4   uso il resto per creare un displacement
  lda $d012  ; 4   Stabilizzazione raster
  nop    ; 2w
  nop    ; 2w
  bit $d012  ; 4   se il ritardo dovuto alla NOP era 1   
  beq synced  ; 2/3 effettuo un branch per allinearmi
      ; Routine di delay della prima badline
synced bcc brnch  ; questo branch serve per saltare un ciclo
brnch bpl *  ; con questo si saltano 2*N  cicli
  ds  $13,NOPopcode; (0-38 cicli) 19xNOP (la nop impiega 2 cicli)
  lda setDEN  ;
  sta $d011  ; Attivazione badline
  inc sinuspos ; incrementa il pointer e setta 06 il colore del garbage (INC = $E6)
  lda sinuslow,x ; Parte meno significativa dello spostamento
  sta $d016  ; orizzontale - scrolling fine
  lda #$00  ; reset
  sta $d011  ; del bit DEN nel registro $D011
  lda rastline
  sta $d012  ; ripristino del corretto raster compare
  ldx #<fstirq       
  stx $0314  ; ripristino il vecchio IRQ pointer
  ldx temp  ;
  txs    ; ripristino dello stack pointer 
  lsr $d019  ; Acknowledge del raster IRQ
  cli    ; Interrupt nuovamente attivi
  jmp $ea31  ; Salto alla normale routine di interruzione



; ************
; * 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 $dd0c
  lda $dc0c
  lda #$10
  sta $d011
  lda $fb
  sta $d012
  lda #<fstirq
  sta $0314
  lda #>fstirq
  sta $0315
  lda #$01
  sta $d01a
  lsr $d019
  rts

 
*=$0b00

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
« Ultima modifica: 21 Gennaio 2015, 23:47:46 da eregil »

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Dma Delay
« Risposta #1 il: 28 Aprile 2009, 01:19:49 »
 Non funziona nulla ne' in vice 2.19 ne' in hoxs. Schermo spento e null'altro.
Hai per caso provato su C64 e ti funziona? se si, siamo di fronte ad un altro baco di emulazione :)
Edit: funziona solo in vice 2.1, come abbiamo verificato in chat. Essendo stato corretto un baco di emulazione dalla 2.1.5, si puo' solo dedurre che cosi' com'e' questa routine si basa su un'assunzione errata.
Andrebbe provato su c64 reale prima di stabilire dove stia l'errore.
-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Dma Delay
« Risposta #2 il: 28 Aprile 2009, 02:00:39 »
Ok, in effetti il codice andava corretto: ora dovrebbe andare meglio.

Codice: [Seleziona]
NOPopcode = $EA
temp  = $FE
setDEN  = $FA
rastline = $FB
sinuspos = $FD

         
  *=$0801
        word eoprg
        word 2009
        byte $9E,[intro]d
        petc ":rem dma delay"
        byte 0
eoprg
        word 0
        *=$0840

intro   
  lda #$18  ; Attivazione schermo (D011 - bit DEN)
  sta setDEN
  lda #$2e  ; Linea $30 (-2 per la stabilizzazione)
  sta rastline
  lda #$00  ; Resetta la posizione della sinus table
  sta sinuspos 
  jsr initIRQ  ; Inizializzazione raster IRQ
  cli    ; Interrupt attivati
  rts     
 
 
; ***************************************************
; * Routine di sincronizzazione a doppio raster IRQ *
; ***************************************************
; La prima chiamata IRQ é su JMP, quindi l'incertezza é 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  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 perché 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 ldx sinuspos ; 3 + (36 Kernal IRQ) + (da 2 a 3 NOP) 
  lda sinushigh,x ; 4   Carico la parte più significativa dello spostamento
  lsr    ; 2   orizzontale, nel carry metto il bit meno significativo
  sta brnch+1  ; 4   uso il resto per creare un displacement
  lda $d012  ; 4   Stabilizzazione raster
  nop    ; 2w
  nop    ; 2w 
  bit $d012  ; 4   se il ritardo dovuto alla NOP era 1   
  beq synced  ; 2/3 effettuo un branch per allinearmi
      ; Routine di delay della prima badline
synced bcc brnch  ; questo branch serve per saltare un ciclo
brnch bpl *  ; con questo si saltano 2*N  cicli
  ds  $13,NOPopcode; (0-38 cicli) 19xNOP (la nop impiega 2 cicli)
  lda setDEN  ;
  sta $d011  ; Attivazione badline 
  inc sinuspos ; incrementa il pointer e setta 06 il colore del garbage (INC = $E6)
  lda sinuslow,x ; Parte meno significativa dello spostamento
  sta $d016  ; orizzontale - scrolling fine
  lda rastline
  sta $d012  ; ripristino del corretto raster compare
  ldx #<fstirq       
  stx $0314  ; ripristino il vecchio IRQ pointer
  tsx
  txa
  clc
  adc #$06
  tax
  txs    ; ripristino dello stack pointer 
  lsr $d019  ; Acknowledge del raster IRQ
  cli    ; Interrupt nuovamente attivi
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff
  inc $ffff 
  lda #$00  ; reset 
  sta $d011  ; del bit DEN nel registro $D011 
  jmp $ea31  ; Salto alla normale routine di interruzione



; ************
; * 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 $dd0c
  lda $dc0c
  lda #$00
  sta $d011
  lda $fb
  sta $d012
  lda #<fstirq
  sta $0314
  lda #>fstirq
  sta $0315
  lda #$01
  sta $d01a
;  lsr $d019
  rts

 
*=$0b00

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
« Ultima modifica: 21 Gennaio 2015, 23:48:09 da eregil »

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Dma Delay
« Risposta #3 il: 28 Aprile 2009, 11:29:39 »
Non ho potuto fare a meno di applicare un paio di modifiche :D
Come gia' detto a freshness in chat, non riuscivo a capacitarmi del perche' non mi partisse in autorun, l'errore era nella init.
Codice: [Seleziona]
; v2.1 revisione di iAN CooG
;
;- sysline che non causa ?SYNTAX  ERROR
;- ciclo all'uscita della fstirq anziche' inc $ffff ripetuti
;- corretta initIRQ, ora parte in ogni emulatore, sempre.
;- ridotta occupazione in memoria. ok, non era necessario :)

NOPopcode = $EA
temp      = $FE
setDEN    = $FA
rastline  = $FB
sinuspos  = $FD


  *=$0801
  word eoprg
  word 2009
  byte $9E,[intro]d,":",$8f,$0d,"FRESHNESS79(CODE) + IAN COOG(FIX)"
  byte 0
eoprg
  word 0

intro
  lda #$18        ; Attivazione schermo (D011 - bit DEN)
  sta setDEN
  lda #$2e        ; Linea $30 (-2 per la stabilizzazione)
  sta rastline
  lda #$00        ; Resetta la posizione della sinus table
  sta sinuspos
  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
  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
  ldx sinuspos    ; 3 + (36 Kernal IRQ) + (da 2 a 3 NOP)
  lda sinushigh,x  ; 4   Carico la parte piu' significativa dello spostamento
  lsr              ; 2   orizzontale, nel carry metto il bit meno significativo
  sta brnch+1      ; 4   uso il resto per creare un displacement
  lda $d012        ; 4   Stabilizzazione raster
  nop              ; 2w
  nop              ; 2w
  bit $d012        ; 4   se il ritardo dovuto alla NOP era 1
  beq synced      ; 2/3 effettuo un branch per allinearmi

; Routine di delay della prima badline
synced
  bcc brnch        ; questo branch serve per saltare un ciclo
brnch
  bpl *            ; con questo si saltano 2*N  cicli

  ds  $13,NOPopcode; (0-38 cicli) 19xNOP (la nop impiega 2 cicli)

  lda setDEN
  sta $d011        ; Attivazione badline
  inc sinuspos    ; incrementa il pointer e setta 06 il colore del garbage (INC = $E6)
  lda sinuslow,x  ; Parte meno significativa dello spostamento
  sta $d016        ; orizzontale - scrolling fine
  lda rastline
  sta $d012        ; ripristino del corretto raster compare
  ldx #<fstirq
  stx $0314        ; ripristino il vecchio IRQ pointer
  tsx
  txa
  clc
  adc #$06
  tax
  txs              ; ripristino dello stack pointer
  lsr $d019        ; Acknowledge del raster IRQ
;cli            ; Interrupt nuovamente attivi << ha senso durante l'IRQ?

;qua possiamo ciclare, CREDO siano sufficienti, aggiustare alla bisogna;D
  ldx #$0d
dexdel
  inc $ffff
  dex
  bne dexdel

  lda #$00        ; reset
  sta $d011        ; del bit DEN nel registro $D011
  jmp $ea31        ; Salto alla normale routine di interruzione



; ************
; * 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 !
  lda $dd0d;non dd0c !
  lda #$00
  sta $d011
  lda $fb
  sta $d012
  lda #<fstirq
  sta $0314
  lda #>fstirq
  sta $0315
  lda #$01
  sta $d01a
; Meglio settare SEMPRE d019 per pulire ogni irq pendente, come le lda $dc0d.
; A me ad esempio in Vice 2.1.9 non parte MAI in autostart senza questa :)
  sta $d019
  rts

  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

Interessante il fatto che il colore del pattern in alto a sinistra (visibile se si cambia il colore di sfondo $d021 ad esempio in nero) sia dovuto all'opcode fetchato dopo la sta $d011, non sapevo di questa cosa =)
« Ultima modifica: 21 Gennaio 2015, 23:48:36 da eregil »
-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Dma Delay
« Risposta #4 il: 28 Aprile 2009, 13:16:04 »
Grazie dei fix, effettivamente ora il codice é più pulito.
Per quanto riguarda il colore del garbage (e anche il carattere), riporto la parte riguardante il DMA delay tratta dal documento redatto da Christian Bauer - VIC-II Article
Ho evidenziato le parti salienti riguardanti il difetto: sostanzialmente é la stessa cosa che succede quando si creano dei FLI.

Citazione
...

3.14.6. DMA delay
-----------------

The most sophisticated Bad Line manipulation is to create a Bad Line
Condition within cycles 15-53 of a raster line in the display window in
which the graphics data sequencer is in idle state, e.g. by modifying
register $d011 so that YSCROLL is equal to the lower three bits of RASTER.

The VIC will then set BA to low immediately in the next cycle, switch to
display state and start reading from the video matrix (the processor is now
stopped because BA is low and it wants to read the next opcode). However,
AEC still follows ø2 for three cycles before also staying at low state.
This behavior (AEC not until three cycles after BA) is hardwired in the VIC
and cannot be avoided.

Nevertheless, the VIC accesses the video matrix, or at least it tries,
because as long as AEC is still high in the second clock phase, the address
and data bus drivers D0-D7 of the VIC are in tri-state and the VIC reads
the value $ff from D0-D7 instead of the data from the video matrix in the
first three cycles. The data lines D8-D13 of the VIC however don't have
tri-state drivers and are always set to input. But the VIC doesn't get
valid Color RAM data from there either, because as AEC is high, the 6510 is
still considered the bus master and unless it doesn't by chance want to
read the next opcode from the Color RAM, the chip select input of the Color
RAM is not active. Instead, a 4 bit analog (!) switch, U16, connects the
data bits D0-D3 of the processor with the data bits D8-D13. This connection
is always in place when AEC is high and should allow the processor to
access the Color RAM if desired.
To make a long story short: In the first
three cycles after BA went low, the VIC reads $ff as character pointers and
as color information the lower 4 bits of the opcode after the access to
$d011.
Not until then, regular video matrix data is read.

...
« Ultima modifica: 21 Gennaio 2015, 23:51:32 da eregil »

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
Dma Delay
« Risposta #5 il: 28 Aprile 2009, 21:24:13 »
 Ah il Vic Article. Non sono mai riuscito a leggerlo interamente, dopo un po' mi va insieme la vista  :lol:  
-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -

SevenLegion

  • Neo-iscritto
  • *
  • Post: 49
  • Gioco Preferito: wizard of wor
Dma Delay
« Risposta #6 il: 13 Maggio 2009, 09:28:10 »
 Domanda: perche' l'effetto viene chiamato proprio "DMA delay"?
Cioe', la parola "DMA" viene dal nome di un coder che per primo l'ha scoperto oppure il trucco ha effettivamente a che fare con una operazione di DMA nella memoria?

ice00

  • Utente
  • **
  • Post: 469
    • http://digilander.iol.it/ice00
Dma Delay
« Risposta #7 il: 13 Maggio 2009, 20:38:51 »
 In  informatica DMA è l'acronimo per  Direct Memory Access: l'accesso diretto alla memoria da parte di un dispositivo senza passare per una lettura tramite il processore. In questo contesto dovrebbe riferirsi al fatto che viene ritardato l'accesso da parte del chip grafico alla memoria video che avviene nella bad line.

SevenLegion

  • Neo-iscritto
  • *
  • Post: 49
  • Gioco Preferito: wizard of wor
Dma Delay
« Risposta #8 il: 15 Maggio 2009, 18:12:40 »
 ...quindi qui , con DMA si intende la lettura della RAM da parte della circuiteria incaricata di generare l'immagine video.

Domanda: qualcuno sa dirmi se normalmente nel C64 il VICII provoca degli stalli al processore 6510, nel caso i due cerchino di accedere alla stessa area di memoria?

Ad esempio, il circuito grafico dello Spectrum (ULA) blocca sistematicamente il clock dello Z80 se c'e' un conflitto d'accesso nel banco RAM sotto i 32K (area video). Nell'Amiga, invece, usavano una  tecnica di accesso a cicli alternati che evitava i conflitti...

ice00

  • Utente
  • **
  • Post: 469
    • http://digilander.iol.it/ice00
Dma Delay
« Risposta #9 il: 15 Maggio 2009, 23:40:47 »
 L'accesso alla memoria da parte del processore è bloccata (BA request) quando il VIC accede alla memoria video. Peranto a ogni bad line, il processore ha meno cicli a disposizione (dato che ogni istruzione del 6510 accede alla memoria)

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Dma Delay
« Risposta #10 il: 16 Maggio 2009, 19:56:19 »
 Aggiungo qualche dettaglio a quanto già detto da ice.
In realtà il VIC accede alla memoria costantemente, manda in stallo il 6510 solo in determinate condizioni (bad line, sprites).

La suddivisione dell'accesso alla memoria é basata sul segnale AEC che normalmente é identico al segnale PHI2 (Il clock principale da circa 1Mhz).
In sostanza, tenendo in mente che il PHI2 é un'onda quadra, durante la prima fase di PHI2 (quando PHI2 ed AEC sono low) la memoria é acceduta dal VIC, nell'altra fase (PHI2 e AEC high) é acceduta dal processore.
Gli accessi del VIC in questo caso sono di 4 tipi:
- 5 refresh della memoria
- lettura degli 8 sprite pointers
- lettura di 40 byte di memoria grafica o di font (solo nella zona interna ai bordi)
- idle (quando non fa nessuna delle prime 3, tipicamente "sotto" ai bordi, viene comunque letto un byte dall'ultima locazione della memoria video).
Queste 4 operazioni avvengono di fatto a costo 0 per il 6510.

I casi nei quali il VIC richiede esplicitamente uno stallo del 6510 sono invece essenzialmente due:
- lettura dei dati grafici di 1 o più sprite (2 cicli per sprite)
  Avviene quando uno o più sprite sono attivi in una determinata linea
- lettura del colore (bitmap mode) o del codice carattere (textmode) (La cosiddetta badline che richiede 40 cicli)
  Avviene (normalmente) ogni 8 linee per generare una nuova serie di colori (bitmap mode) oppure una nuova serie di caratteri (textmode).

Per ottenere ciò, 3 cicli prima di quando ne ha necessità il VIC porta a low il segnale BA e dopo (massimo) 3 cicli di clock il processore va in stallo: passati i 3 cicli diventa low anche il segnale AEC ed il VIC ottiene il controllo della memoria in entrambe le fasi di phi2.
Durante i 3 cicli intermedi allo stallo (Con BA low) il processore può solamente effettuare scritture, la prima lettura effettuata lo manda subito in stallo.

Di fatto quindi, quando si realizzano effetti come ad esempio i FLI, il processore viene mandato in stallo per diverse centinaia di cicli in ogni frame.

SevenLegion

  • Neo-iscritto
  • *
  • Post: 49
  • Gioco Preferito: wizard of wor
Dma Delay
« Risposta #11 il: 19 Maggio 2009, 23:00:04 »
 interessante... quindi possiamo dire che nell' architettura del C64 si sono posti il problema di contenere gli stalli entro il possibile, almeno nelle operazioni piu' comuni.

Mi viene da considerare che che la tecnologia del processore 6502, lavorante a basso numero di Mhz, avrebbe il vantaggio di  consentire accessi in coesistenza col VIC, dato che le RAM dell'epoca erano circa cloccabili a 4 Mhz, quindi con un buon margine di banda residua...

Immagino anche che sia unicamente il VIC ad arbitrare l'uso del bus, quindi gli stalli della CPU accadono solo quando si va a  lavorare dentro al suo banco da 16K, giusto?

Freshness79

  • Utente
  • **
  • Post: 128
  • Gioco Preferito: Dizzy collection
Dma Delay
« Risposta #12 il: 20 Maggio 2009, 00:15:18 »
 Dunque... supponendo di lavorare in condizioni normali, cioé senza tirare per il collo il VIC con i vari trick hardware che sono stati scoperti, e con 8 sprite attivi - senza alcun multiplexing - il conto dei cicli CPU persi è più o meno questo:

Sprite: 8*21*2 (8 sprite, 21 linee per ogni sprite, 2 cicli cpu persi)  

Foreground: 25*40 (25 linee per 40 cicli cpu persi)

(336+1000)*50 (50 frame per secondo) = 66800 cicli/sec

Tenendo presente che all'appello mancano in realtà altri cicli persi a causa del meccanismo di stallo (BA e dopo tre cicli AEC) direi che possiamo approssimare più o meno al 7/8% di un Mhz che comunque a mio avviso non é poco.
Nel caso del 64 in effetti la memoria viene acceduta 2 volte per ciclo di clock, pertanto con una frequenza di 2Mhz, bisogna ammettere che almeno da questo punto di vista l'architettura é stata disegnata in modo efficiente.

Quanto alla tua seconda domanda: si e no.
Si, é il VIC ad arbitrare il bus tramite il pin AEC.
No, non c'è alcun stallo legato ad un accesso alla stessa area di memoria: VIC e CPU non possono fare accessi contemporanei.
In base al valore di AEC vanno in tri-state le linee di indirizzamento della CPU oppure del VIC: pertanto in ogni istante a prescindere dall'indirizzo scelto solo uno dei due può leggere o scrivere in memoria.
In effetti nel precedente post forse mi sono spiegato male. Quando dicevo che il VIC accede costantemente alla memoria, intendevo dire in effetti che ci accede in ogni ciclo di clock: questo perché la prima fase del ciclo corrisponde sempre ad un accesso del VIC; nella seconda fase del ciclo però, a meno che il VIC non abbia motivi particolari (badline, sprite) per bloccarla, la CPU ha totale controllo sul bus indirizzi, a prescindere dalla locazione alla quale ha bisogno di accedere, il VIC in questo semiciclo ha le sue linee in tri-state.

Speranza

  • Utente
  • **
  • Post: 52
  • Gioco Preferito: 1942
Dma Delay
« Risposta #13 il: 20 Maggio 2009, 18:22:42 »
 Ho capito dove mi trovo!

MATRIX RELOAD   :D

Prima o poi riuscivo a decodificare tutto mmmmmmmmmmmmn   ;)

- cerchiamo di evitare gli OT, specialmente nei thread tecnici. Grazie

mces

  • Utente
  • **
  • Post: 339
  • Gioco Preferito: fort apocalypse
Dma Delay
« Risposta #14 il: 26 Maggio 2009, 10:18:14 »
 credo sia interessante far notare che alcuni programmi hanno necessità di avere una precisa PREDIZIONE dei tempi di esecuzione, come ad es. i programmi che generano/leggono il segnale della cassetta del datassette, e che grazie alla "chiusura" dello schermo, venendo meno le necessità di caricare le informazioni per la grafica dello schermo stesso, vengono eliminati gli accessi "extra" alla memoria che rimane sempre disponibile per il lavoro del 6502 senza introdurre "casuali" ritardi nel flusso esecutivo del SW.
Non esistono problemi, solo soluzioni.