Come posso mostrare sprite al confine sulla C64?
Domanda
Ho visto fresche demo C64 mostrano sprite nella zona di frontiera dello schermo. Non dovrebbe essere possibile; Credo che sono riusciti a ingannare il chip grafico in qualche modo. Esattamente come lo hanno fatto?
Soluzione
Sì, avete bisogno di assembler. E 'un trucco tempi di interruzione. Il VIC è in grado di mostrare sprite nel bordo, ma il telaio è semplicemente nascondendo, così gli sprite possono scorrere dietro di esso. E 'collegato per la scansione di linee visualizzate dal VIC. Per i bordi inferiori / superiori è abbastanza semplice:
- Programm un interrupt, sincronizzati per iniziare ad una certa linea di scansione, 7 pixel o qualcosa di simile prima del bordo inferiore.
- Imposta il registro in VIC per rendere più piccolo il confine. (C'è un registro che può farlo.)
- VIC ora crede che il confine già avviato e non inizia a dipingere.
- -.> Nessun bordo in basso
- Programm un'altra interrompere dopo il confine reale per impostare di nuovo a originale.
Per sprite in / confini di destra di sinistra, è più complicato perché il processo deve essere ripetuto per ogni linea di scansione:
- Programm un interrupt, sincronizzati per iniziare ad una determinata linea di scansione.
- Quindi fare alcune PON finché non si è 7 pixel prima del bordo destro.
- Imposta il registro in VIC per rendere più piccolo il confine.
- -.> Nessun bordo sul lato destro
- Fare qualche PON finché non si è dopo il confine reale e impostare il registro di nuovo al valore originale.
- Anche in questo caso fare alcune PON fino al passaggio 2.
Il problema è che tutti questi PON sono occupato aspetta e rubano i cicli che avete per la vostra roba.
Sono riuscito a trovare un po 'di codice per voi, da uno scroller sprite nel bordo inferiore. Ecco il codice. (E 'stato strappato da qualche demo.)
C198 78 SEI
C199 20 2E C1 JSR C12E # clear sprite area
C19C 20 48 C1 JSR C148 # init VIC
C19F A9 BF LDA #BF # set up IRQ in C1BF
C1A1 A2 C1 LDX #C1
C1A3 8D 14 03 STA 0314
C1A6 8E 15 03 STX 0315
C1A9 A9 1B LDA #1B
C1AB 8D 11 D0 STA D011
C1AE A9 F7 LDA #F7
C1B0 8D 12 D0 STA D012
C1B3 A9 01 LDA #01
C1B5 8D 1A D0 STA D01A
C1B8 A9 7F LDA #7F
C1BA 8D 0D DC STA DC0D
C1BD 58 CLI
C1BE 60 RTS
----------------------------------
# init VIC
C148 A2 00 LDX #00
C14A BD 88 C1 LDA C188,X
C14D 9D 00 D0 STA D000,X # set first 16 values from table
C150 E8 INX
C151 E0 10 CPX #10
C153 D0 F5 BNE C14A
C155 A9 FF LDA #FF
C157 8D 15 D0 STA D015
C15A A9 00 LDA #00
C15C 8D 1C D0 STA D01C
C15F A9 FF LDA #FF
C161 8D 17 D0 STA D017
C164 8D 1D D0 STA D01D
C167 A9 C0 LDA #C0
C169 8D 10 D0 STA D010
C16C A9 F8 LDA #F8
C16E A2 00 LDX #00
C170 9D F8 07 STA 07F8,X
C173 18 CLC
C174 69 01 ADC #01
C176 E8 INX
C177 E0 08 CPX #08
C179 D0 F5 BNE C170
C17B A9 0E LDA #0E
C17D A2 00 LDX #00
C17F 9D 27 D0 STA D027,X
C182 E8 INX
C183 E0 08 CPX #08
C185 D0 F8 BNE C17F
C187 60 RTS
----------------------------------
# data set into VIC registers
C188 00 F7 30 F7 60 F7 90 F7
C190 C0 F7 F0 F7 20 F7 50 F7
----------------------------------
# main IRQ routine
C1BF A2 08 LDX #08
C1C1 CA DEX
C1C2 D0 FD BNE C1C1
C1C4 A2 28 LDX #28 # 40 or so lines
C1C6 EA NOP # "timing"
C1C7 EA NOP
C1C8 EA NOP
C1C9 EA NOP
C1CA CE 16 D0 DEC D016 # fiddle register
C1CD EE 16 D0 INC D016
C1D0 AC 12 D0 LDY D012
C1D3 88 DEY
C1D4 EA NOP
C1D5 98 TYA
C1D6 29 07 AND #07
C1D8 09 18 ORA #18
C1DA 8D 11 D0 STA D011
C1DD 24 EA BIT EA
C1DF EA NOP
C1E0 EA NOP
C1E1 CA DEX
C1E2 10 E4 BPL C1C8 # repeat next line
C1E4 A9 1B LDA #1B
C1E6 8D 11 D0 STA D011
C1E9 A9 01 LDA #01
C1EB 8D 19 D0 STA D019
C1EE 20 00 C0 JSR C000 # call main code
C1F1 4C 31 EA JMP EA31 # finish IRQ
Altri suggerimenti
Tutto si basava sui tempi. La C64 ha un metodo per interrogare la posizione verticale esatta del fascio di elettroni mentre si avvicinava schermo. Quando una nuova linea ha iniziato, si doveva aspettare alcuni cicli (si potrebbe cronometrare questo utilizzando l'istruzione NOP) e poi si doveva impostare un registro hardware del videochip incaricata per l'impostazione del ScreenMode (e la larghezza del bordo). Cronometrando esattamente a destra, e farlo ogni linea di scansione ancora una volta, l'intera sideborder scomparso.
Il bordo inferiore è andato via con un trucco simile. Sulla linea di scansione esatto in cui il confine verticale iniziato troppo si doveva impostare il videomode che disabilitato il bordo inferiore per quel fotogramma.
In realtà tutta questa cosa doveva essere fatto in assemblea. In caso contrario, si potrebbe mai ottenere la tempistica esattamente a destra.
Come nota a margine, penso che il trucco sideborder è stato accreditato al 1001 Crew (un gruppo olandese). Non sono sicuro che ha tirato fuori il primo trucco bordo inferiore.
Per un buon tutorial sul tema di aprire i confini sul C64, Verificate eccellente articolo di Pasi Ojala nel C = Hacking Numero 6 .
Senza entrare troppo tecnico, il trucco usa una caratteristica del VIC chip per lasciare che si passa da 25/24 righe e 40/38 colonne di testo / grafica, e consista nel mettere questo interruttore al esatto momento giusto per ingannare il VIC a pensare che ha già acceso i confini quando in realtà Non ha. Controlla il suddetto articolo per una spiegazione più approfondita con esempi di codice.
Questo è un molto tempo fa.
So che c'era una soluzione che si basava sulla frequenza del monitor.
Con un CRT, il pixel corrente è noto anche se era al di fuori dello schermo normale. Così si potrebbe manipolare il raggio.
Da qualche parte nel mio junkpile ci devono essere alcuni libri C64.
Offtopic, ma la grafica con il VIC20 (il predecessore del C64) era divertente. Non c'era modo di manipolare ogni pixel, ma si potrebbe cambiare i caratteri esistenti. Così si riempiva lo schermo con tutti i caratteri da 0 a ... e cambiato i personaggi per impostare pixel sullo schermo. ; -).
Timing è stata la chiave. L'immagine è stata creata nel bordo cambiando il colore (confine) overscan come il raggio del tubo catodico spostato da sinistra a destra. Ci sono due segnali di temporizzazione necessari per produrre un'immagine - aggiornamento verticale e orizzontale aggiornamento. Rilevando quando si verifica l'aggiornamento orizzontale e verticale è possibile avviare una sequenza di istruzioni assembler per cambiare il colore del bordo per produrre un'immagine. Hai bisogno di lavorare il numero di CPU clock ticks per pixel di confine e l'uso che per creare il codice che cambia il colore del bordo al punto giusto.
Non funziona molto bene quando si tratta di scrivere i giochi come il sovraccarico della CPU è troppo elevato per poter essere in qualsiasi momento ascensore per l'input dell'utente di processo e di stato di gioco.