Programmazione in Assembly Per Commodore 64 E Sua Applicazione Nella Demoscene
Total Page:16
File Type:pdf, Size:1020Kb
ALESSIO COSENZA PROGRAMMAZIONE IN ASSEMBLY PER COMMODORE 64 E SUA APPLICAZIONE NELLA DEMOSCENE INTERVIENE: DIEGO BARZON TESTO PRESENTAZIONI! ▸ Alessio Cosenza ▸ Di giorno sviluppatore servizi web / app ▸ Di notte sviluppatore su piattaforme "old school" ▸ Commodore 64, Vectrex ▸ Power Glove Ultra TESTO PRESENTAZIONI! ▸ Membro del gruppo Commodore 64 "Onslaught" con il nickname Elder0010 ▸ Basati in Australia ma con membri in Europa e America ▸ Attivi dal 1995 ▸ Cracking & Demo Group ▸ "Vandalism News" C64 Disk Magazine ▸ Operativi anche su Amiga e PC. TESTO CENNI DI STORIA ▸ La Demoscene Commodore è considerata l'originaria ▸ Nasce dalla Cracking Scene nei primi 80's ▸ Organizzata in gruppi di persone anonime con nicknames ▸ Scambio di informazione tramite "Snail Mail" ▸ Poca differenza tra crack intro e prime demo TESTO CRACK INTRO? ▸ Piccoli programmi "iniettati" prima dei giochi piratati ▸ Una sola schermata ▸ Elementi ricorrenti: logo, scrolltext, rasterbars! ▸ Max 16k (0x4000 bytes) inclusa grafica suono e codice ▸ Compatibili PAL/NTSC TESTO CRACK INTRO? ▸ Fairlight [FLT] #01 TESTO CRACK INTRO? ▸ TRIAD "Raster Revenge intro" TESTO CRACK INTRO? ▸ Exodus #04 TESTO CRACK INTRO? ▸ Alpha Flight #02 TESTO FROM CRACK INTROS TO DEMOS! ▸ Effetti sempre più spettacolari e complicati ▸ Standalone, non più linkati ai giochi ▸ Utilizzo del 100% della memoria della macchina ▸ Compatibilità PAL/NTSC non più necessaria ▸ Commistione di arte e cultura informatica ▸ Demo making = disciplina hacker TESTO STILL RULING.. IN 2016! ▸ Mekanix (Booze Design) - 2010 TESTO STILL RULING.. IN 2016! ▸ Edge of Disgrace (Booze Design) - 2008 TESTO STILL RULING.. IN 2016! ▸ We Are New - Fairlight [2010] TESTO STILL RULING.. IN 2016! ▸ Wonderland XII (Censor Design) - 2013 C64 HARDWARE ▸ CPU: Mos Technology 6510 (8 bit / 0,985 MHz) ▸ RAM: 64Kb ▸ Video: VIC-II (16 colori) ▸ Audio: SID 6581 / 8580 (3 canali audio) ▸ 2 CIA (Complex Interface Adapter): controllo dei processi di I/O e i timer di sistema C64 MEMORY MAP (FONTE: C64-WIKI.COM) 64 Kb Totali COMMODORE 64 MEMORY MAP • 0x1FFF - Kernal Rom • 0xFFF - Char Rom / IO • 0x1FFF - Basic Rom • 0xAFFF - Free Ram (DEC) • 8kb - Kernal Rom • 4kb - Char Rom / IO • 8kb - Basic Rom • 44kb - Free Ram MOS 6510 ▸ 3 Registri a 8 bit (A,X,Y) ▸ Indirizzamento a 16 bit (max 64kb) ▸ Derivato del 6502 MOS VIC-II ▸ Risoluzione max: 320x200 (hi res) / 160x200 (multicolour) ▸ Modalità testo o bitmap ▸ 16 colori ▸ 8 sprites (24x21 pixels ognuno) ▸ Raster Interrupt ▸ Smooth Scrolling MOS VIC-II / PALETTE ▸ 16 colori contrassegnati da un valore 0x0 -> 0xF ▸ Ogni modalità grafica ha delle restrizioni ▸ Colour clash COMMODORE 64 INSTRUCTION SET ▸ 18 Opcodes Aritmetici / Logici (ORA, AND, EOR, ADC, SBC..) ▸ 16 Opcodes per leggere o scrivere la memoria o i registri del processore / stack (LDA, STA, LDX, LDY, STX, TAX..) ▸ 22 Opcodes per effettuare salti e leggere i flags del processore (JMP, RTS, BPL, BMI, CLC..) ▸ 21 "Illegal" opcodes non documentati ufficialmente ma scoperti nel tempo (LAX, SAX, SLO, RLA, AXS..) EX1.ASM UN SEMPLICE ESEMPIO PER COMINCIARE! sei //fermiamo gli interrupt lda #$00 //carichiamo nell'accumulatore il valore #$00 sta $d020 //scriviamo il valore in $d020 -> colore del bordo (diventa nero) lda #$04 //carichiamo nell'accumulatore il valore #$04 sta $d021 //scriviamo il valore in $d021 -> colore dello schermo (viola) jmp * //loop infinito TESTO TRADUZIONE DELLE ISTRUZIONI ▸ L'assembler "converte" 1:1 il sorgente con l'eseguibile ▸ Ogni istruzione è lunga da 1 a 3 bytes ▸ Esempio di traduzione *= $810 lda #$02 .C:0810 A9 02 sta $d020 .C:0812 8D 20 D0 jmp * .C:0815 4C 15 08 COMMODORE 64 CPU FLAGS (SOLO ALCUNI..) ▸ N = negative flag (1 quando il risultato di una operazione è negativo) ▸ V = overflow flag (1 su signed overflow) ▸ I = IRQ flag (quando è a 1 gli irq sono disabilitati.. quasi sempre) ▸ Z = zero flag (quando un operazione ritorna 0) ▸ C = carry flag (1su overflow unsigned) FONTE: CODEBASE64.ORG LO SCHERMO Area Visibile • Screen Area: 320x200 • Totale: 402x292 • 312 "Rasterlines" • Registri $d011 e $d012 • Badline ogni 8 linee • Standard line = 63 cicli CPU • Bad line = 23 cicli CPU LE BADLINES ▸ Ogni rasterline "dura" 63 cicli cpu (PAL) ▸ Nell'area schermo il VIC "ruba" 40 cicli ogni 8 linee per generare una badline ▸ Nelle badlines viene aggiornato il puntatore alla memoria schermo corrente EX2.ASM ESERCIZIETTO SUI RASTER! * = $0810 lda #$00 tax tay jsr $1000 ; inizializzo musica mainloop: lda #$85 wait: cmp $d012 ; confronto $d012 con #$85 bne wait ; se false, continuo a loopare inc $d020 ; incremento il colore del bordo jsr $1003 ; play della musica dec $d020 ; decremento il colore del bordo jmp mainloop ; loop again! EX_RASTERBARS.ASM HELLO RASTERBARS! line_loop: lda colors,x //leggo la tabella dei colori usando il registro x come indice cpy $d012 //attendo la rasterline giusta bne *-3 // sta $d020 //se sono arrivato alla rasterline giusta cambio il colore del bordo cpx #54 //loop finche' non ho finito di leggere la tabella beq play_music //se x=54 effetto finito, suoniamo la musica! inx //incremento x -> leggero' il prossimo colore iny //incremento y -> attendero' la prossima rasterline jmp line_loop //loop sulla prossima linea! colors: .byte $06,$06,$06,$0e,$06,$0e .byte $0e,$06,$0e,$0e,$0e,$03 .byte $0e,$03,$03,$0e,$03,$03 .byte $03,$01,$03,$01,$01,$03 .byte $01,$01,$01,$03,$01,$01 .byte $03,$01,$03,$03,$03,$0e .byte $03,$03,$0e,$03,$0e,$0e .byte $0e,$06,$0e,$0e,$06,$0e .byte $06,$06,$06,$00,$00,$00 TIMING IS THE KEY ▸ Effetti basati su features non documentate del VIC-II ▸ Manipolazione di registri del VIC al momento giusto! ▸ Il busy waiting spreca troppa cpu (siamo a < 1mhz!) ▸ Soluzione: INTERRUPTS! COSA SONO GLI INTERRUPT? ▸ Permettono di eseguire un blocco di istruzioni in un preciso momento ▸ Eliminano la necessità del busy waiting (yeah!) ▸ Tipologia: Raster o Timer ▸ Forniscono una sorta di "multitasking" ▸ Paragonabili a una "sveglia" RASTER INTERRUPT ▸ Generati dal VIC ▸ Il valore di $d012 e il bit 7 di $d011 decidono la linea dell'IRQ ▸ Quando il raster beam raggiunge la linea scelta in $d012/$d011 l'interrupt viene eseguito ▸ Terminato il blocco di istruzioni nell'IRQ il controllo torna nel "main" EX3.ASM OPTIMIZATION TIME! ▸ Possiamo scrivere l'esempio predecente facendo uso di IRQ ▸ Come: generare un raster interrupt una volta per frame per suonare la musica ▸ In questa maniera evitiamo il busy waiting e lasciamo la cpu libera per altri task! SLIDE UN PÒ COMPLICATA, MA NE VALE LA PENA, PROMESSO! IT'S VIC PORN TIME! ▸ Se si trova su una badline il VIC indirizza la memoria schermo e il charset corrente ▸ Il registro $d011 regola la generazione delle badline ▸ Se i bit 0/1/2 di $d011 coincidono con i bit 0/1/2 di $d012 all'inizio di una linea, viene generata una badline ▸ Utilizzando un interrupt possiamo "sincronizzarci" e manipolare la creazione delle badline per ottenere effetti nella demo! UN EFFETTO DI ESEMPIO - FLEXIBLE LINE DISTANCE FLEXIBLE LINE DISTANCE (FLD) ▸ Le badline segnalano al VIC "cosa" disegnare nelle prox 8 linee di grafica (fino alla prossima badline) ▸ Manipolando $d011 possiamo ritardare le badline, impedendo questo aggiornamento ▸ Questo ci permette di effettuare scrolling verticale senza toccare la memoria ▸ Questa tecnica si chiama "Flexible Line Distance" UN EFFETTO DI ESEMPIO - FLEXIBLE LINE DISTANCE ▸ Se si trova su una badline il VIC indirizza la memoria schermo e il charset corrente (eventualmente aggiornando il puntamento) ▸ Il registro $d011 regola la generazione delle badline ▸ Se i bit 0/1/2 di $d011 coincidono con i bit 0/1/2 di $d012 all'inizio di una linea, viene generata una badline ▸ Utilizzando un interrupt possiamo "sincronizzarci" e manipolare la creazione delle badline per ottenere effetti nella demo! UN EFFETTO DI ESEMPIO - FLEXIBLE LINE DISTANCE start: sei loop1: bit $d011 //Aspetto un nuovo frame bpl *-3 bit $d011 bmi *-3 lda #$13 //Ripristino $d011 (per fare l'fld piu' tardi) sta $d011 jsr CalcNumLines //Calcolo il valore di oscillazione dell'effetto lda #$40 //busy waiting della linea giusta.. cmp $d012 bne *-3 ldx NumFLDLines beq loop1 //se vale 0 si torna all'inizio (niente effetto!) loop2: lda $d012 //Attendo la fine della rasterline.. cmp $d012 beq *-3 //a questo punto sono all'inizio della rasterline successiva clc //Faccio una linea di FLD alterando il valore dei bit 0-1-2 di $d011! lda $d011 adc #1 and #7 ora #$10 sta $d011 dex //Decremento il contatore bne loop2 //E continuo il loop finche' il contatore non e' 0! jmp loop1 //Via al prossimo frame.. CalcNumLines: lda #0 bpl *+4 eor #$ff lsr sta NumFLDLines inc CalcNumLines+1 rts $D011 TRICKERY ANCORA SULLE BADLINES ▸ Moltissimi effetti sono basati sulla manipolazione di $d011 per ottenere badlines "a piacimento" ▸ Distorsione "realtime" di textures (Y-stretchers, linecrunchers) ▸ Modalità grafiche custom che superano le limitazioni standard del C64 ▸ Esempi: FLI, FPP, Linecruncher SPRITES TRICKERY IN PILLOLE INTRODUZIONE AL MULTIPLEXING DEGLI SPRITES ▸ Molti dicono: "Il C64 può gestire al massimo 8 sprites" ▸ Realtà: "L'hardware del Commodore 64 può gestire al massimo 8 sprites per rasterline" ▸ Regola: la coordinata Y di uno sprite deve essere impostata prima che il raster la raggiunga ▸ Dopo aver disegnato uno sprite possiamo però "riutilizzarlo", posizionandolo più in basso in tempo utile ▸ Possiamo anche cambiare colore e definizione per ottenere uno sprite totalmente diverso! SPRITES TRICKERY IN PILLOLE INTRODUZIONE AL MULTIPLEXING DEGLI SPRITES ▸ Ogni volta che vogliamo riutilizzare