; Programma in Assembly per Commodore 64 ; Scritto da Kimono (F. Nardella) ; Visualizza e ruota un ottaedro in modalità bitmap (HiRes) ; Le coordinate dei vertici del poliedro sono precalcolate e lette da memoria * = $C000 ;****************************************************** ; PARAMETRI VICII ;****************************************************** VICII = $d000 VICII1 = VICII + $11 ; VICII Control Register 1 - Hi Res - 53265 VICII2 = VICII + $16 ; VICII Control Register 2 - Hi Res - 53270 VICIIA = VICII + $18 ; VICII Start Address Graphic Ram - 53272 VICIIB = VICII + $20 ; VICII Border Color Registry - 53280 VICIIS = VICII + $21 ; VICII BackGround Color Registry - 53281 loc = $5a ;loc e loc+1 sono LSB e MSB della locaz. in Graphic RAM in cui accendere il pixel store = $5c bmpage = $ff FRAMEPTR = $fb ; Puntatore al frame corrente FRAMECNT = $fd ; Contatore dei frame PARAMS = $828 xL = PARAMS + 0 ; LSB sono le coordinate per plot xH = PARAMS + 1 ; MSB sono le coordinate per plot yy = PARAMS + 2 ; sono le coordinate per plot x1 = PARAMS + 3 ; Coordinata X del primo punto y1 = PARAMS + 4 ; Coordinata Y del primo punto x2 = PARAMS + 5 ; Coordinata X del secondo punto y2 = PARAMS + 6 ; Coordinata Y del secondo punto dx = PARAMS + 7 ; Differenza X dy = PARAMS + 8 ; Differenza Y sx = PARAMS + 9 ; Direzione X (-1 o +1) sy = PARAMS + 10 ; Direzione Y (-1 o +1) err = PARAMS + 11 ; Errore accumulato START ldx #11 stx VICIIB ; Bordo grigio scuro jsr HIRES ; Passa in modalità hi res jsr GRRAM ; Imposta l'area della RAM grafica jsr CLEARGR ; Cancella la RAM grafica jsr CLEARCO ; Cancella la Color RAM jsr DRAWCUBE ; Disegna e ruota il dodecaedro rts DRAWCUBE ; Inizializza il puntatore al primo frame lda #COORD_TABLE sta FRAMEPTR+1 lda #0 sta FRAMECNT ANIMATE jsr DRAWFRAME ; Disegna il frame corrente jsr DELAY ; Attendi jsr DELAY jsr DELFRAME ; Cancella il frame corrente ; Passa al frame successivo lda FRAMEPTR clc adc #48 ; Ogni frame occupa 48 byte sta FRAMEPTR bcc b_no_carry inc FRAMEPTR+1 b_no_carry ; Incrementa il contatore dei frame inc FRAMECNT lda FRAMECNT cmp #15 ; Numero totale di frame bne ANIMATE jmp DRAWCUBE ; -------------------------------------------------------------- ; Funzione per disegnare il cubo ; -------------------------------------------------------------- DRAWFRAME ldy #0 ldx #0 draw_loop ; Leggi coordinate x1,y1 lda (FRAMEPTR),y sta x1 iny lda (FRAMEPTR),y sta y1 iny ; Leggi coordinate x2,y2 lda (FRAMEPTR),y sta x2 iny lda (FRAMEPTR),y sta y2 iny stx store+1 ; Salva X tya pha ; Salva Y jsr LINE ; Disegna la linea pla tay ; Recupera Y ldx store+1 ; Recupera X inx cpx #12 ; 12 linee per il dodecaedro bne draw_loop rts ; -------------------------------------------------------------- ; Funzione per cancellare il cubo ; -------------------------------------------------------------- DELFRAME ldy #0 ldx #0 del_loop ; Leggi coordinate x1,y1 lda (FRAMEPTR),y sta x1 iny lda (FRAMEPTR),y sta y1 iny ; Leggi coordinate x2,y2 lda (FRAMEPTR),y sta x2 iny lda (FRAMEPTR),y sta y2 iny stx store+2 tya pha ; Salva Y jsr DELLINE ; Disegna la linea pla ; Recupera Y tay ldx store+2 inx cpx #12 ; 12 linee per il dodecaedro bne del_loop rts ; -------------------------------------------------------------- ; Funzione per introdurre un ritardo ; -------------------------------------------------------------- DELAY ldx #$FF ldy #$FF delay_loop dex bne delay_loop dey bne delay_loop rts ; -------------------------------------------------------------- ; Funzione per attivare la modalità bitmap HiRes ; -------------------------------------------------------------- HIRES lda VICII1 ora #32 sta VICII1 rts GRRAM lda VICIIA ora #8 sta VICIIA rts ; -------------------------------------------------------------- ; Funzione per pulire lo schermo grafico ; -------------------------------------------------------------- CLEARGR lda #0 sta $fa lda #$20 sta $fb ldx #32 loop ldy #$0 byte lda #$0 sta ($fa),y dey bne byte inc $fb dex bne loop rts ; -------------------------------------------------------------- ; Funzione per pulire e impostare la Color RAM ; -------------------------------------------------------------- CLEARCO lda #208 ldx #0 stx $fa ldx #4 stx $fb ldy #0 cloop sta ($fa),y iny bne CLOOP inc $fb ldx $fb cpx #8 bne cloop rts ; -------------------------------------------------------------- ; Funzione per disegnare un punto ; -------------------------------------------------------------- PLOT jsr SUB_PLOT ora BITMASK,x sta (loc),y rts ; -------------------------------------------------------------- ; Funzione per cancellare un punto ; -------------------------------------------------------------- UNPLOT jsr SUB_PLOT and NEGMASK,x sta (loc),y rts SUB_PLOT lda xL and #7 tax lda #0 sta loc lda xL and #$f8 sta store lda yy lsr lsr lsr sta loc+1 lsr ror loc lsr ror loc adc loc+1 sta loc+1 lda yy and #7 adc loc adc store sta loc lda loc+1 adc xH adc bmpage sta loc+1 ldy #0 lda (loc),y rts ; -------------------------------------------------------------- ; Funzione per disegnare una linea tra due punti ; -------------------------------------------------------------- LINE jsr SUB_LINE ; Calcola error = (dx > dy ? dx : dy) / 2 lda dx cmp dy bcc dy_greater lsr ; Dividi dx per 2 sta err jmp check_slopes dy_greater lda dy lsr ; Dividi dy per 2 sta err check_slopes ; Decidi quale routine di loop usare lda dx cmp dy bcs dx_ge_dy ; Se dx >= dy, usa la routine x-dominant ; Routine y-dominant (pendenza > 1) y_loop jsr PLOT ; Disegna il punto ; Aggiorna l'errore e muovi x se necessario lda err clc adc dx ; err += dx sta err cmp dy ; Se err >= dy... bcc skip_x_step sec sbc dy ; ...sottrai dy da err sta err lda xL ; ...e incrementa/decrementa x clc adc sx sta xL bcc skip_x_step inc xH ; Gestisci il riporto se necessario skip_x_step ; Incrementa o decrementa y lda yy clc adc sy sta yy ; Controlla se abbiamo raggiunto y2 cmp y2 bne y_loop ; Se y != y2, continua lda xL cmp x2 bne y_loop ; Se x != x2, continua rts dx_ge_dy ; Routine x-dominant (pendenza <= 1) x_loop jsr PLOT ; Disegna il punto ; Aggiorna l'errore e muovi y se necessario lda err clc adc dy ; err += dy sta err cmp dx ; Se err >= dx... bcc skip_y_step sec sbc dx ; ...sottrai dx da err sta err lda yy ; ...e incrementa/decrementa y clc adc sy sta yy skip_y_step ; Incrementa o decrementa x lda xL clc adc sx sta xL bcc no_carry inc xH ; Gestisci il riporto se necessario no_carry ; Controlla se abbiamo raggiunto x2 cmp x2 bne x_loop ; Se x != x2, continua lda yy cmp y2 bne x_loop ; Se y != y2, continua rts SUB_LINE ; Controlla se x1 > x2 e in tal caso scambia i punti lda x1 cmp x2 bcc no_swap_x ; Se x1 < x2, non serve scambiare ; Scambia x1 e x2 lda x1 pha ; Salva x1 nello stack lda x2 sta x1 pla sta x2 ; Scambia anche y1 e y2 lda y1 pha ; Salva y1 nello stack lda y2 sta y1 pla sta y2 no_swap_x ; Calcola dx = abs(x2 - x1) lda x2 sec sbc x1 bpl store_dx ; Se è positivo, salta eor #$FF ; Altrimenti, negalo (complemento a 1) clc adc #1 ; Complemento a 2 per ottenere abs() store_dx sta dx ; Calcola dy = abs(y2 - y1) lda y2 sec sbc y1 bpl store_dy ; Se è positivo, salta eor #$FF ; Altrimenti, negalo clc adc #1 store_dy sta dy ; Determina direzione x (sx) lda x1 cmp x2 bcc x_ascending lda #$FF ; sx = -1 (x1 > x2) jmp store_sx x_ascending lda #$01 ; sx = 1 (x1 < x2) store_sx sta sx ; Assicurati che sx sia sempre positivo lda #$01 sta sx ; Determina direzione y (sy) lda y1 cmp y2 bcc y_ascending lda #$FF ; sy = -1 (y1 > y2) jmp store_sy y_ascending lda #$01 ; sy = 1 (y1 < y2) store_sy sta sy ; Imposta i valori iniziali di x e y lda x1 sta xL lda #0 ; Assumiamo che xH sia sempre 0 per semplicità sta xH lda y1 sta yy rts ; -------------------------------------------------------------- ; Funzione per cancellare una linea tra due punti ; -------------------------------------------------------------- DELLINE jsr SUB_LINE ; Calcola error = (dx > dy ? dx : dy) / 2 lda dx cmp dy bcc d_dy_greater lsr ; Dividi dx per 2 sta err jmp d_check_slopes d_dy_greater lda dy lsr ; Dividi dy per 2 sta err d_check_slopes ; Decidi quale routine di loop usare lda dx cmp dy bcs d_dx_ge_dy ; Se dx >= dy, usa la routine x-dominant ; Routine y-dominant (pendenza > 1) d_y_loop jsr UNPLOT ; Cancella il punto ; Aggiorna l'errore e muovi x se necessario lda err clc adc dx ; err += dx sta err cmp dy ; Se err >= dy... bcc d_skip_x_step sec sbc dy ; ...sottrai dy da err sta err lda xL ; ...e incrementa/decrementa x clc adc sx sta xL bcc d_skip_x_step inc xH ; Gestisci il riporto se necessario d_skip_x_step ; Incrementa o decrementa y lda yy clc adc sy sta yy ; Controlla se abbiamo raggiunto y2 cmp y2 bne d_y_loop ; Se y != y2, continua lda xL cmp x2 bne d_y_loop ; Se x != x2, continua rts d_dx_ge_dy ; Routine x-dominant (pendenza <= 1) d_x_loop jsr UNPLOT ; Cancella il punto ; Aggiorna l'errore e muovi y se necessario lda err clc adc dy ; err += dy sta err cmp dx ; Se err >= dx... bcc d_skip_y_step sec sbc dx ; ...sottrai dx da err sta err lda yy ; ...e incrementa/decrementa y clc adc sy sta yy d_skip_y_step ; Incrementa o decrementa x lda xL clc adc sx sta xL bcc d_no_carry inc xH ; Gestisci il riporto se necessario d_no_carry ; Controlla se abbiamo raggiunto x2 cmp x2 bne d_x_loop ; Se x != x2, continua lda yy cmp y2 bne d_x_loop ; Se y != y2, continua rts BITMASK .byte $80, $40, $20, $10, $08, $04, $02, $01 ; Tabella maschere negate (complemento delle maschere bit) NEGMASK .byte $7F, $BF, $DF, $EF, $F7, $FB, $FD, $FE COORD_TABLE ; Frame 0 .byte 210, 100, 160, 150 .byte 210, 100, 160, 50 .byte 210, 100, 160, 100 .byte 210, 100, 160, 100 .byte 110, 100, 160, 150 .byte 110, 100, 160, 50 .byte 110, 100, 160, 100 .byte 110, 100, 160, 100 .byte 160, 150, 160, 100 .byte 160, 150, 160, 100 .byte 160, 50, 160, 100 .byte 160, 50, 160, 100 ; Frame 1 .byte 211, 100, 161, 146 .byte 211, 100, 158, 48 .byte 211, 100, 164, 91 .byte 211, 100, 153, 113 .byte 111, 100, 161, 146 .byte 111, 100, 158, 48 .byte 111, 100, 164, 91 .byte 111, 100, 153, 113 .byte 161, 146, 164, 91 .byte 161, 146, 153, 113 .byte 158, 48, 164, 91 .byte 158, 48, 153, 113 ; Frame 2 .byte 211, 100, 163, 141 .byte 211, 100, 155, 49 .byte 211, 100, 167, 83 .byte 211, 100, 147, 126 .byte 113, 100, 163, 141 .byte 113, 100, 155, 49 .byte 113, 100, 167, 83 .byte 113, 100, 147, 126 .byte 163, 141, 167, 83 .byte 163, 141, 147, 126 .byte 155, 49, 167, 83 .byte 155, 49, 147, 126 ; Frame 3 .byte 211, 100, 167, 135 .byte 211, 100, 149, 52 .byte 211, 100, 170, 75 .byte 211, 100, 144, 136 .byte 115, 100, 167, 135 .byte 115, 100, 149, 52 .byte 115, 100, 170, 75 .byte 115, 100, 144, 136 .byte 167, 135, 170, 75 .byte 167, 135, 144, 136 .byte 149, 52, 170, 75 .byte 149, 52, 144, 136 ; Frame 4 .byte 210, 100, 172, 128 .byte 210, 100, 141, 59 .byte 210, 100, 171, 67 .byte 210, 100, 143, 143 .byte 118, 100, 172, 128 .byte 118, 100, 141, 59 .byte 118, 100, 171, 67 .byte 118, 100, 143, 143 .byte 172, 128, 171, 67 .byte 172, 128, 143, 143 .byte 141, 59, 171, 67 .byte 141, 59, 143, 143 ; Frame 5 .byte 209, 100, 178, 121 .byte 209, 100, 133, 69 .byte 209, 100, 171, 60 .byte 209, 100, 145, 148 .byte 121, 100, 178, 121 .byte 121, 100, 133, 69 .byte 121, 100, 171, 60 .byte 121, 100, 145, 148 .byte 178, 121, 171, 60 .byte 178, 121, 145, 148 .byte 133, 69, 171, 60 .byte 133, 69, 145, 148 ; Frame 6 .byte 207, 100, 183, 112 .byte 207, 100, 125, 80 .byte 207, 100, 168, 55 .byte 207, 100, 150, 150 .byte 124, 100, 183, 112 .byte 124, 100, 125, 80 .byte 124, 100, 168, 55 .byte 124, 100, 150, 150 .byte 183, 112, 168, 55 .byte 183, 112, 150, 150 .byte 125, 80, 168, 55 .byte 125, 80, 150, 150 ; Frame 7 .byte 204, 100, 188, 104 .byte 204, 100, 119, 93 .byte 204, 100, 163, 51 .byte 204, 100, 156, 150 .byte 128, 100, 188, 104 .byte 128, 100, 119, 93 .byte 128, 100, 163, 51 .byte 128, 100, 156, 150 .byte 188, 104, 163, 51 .byte 188, 104, 156, 150 .byte 119, 93, 163, 51 .byte 119, 93, 156, 150 ; Frame 8 .byte 201, 100, 191, 95 .byte 201, 100, 115, 106 .byte 201, 100, 156, 49 .byte 201, 100, 163, 148 .byte 131, 100, 191, 95 .byte 131, 100, 115, 106 .byte 131, 100, 156, 49 .byte 131, 100, 163, 148 .byte 191, 95, 156, 49 .byte 191, 95, 163, 148 .byte 115, 106, 156, 49 .byte 115, 106, 163, 148 ; Frame 9 .byte 196, 100, 193, 86 .byte 196, 100, 115, 117 .byte 196, 100, 146, 50 .byte 196, 100, 171, 145 .byte 135, 100, 193, 86 .byte 135, 100, 115, 117 .byte 135, 100, 146, 50 .byte 135, 100, 171, 145 .byte 193, 86, 146, 50 .byte 193, 86, 171, 145 .byte 115, 117, 146, 50 .byte 115, 117, 171, 145 ; Frame 10 .byte 191, 100, 193, 77 .byte 191, 100, 117, 128 .byte 191, 100, 136, 53 .byte 191, 100, 180, 140 .byte 139, 100, 193, 77 .byte 139, 100, 117, 128 .byte 139, 100, 136, 53 .byte 139, 100, 180, 140 .byte 193, 77, 136, 53 .byte 193, 77, 180, 140 .byte 117, 128, 136, 53 .byte 117, 128, 180, 140 ; Frame 11 .byte 186, 100, 191, 68 .byte 186, 100, 123, 136 .byte 186, 100, 127, 60 .byte 186, 100, 188, 134 .byte 143, 100, 191, 68 .byte 143, 100, 123, 136 .byte 143, 100, 127, 60 .byte 143, 100, 188, 134 .byte 191, 68, 127, 60 .byte 191, 68, 188, 134 .byte 123, 136, 127, 60 .byte 123, 136, 188, 134 ; Frame 12 .byte 180, 100, 186, 61 .byte 180, 100, 130, 142 .byte 180, 100, 118, 68 .byte 180, 100, 196, 127 .byte 147, 100, 186, 61 .byte 147, 100, 130, 142 .byte 147, 100, 118, 68 .byte 147, 100, 196, 127 .byte 186, 61, 118, 68 .byte 186, 61, 196, 127 .byte 130, 142, 118, 68 .byte 130, 142, 196, 127 ; Frame 13 .byte 173, 100, 179, 55 .byte 173, 100, 139, 146 .byte 173, 100, 113, 78 .byte 173, 100, 202, 119 .byte 151, 100, 179, 55 .byte 151, 100, 139, 146 .byte 151, 100, 113, 78 .byte 151, 100, 202, 119 .byte 179, 55, 113, 78 .byte 179, 55, 202, 119 .byte 139, 146, 113, 78 .byte 139, 146, 202, 119 ; Frame 14 .byte 166, 100, 170, 51 .byte 166, 100, 149, 149 .byte 166, 100, 110, 89 .byte 166, 100, 207, 110 .byte 155, 100, 170, 51 .byte 155, 100, 149, 149 .byte 155, 100, 110, 89 .byte 155, 100, 207, 110 .byte 170, 51, 110, 89 .byte 170, 51, 207, 110 .byte 149, 149, 110, 89 .byte 149, 149, 207, 110