Last active
December 29, 2018 19:00
-
-
Save kristerw/59de3f1005a8d20e4fb56a9e20369491 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Zero page variables | |
sprite_x_idx = $03 | |
sprite_y_idx = $04 | |
sprite_skip_counter = $05 | |
tmp1 = $10 | |
irq_saved_a = $20 | |
irq_saved_x = $21 | |
irq_saved_y = $22 | |
irq_color_addr_lo = $22 | |
irq_color_addr_hi = $23 | |
* = $07ff | |
;; File header and a BASIC program that calls the assembly code. | |
!byte $01,$08 ; Load address $0801 | |
!byte $0c,$08 ; ??? Usually end of 1st line of BASIC prog. | |
!byte $0a,$00,$9e,$20,$32,$30,$36,$34,$00 ; 10 SYS 2064 | |
!byte $00,$00 ; End of program | |
*= $0810 | |
start: | |
jsr init_irq | |
jsr clear_screen | |
jsr init_sprites | |
loop: | |
jsr step_time | |
;; Wait until the raster is below the sprites. | |
loop1: | |
ldx $d012 | |
cpx #250 | |
bne loop1 | |
jsr move_sprites | |
jmp loop | |
;;; Update sine-table indices one time step. | |
step_time: | |
inc sprite_x_idx | |
lda sprite_x_idx | |
and #127 | |
sta sprite_x_idx | |
;; Skip some updates to y to prevent the position from repeating | |
;; every 64 frames. | |
inc sprite_skip_counter | |
ldx sprite_skip_counter | |
cpx #53 | |
bne st1 | |
ldx #0 | |
stx sprite_skip_counter | |
rts | |
st1: | |
inc sprite_y_idx | |
lda sprite_y_idx | |
and #127 | |
sta sprite_y_idx | |
rts | |
;;; Update sprites x and y coordinates | |
move_sprites: | |
ldx #0 | |
ldy sprite_x_idx | |
ms1: | |
tya | |
clc | |
adc #5 | |
and #127 | |
sta tmp1 | |
and #63 | |
tay | |
lda sine64,y | |
clc | |
adc #168 | |
ldy tmp1 | |
adc sine128,y | |
sta $d000,x | |
inx | |
inx | |
cpx #16 | |
bne ms1 | |
ldx #0 | |
ldy sprite_y_idx | |
ms2: | |
tya | |
clc | |
adc #5 | |
and #127 | |
tay | |
lda sine128,y | |
clc | |
adc #154 | |
sta $d001,x | |
inx | |
inx | |
cpx #16 | |
bne ms2 | |
rts | |
clear_screen: | |
lda #$20 | |
cs_loop: | |
sta $0400,x | |
sta $0500,x | |
sta $0600,x | |
sta $0700,x | |
dex | |
bne cs_loop | |
rts | |
;;; Initialize sprites | |
;;; https://www.c64-wiki.com/wiki/Sprite | |
init_sprites: | |
ldx #0 | |
ldy #0 | |
is1: | |
lda #sprite1/64 | |
sta $07f8,y | |
lda #0 | |
sta $d000,x | |
sta $d001,x | |
lda #1 | |
sta $d027,y | |
inx | |
inx | |
iny | |
cpx #16 | |
bne is1 | |
lda #0 | |
sta $d010 | |
lda #$ff | |
sta $d015 | |
;; Initialize variables used for calculating sprite positions. | |
lda #0 | |
sta sprite_x_idx | |
sta sprite_skip_counter | |
lda #40 | |
sta sprite_y_idx | |
rts | |
;;; Initialize IRQ | |
;;; http://codebase64.org/doku.php?id=base:introduction_to_raster_irqs | |
init_irq: | |
sei | |
lda #$7f | |
sta $dc0d | |
sta $dd0d | |
lda $dc0d | |
lda $dd0d | |
lda #1 | |
sta $d01a | |
lda #80 | |
sta $d012 | |
lda #$1b | |
sta $d011 | |
lda #$35 | |
sta $01 | |
lda #<irq1 | |
sta $fffe | |
lda #>irq1 | |
sta $ffff | |
cli | |
rts | |
;; Align the IRQ code to ensure the branches do no cross a page | |
;; boundary (branches takes longer when crossing page boundaries, | |
;; and the code below rely on branches taking 3 cycles). | |
!align 255, 0 | |
;;; Draw rasterbar1 | |
irq1: | |
;; Entering the IRQ takes 9-16 cycles (depending how long it takes to | |
;; execute the current instruction. We do not need to be cycle-exact | |
;; (as the first cycles are outside the screen), so assume 10 cycles. | |
;; But this is sloppy... See the link below for implementing better | |
;; raster routines: | |
;; http://codebase64.org/doku.php?id=base:making_stable_raster_routines | |
sta irq_saved_a ; 3 cycles | |
stx irq_saved_x ; 3 | |
sty irq_saved_y ; 3 | |
lda #<irq2 ; 2 | |
sta $fffe ; 4 | |
lda #>irq2 ; 2 | |
sta $ffff ; 4 | |
lda #100 ; 2 | |
sta $d012 ; 4 | |
lda #$ff ; 2 | |
sta $d019 ; 4 | |
lda #<rasterbar1 ; 2 | |
sta irq_color_addr_lo ; 3 | |
lda #>rasterbar1 ; 2 | |
sta irq_color_addr_hi ; 3 | |
jmp rasterbar_irq ; 3 | |
;;; Second half of IRQ. Assumes the first part has taken 56 cycles. | |
rasterbar_irq: | |
ldy #0 ; 2 cycles | |
lda (irq_color_addr_lo),y ; 5 | |
;; ---------------------------- = 63 | |
irq1_loop2: | |
sta $d020 ; 4 | |
sta $d021 ; 4 | |
ldx #9 ; 2 | |
irq1_loop3: | |
dex ; 2 * n | |
bne irq1_loop3 ; 3 * n - 1 | |
iny ; 2 | |
lda (irq_color_addr_lo),y ; 4 | |
bne irq1_loop2 ; 3 (2 for last iteration) | |
;; ---------------------------- = 63/62 | |
sta $d020 | |
sta $d021 | |
ldy irq_saved_y | |
ldx irq_saved_x | |
lda irq_saved_a | |
rti | |
;;; Draw rasterbar2 | |
irq2: | |
sta irq_saved_a | |
stx irq_saved_x | |
sty irq_saved_y | |
lda #<irq1 | |
sta $fffe | |
lda #>irq1 | |
sta $ffff | |
lda #85 | |
sta $d012 | |
lda #$ff | |
sta $d019 | |
lda #<rasterbar2 | |
sta irq_color_addr_lo | |
lda #>rasterbar2 | |
sta irq_color_addr_hi | |
jmp rasterbar_irq | |
rasterbar1: | |
!byte 6, 14, 14, 6, 0 | |
rasterbar2: | |
!byte 8, 7, 7, 8, 0 | |
sine64: | |
!byte $00,$03,$06,$09,$0b,$0e,$11,$13,$15,$17,$19,$1a,$1c,$1d,$1d,$1e | |
!byte $1e,$1e,$1d,$1d,$1c,$1a,$19,$17,$15,$13,$11,$0e,$0c,$09,$06,$03 | |
!byte $00,$fd,$fa,$f7,$f5,$f2,$ef,$ed,$eb,$e9,$e7,$e6,$e4,$e3,$e3,$e2 | |
!byte $e2,$e2,$e3,$e3,$e4,$e6,$e7,$e9,$eb,$ed,$ef,$f2,$f4,$f7,$fa,$fd | |
sine128: | |
!byte $00,$01,$02,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f,$10 | |
!byte $11,$12,$13,$13,$14,$15,$15,$16,$16,$17,$17,$17,$18,$18,$18,$18 | |
!byte $18,$18,$18,$18,$18,$17,$17,$17,$16,$16,$15,$15,$14,$13,$13,$12 | |
!byte $11,$10,$0f,$0e,$0d,$0c,$0b,$0a,$09,$08,$07,$06,$05,$04,$02,$01 | |
!byte $00,$ff,$fe,$fd,$fb,$fa,$f9,$f8,$f7,$f6,$f5,$f4,$f3,$f2,$f1,$f0 | |
!byte $ef,$ee,$ed,$ed,$ec,$eb,$eb,$ea,$ea,$e9,$e9,$e9,$e8,$e8,$e8,$e8 | |
!byte $e8,$e8,$e8,$e8,$e8,$e9,$e9,$e9,$ea,$ea,$eb,$eb,$ec,$ed,$ed,$ee | |
!byte $ef,$f0,$f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$fa,$fb,$fc,$fe,$ff | |
!align 63, 0 ; Sprites must be 64-byte aligned | |
sprite1: | |
!byte $00,$7e,$00 | |
!byte $03,$ff,$c0 | |
!byte $07,$ff,$e0 | |
!byte $1f,$ff,$f8 | |
!byte $1f,$ff,$f8 | |
!byte $3f,$ff,$fc | |
!byte $7f,$ff,$fe | |
!byte $7f,$ff,$fe | |
!byte $ff,$ff,$ff | |
!byte $ff,$ff,$ff | |
!byte $ff,$ff,$ff | |
!byte $ff,$ff,$ff | |
!byte $ff,$ff,$ff | |
!byte $7f,$ff,$fe | |
!byte $7f,$ff,$fe | |
!byte $3f,$ff,$fc | |
!byte $1f,$ff,$f8 | |
!byte $1f,$ff,$f8 | |
!byte $07,$ff,$e0 | |
!byte $03,$ff,$c0 | |
!byte $00,$7e,$00 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment