Skip to content

Instantly share code, notes, and snippets.

@cesarmiquel
Created November 13, 2023 03:07
Show Gist options
  • Save cesarmiquel/b4977b6f1badb01eed60c8cbdae7c007 to your computer and use it in GitHub Desktop.
Save cesarmiquel/b4977b6f1badb01eed60c8cbdae7c007 to your computer and use it in GitHub Desktop.
C64 left scroller
//============================================================
// resources
//============================================================
.const logo_width = 10 + 93 + 10
.const logo_height = 14
.const state_1 = 1
.const state_2 = 2
.const state_3 = 3
.const screen_bg_color = BLACK
.const paused = $1a
.const next_scrollx = $1b
.const scroll_state = $1c
.const scroll_offset = $1d // fine grain scroll
.const offset = $1e
.const scroll_dir = $1f
//============================================================
// resources: PETSCII and SID data
//============================================================
// https://csdb.dk/sid/?id=26164
// Dull - Jeroen Soede - Released: 1989 SoedeSoft
// Relocated to $1000 with sidreloc
.var music = LoadSid("dull-reloc.sid")
.var intro_data = LoadBinary( "rc/logo.char" )
.var intro_data_color = LoadBinary( "rc/logo.color" )
//============================================================
// symbols
//============================================================
.const screen_ram = $0400 // location of screen ram
.const color_ram = $d800 // location of screen ram
.pc = $0801 "Basic Upstart"
:BasicUpstart(start) // 10 sys$0810
.pc =$0810 "Program"
start:
//============================================================
// Initialize involved VIC-II registers
//============================================================
main:
sei // set interrupt disable flag
jsr clear_screen
// Init music
lda #music.startSong-1
jsr music.init
lda #$01 // Set Interrupt Request Mask...
sta $d01a // ...we want IRQ by Rasterbeam (%00000001)
// triger irq on line 200
lda #210
sta $d012
lda $d011
and #%01111111
sta $d011
lda #<irq // point IRQ Vector to our custom irq routine
ldx #>irq
sta $0314 // store in $314/$315
stx $0315
lda #$00 // trigger interrupt at row zero
sta $d012
sta scroll_state
// offset of logo
lda #0
sta offset
sta paused
lda #7
sta scroll_offset
// scroll direction 1: left, -1: right
lda #1
sta scroll_dir
cli // clear interrupt disable flag
jmp * // infinite loop
//============================================================
// Main loop called on each interrupt
//============================================================
irq:
dec $d019 // acknowledge IRQ / clear register for next interrupt
lda #210 // wait for line 210
cmp $d012
bne *-3
// Play SID
jsr music.play
// read keyboard and check for [space]
lda #$7F // %01111111
sta $dc00
lda $dc01
and #$10 // mask %00010000
bne !+
lda paused
eor #1
sta paused
!:
lda paused
bne finish_irq
// Smooth scroll always
jsr smooth_scroll
lda scroll_state
cmp #state_1
bne !+
jsr state_1_callback
jmp finish_irq
!:
cmp #state_2
bne !+
jsr state_2_callback
jmp finish_irq
!:
cmp #state_3
bne finish_irq
jsr state_3_callback
finish_irq:
lda $d011 // Reset bit 3 for the next frame
ora #$08
sta $d011
jmp $ea31 // return to Kernel routine
// smoooth scroll -------------------------------
smooth_scroll:
sec
lda scroll_offset
sbc #3
sta scroll_offset
cmp #0
bmi !+
jmp finish_scroll
// Reset scroll x de 0 -> 7
!:
lda #7
sta scroll_offset
lda $d016
// reset bit
and #%11110000
ora #%00000111
sta next_scrollx
lda #state_1
sta scroll_state
rts
finish_scroll:
lda $d016
and #%11110000
ora scroll_offset
sta $d016
rts
// state 1 -------------------------------
state_1_callback:
clc
inc offset
lda offset
cmp #logo_width
bmi draw
lda #0
sta offset
draw:
jsr scroll_screen_left
lda next_scrollx
sta $d016
lda #state_2
sta scroll_state
rts
// state 2 -------------------------------
state_2_callback:
lda #<petscii_data
clc
adc offset
sta $20
lda #>petscii_data
bcc !+
adc #1
!:
sta $21
lda #$c8+39 // fila 5
sta $22
lda #$04
sta $23
jsr write_last_col
lda #state_3
sta scroll_state
rts
// state 3 -------------------------------
state_3_callback:
//
// Color
//
lda #<petscii_color_data
clc
adc offset
sta $20
lda #>petscii_color_data
bcc !+
adc #1
!:
sta $21
lda #$c8+39
sta $22
lda #$d8
sta $23
jsr write_last_col
lda #state_1
sta scroll_state
rts
write_last_col:
ldx #0
ldy #0
!loop:
lda ($20), y
sta ($22), y
clc
lda $20
adc #logo_width
sta $20
bcc !+
inc $21
!:
clc
lda $22
adc #40
sta $22
bcc !+
inc $23
!:
inx
cpx #logo_height
bmi !loop-
rts
clear_screen:
ldx #screen_bg_color
stx $d021 // write to screen color register
ldx #$00 // start of loop
stx $d020 // write to border color register
clear_loop:
lda #$20 // #$20 is the spacebar screencode
sta screen_ram, x // fill four areas with 256 spacebar characters
sta screen_ram + $100,x
sta screen_ram + $200,x
sta screen_ram + $300,x
lda #$0c // puts into the associated color ram dark grey ($0c)...
sta $d800,x // and this will become color of the scroll text
sta $d900,x
sta $da00,x
sta $dae8,x
inx
bne clear_loop
rts
draw_logo:
lda #<petscii_data
sta $20
lda #>petscii_data
sta $21
lda #$c8 // fila 5
sta $22
lda #$04
sta $23
jsr copydata
lda #<petscii_color_data
sta $20
lda #>petscii_color_data
sta $21
lda #$c8
sta $22
lda #$d8
sta $23
jsr copydata
rts
copydata:
ldx #0
copydata2:
ldy #0
!loop:
lda ($20), y
sta ($22), y
iny
cpy #40
bmi !loop-
clc
lda $20
adc #logo_width
sta $20
bcc !+
inc $21
!:
clc
lda $22
adc #40
sta $22
bcc !+
inc $23
!:
inx
cpx #logo_height
bmi copydata2
rts
scroll_screen_left:
ldx #0
!loop:
.for(var x=5;x<5+logo_height;x++) {
lda screen_ram + x*40 + 1, x
sta screen_ram + x*40, x
lda color_ram + x*40 + 1, x
sta color_ram + x*40, x
}
inx
cpx #39
bpl !+
jmp !loop-
!:
rts
//============================================================
// SID
//============================================================
.pc = music.location "Music"
.fill music.size, music.getData(i)
.print "SID Data"
.print "--------"
.print "location=$"+toHexString(music.location)
.print "init=$"+toHexString(music.init)
.print "play=$"+toHexString(music.play)
.print "songs="+music.songs
.print "startSong="+music.startSong
.print "size=$"+toHexString(music.size)
.print "name="+music.name
.print "author="+music.author
.print "copyright="+music.copyright
.print ""
.print "Additional tech data"
.print "--------------------"
.print "header="+music.header
.print "header version="+music.version
.print "flags="+toBinaryString(music.flags)
.print "speed="+toBinaryString(music.speed)
.print "startpage="+music.startpage
.print "pagelength="+music.pagelength
//============================================================
// PETSCII DATA
//============================================================
petscii_data:
.pc = * "PETSCII char"
.fill intro_data.getSize(), intro_data.get(i)
petscii_color_data:
.pc = * "PETSCII color"
.fill intro_data_color.getSize(), intro_data_color.get(i)
// vim: se ft=kickass:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment