1 ;----------------------------------------------------------
  2 ; badass -- C64 Example source
  3 ; Koala screen, animated sprite and music
  4 ; sasq - 2020
  5 ;----------------------------------------------------------
  6 !script "../lua/sid.lua"
  7 
  8 ; Set the 16k VIC area. Can only point
  9 ; to $0000, $4000, $8000 or $c000
 10 !macro VicAdr(adr) {
 11     !assert (adr & $3fff) == 0
 12     lda #((~adr)&$ffff)>>14
 13     sta $dd00
 14 }
 15 
 16 ; Set the Bitmap and Screen offsets within VIC
 17 !macro BitmapAndScreen(bm_offs, scr_offs) {
 18     !assert (bm_offs & $dfff) == 0
 19     !assert (scr_offs & $c3ff) == 0
 20     .bits0 = (bm_offs>>10)
 21     .bits1 = (scr_offs>>6)
 22     lda #.bits0 | .bits1
 23     sta $d018
 24 }
 25 
 26 ; Silly short hand macros
 27 !macro ldxy(v) {
 28     ldx v
 29     ldy v+1
 30 }
 31 
 32 !macro stxy(v) {
 33     stx v
 34     sty v+1
 35 }
 36 
 37 ; Koala offsets
 38 !enum Koala {
 39     bitmap = $2
 40     screen = $1f42
 41     colors = $232a
 42     bg = $2712
 43     end = $2713
 44 }
 45 
 46 musicLocation = $1000
 47 
 48 screenMem = $6000
 49 bitmapMem = $4000
 50 spriteMem = $7000
 51 spritePtrs = screenMem + 1016
 52 
 53     !section "test", $c000
 54 
 55     !section "main", $801
 56     !byte $0b,$08,$01,$00,$9e,str(start),$00,$00,$00
 57 start:
 58 
 59     sei
 60 
 61     ; Copy colors and screen data
 62     ldx #$00
 63 $   lda colors,x
 64     sta $d800,x
 65     lda colors+$100,x
 66     sta $d900,x
 67     lda colors+$200,x
 68     sta $da00,x
 69     lda colors+$2e8,x
 70     sta $dae8,x
 71 
 72     !if screen != screenMem {
 73         lda screen,x
 74         sta screenMem,x
 75         lda screen+$100,x
 76         sta screenMem+$100,x
 77         lda screen+$200,x
 78         sta screenMem+$200,x
 79         lda screen+$2e8,x
 80         sta screenMem+$2E8,x
 81     }
 82     inx
 83     bne -
 84 
 85     VicAdr($4000)
 86     BitmapAndScreen(bitmapMem-$4000, screenMem-$4000)
 87 
 88     jsr init_sprite
 89 
 90     lda #$18
 91     sta $d016
 92 
 93     lda #$3b
 94     sta $d011
 95 
 96     lda #bg_color
 97     sta $d020
 98     sta $d021
 99 
100     jsr $1000
101 
102 $   lda #100
103     cmp $d012
104     bne -
105     lda #4
106     sta $d020
107     jsr $1003
108     lda #bg_color
109     sta $d020
110     jsr update_sprite
111     jmp -
112 
113 
114 test_func:
115     brk #2
116     rts
117 
118 !test my_test {
119     jsr test_func
120 }
121 
122 init_sprite
123     ; Enable sprite 2
124     lda #$04
125     sta $d015
126 
127     ; Set sprite 2 pointer
128     lda #(spriteMem-$4000)/64
129     sta spritePtrs+2
130 
131     ; Copy sprite data
132     !rept 8 {
133         ldx #3*21
134     $:  lda spriteData-1+i*64,x
135         sta spriteMem-1+i*64,x
136         dex
137         bne -
138     }
139     rts
140 
141 update_sprite
142     ldxy xy
143     lda sine_xy,x
144     inx
145     sta $d004    ; Sprite position x++
146     lda sine_xy,y
147     iny
148     iny
149     sta $d005    ; Sprite position y++
150 
151     stxy xy
152 
153     lda sine_frame,x
154     adc #(spriteMem-$4000)/64
155 
156     sta spritePtrs+2
157     rts
158 
159 xy: !byte 0,0
160 
161 sine_xy:
162     !rept 256 { !byte (sin(i*Math.Pi*2/256)+1) * 100 + 24 }
163 
164 sine_frame:
165     !rept 256 { !byte (sin(i*Math.Pi*2/96)+1) * 3.5 }
166 
167 %{
168 
169 function setPixel(target, width, x, y)
170     offs = width * y + (x>>3) + 1 -- 1-Indexed arrays :(
171     if offs >=1 and offs <= #target then
172         target[offs] = target[offs] | 1<<(7-(x&7))
173     end
174 end
175 
176 function circle(target, width, xp, yp, radius)
177     r = math.floor(radius + 0.5)
178     for y=-r,r, 1 do
179         for x=-r,r, 1 do
180             if x*x+y*y <= r*r then
181                 setPixel(target, width, xp+x, yp+y)
182             end
183         end
184     end
185     return target
186 end
187 
188 }%
189 
190 spriteData:
191     !rept 8 {
192         !fill circle(zeroes(3*21), 3, 12, 10, i + 3)
193         !byte $ff
194     }
195 
196     ; Koala Image
197 
198     koala = load("../data/oys.koa")
199     bitmap = koala[Koala.bitmap : Koala.screen]
200     screen_ram = koala[Koala.screen : Koala.colors]
201     color_ram = koala[Koala.colors : Koala.bg]
202     bg_color = koala[Koala.bg]
203 
204     ; Music
205 
206     !define swap(x) { (x>>8) | (x<<8) }
207 
208     sid = load("../data/test.sid")
209     music_init = swap(word(sid[$a:$c]))
210     music_play = swap(word(sid[$c:$e]))
211 
212     !assert music_init == musicLocation
213 
214     music_data = sid[$7e:]
215 
216     ; Data layout
217 
218     !section "music", musicLocation
219     !fill music_data
220 
221 colors:
222     !fill color_ram
223 
224 screen:
225     !fill screen_ram
226 
227     !section "koala", bitmapMem
228     !fill bitmap