├── Linux.zip ├── starfield.prg ├── README.md └── starfield.asm /Linux.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jimmy2x2x/C64-Starfield/HEAD/Linux.zip -------------------------------------------------------------------------------- /starfield.prg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jimmy2x2x/C64-Starfield/HEAD/starfield.prg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C64-Starfield 2 | Starfield from Galencia 3 | 4 | This is 6510 asm for the Commodore 64 computer 5 | 6 | It is the code from my 2017 game Galencia and will explain the vertical parallax starfield 7 | -------------------------------------------------------------------------------- /starfield.asm: -------------------------------------------------------------------------------- 1 | ; [WELCOME] ------------------------------------------------------------------- 2 | 3 | ; Starfield example code 4 | 5 | ; This code has been extracted from my 2017 Commodore 64 game 'Galencia' 6 | ; and this portion of the code is placed in the public domain 10 December 2017 7 | ; feel free to use this code for any purpose with the exception of reproducing 8 | ; this tutorial, in part or whole, in a magazine, diskmag, website or similar. 9 | ; If you want to do this, please email me and ask for permission prior to 10 | ; publication. 11 | 12 | ; I have spent a few hours making this code as easy to understand as I can 13 | ; with heavy comments and everything defined to be as portable as possible. 14 | 15 | ; If you find this code useful and would like to see more like this 16 | ; you can buy me a beer via the magic of paypal ;) 17 | 18 | ; my paypal: jay.aldred@gmail.com 19 | 20 | ; Cheers, Jay 21 | 22 | 23 | ; [DESCRIPTION] --------------------------------------------------------------- 24 | 25 | ; The starfield revolves around plotting pixels into a custom character set 26 | 27 | ; It works by reprogramming 50 characters in the charset. 28 | 29 | ; The screen is 25 chars tall and I use two columns worth of characters 30 | ; (2 x 25 = 50 chars) 31 | 32 | ; I have allocated characters 58 to 107 to be the 50 star characters 33 | ; as this fit around my needs in Galencia 34 | 35 | ; This code was assembled using: 36 | ; CBM prg Studio by Arthur Jordison http://www.ajordison.co.uk/ 37 | 38 | 39 | ; [EQUATES] ------------------------------------------------------------------- 40 | 41 | starScreenChar = $0400 ; Screen address 42 | StarScreenCols = $d800 ; Character attribute address 43 | 44 | charBase = $3000 ; Address of our character set 45 | 46 | star1Init = charBase+$1d0 ; Init address for each star 47 | star2Init = charBase+$298 48 | star3Init = charBase+$240 49 | star4Init = charBase+$2e0 50 | 51 | star1Limit = charBase+$298 ; Limit for each star 52 | star2Limit = charBase+$360 ; Once limit is reached, they are reset 53 | star3Limit = charBase+$298 54 | star4Limit = charBase+$360 55 | 56 | star1Reset = charBase+$1d0 ; Reset address for each star 57 | star2Reset = charBase+$298 58 | star3Reset = charBase+$1d0 59 | star4Reset = charBase+$298 60 | 61 | staticStar1 = charBase+$250 ; 2 Locations for blinking static stars 62 | staticStar2 = charBase+$1e0 63 | 64 | starColourLimit = 20 ; use values 1 to 20 65 | ; Galencia uses these values 66 | ; 1 = mono 67 | ; 2 = duo 68 | ; 20 = full colour 69 | 70 | ; [ZERO PAGE VARIABLES] ------------------------------------------------------- 71 | 72 | starfieldPtr = $f0 ; 4 x pointers for moving stars 73 | starfieldPtr2 = $f2 74 | starfieldPtr3 = $f4 75 | starfieldPtr4 = $f6 76 | 77 | zeroPointer = $f8 ; General purpose pointer 78 | 79 | rasterCount = $fa ; Counter that increments each frame 80 | 81 | 82 | ; [AUTO RUN] ------------------------------------------------------------------ 83 | 84 | ; These byte values are a basic SYS call to autoexecute the code. 85 | 86 | *=$0801 87 | 88 | BYTE $0E,$08,$0A,$00,$9E,$20,$28,$32,$30,$36,$34,$29,$00,$00,$00 89 | 90 | ; [CODE START] ---------------------------------------------------------------- 91 | 92 | *=$0810 93 | 94 | sei ; Disable all IRQ 95 | 96 | lda #charBase 99 | sta zeroPointer+1 100 | ldx #8-1 101 | ldy #0 102 | tya 103 | @clrChars 104 | sta (zeroPointer),y 105 | iny 106 | bne @clrChars 107 | inc zeroPointer+1 108 | dex 109 | bne @clrChars 110 | 111 | sta $d020 ; Border and screen colour to 0 (black) 112 | sta $d021 113 | 114 | lda #28 ; Characters at $3000 115 | sta $d018 116 | 117 | jsr initStarfield ; Reset all pointers 118 | jsr createStarScreen ; Initialise Starfield 119 | @loop 120 | 121 | lda #$ff ; Wait for raster to be off screen 122 | @wait 123 | cmp $d012 124 | bne @wait 125 | 126 | inc rasterCount ; Increment our 8 bit counter 127 | 128 | dec $d020 ; Change border colour to show 129 | ; how long routine is taking to 130 | ; execute 131 | 132 | jsr doStarfield ; erase, move and redraw the stars 133 | 134 | inc $d020 ; restore border colour 135 | 136 | jmp @loop ; Loop around for another pass 137 | 138 | 139 | ; [Do Starfield] -------------------------------------------------------------- 140 | 141 | ; This routine does 3 things: 142 | 143 | ; 1) Erases stars 144 | ; 2) Moves stars 145 | ; 3) Draws stars in new position 146 | 147 | 148 | doStarfield 149 | 150 | ; Erase stars 151 | 152 | lda #0 ; Erase 4 stars 153 | tay 154 | sta (starfieldPtr),y 155 | sta (starfieldPtr2),y 156 | sta (starfieldPtr3),y 157 | sta (starfieldPtr4),y 158 | 159 | ; Move star 1 160 | 161 | lda rasterCount ; Test bit 0 of counter 162 | and #1 ; move 1 pixel every 163 | beq @star1Done ; other frame, to simulate 164 | inc starfieldPtr ; 1/2 pixel movement 165 | bne @ok 166 | inc starfieldPtr+1 167 | @ok 168 | lda starfieldPtr 169 | cmp #star1Limit 173 | bne @star1Done 174 | lda #star1Reset 177 | sta starfieldPtr+1 178 | @star1Done 179 | 180 | ; Move star 2 181 | 182 | inc starfieldPtr2 ; 1 pixel per frame 183 | bne @ok2 184 | inc starfieldPtr2+1 185 | @ok2 186 | lda starfieldPtr2 187 | cmp #star2Limit 191 | bne @star2Done 192 | lda #star2Reset 195 | sta starfieldPtr2+1 196 | @star2Done 197 | 198 | ; Move star 3 199 | 200 | lda rasterCount ; half pixel per frame 201 | and #1 202 | beq @star3done 203 | inc starfieldPtr3 204 | bne @ok3 205 | inc starfieldPtr3+1 206 | @ok3 207 | lda starfieldPtr3 208 | cmp #star3Limit 212 | bne @star3done 213 | lda #star3Reset 216 | sta starfieldPtr3+1 217 | @star3done 218 | 219 | ; Move star 4 220 | 221 | lda starfieldPtr4 ; 2 pixels per frame 222 | clc 223 | adc #2 224 | sta starfieldPtr4 225 | bcc @ok4 226 | inc starfieldPtr4+1 227 | @ok4 228 | lda starfieldPtr4+1 229 | cmp #>star4Limit 230 | bne @star4done 231 | lda starfieldPtr4 232 | cmp #star4Reset 237 | sta starfieldPtr4+1 238 | @star4done 239 | 240 | ; 2 static stars that flicker 241 | 242 | lda #192 243 | ldy rasterCount 244 | cpy #230 245 | bcc @show 246 | lda #0 247 | @show sta staticStar1 248 | 249 | tya 250 | eor #$80 251 | tay 252 | lda #192 253 | cpy #230 254 | bcc @show2 255 | lda #0 256 | @show2 sta staticStar2 257 | 258 | ; Plot new stars 259 | 260 | ldy #0 261 | lda (starfieldPtr),y ; Moving stars dont overlap other stars 262 | ora #3 ; as they use non conflicting bit 263 | sta (starfieldPtr),y ; combinations 264 | 265 | lda (starfieldPtr2),y 266 | ora #3 267 | sta (starfieldPtr2),y 268 | 269 | lda (starfieldPtr3),y 270 | ora #12 271 | sta (starfieldPtr3),y 272 | 273 | lda (starfieldPtr4),y 274 | ora #48 275 | sta (starfieldPtr4),y 276 | 277 | rts 278 | 279 | 280 | ; [Initialise Starfield Pointers] --------------------------------------------- 281 | 282 | ; Initialise all pointers, note these INIT values maybe different to RESET 283 | ; values, this is give a non-uniform appearance to the stars and reduce 284 | ; obvious 'patterning' - I tried to give a fairly natural appearance. 285 | 286 | initStarfield 287 | lda #star1Init 290 | sta starfieldPtr+1 291 | 292 | lda #star2Init 295 | sta starfieldPtr2+1 296 | 297 | lda #star3Init 300 | sta starfieldPtr3+1 301 | 302 | lda #star4Init 305 | sta starfieldPtr4+1 306 | 307 | rts 308 | 309 | 310 | ; [Create Star Screen] -------------------------------------------------------- 311 | 312 | ; Creates the starfield charmap and colour charmap 313 | 314 | ; This routine paints vertical stripes of colour into the colourmap 315 | ; so the stars are different colours 316 | 317 | ; It also plots the correct characters to the screen, wrapping them around 318 | ; at the correct char count to give to the starfield effect. 319 | 320 | 321 | CreateStarScreen 322 | ldx #40-1 ; Create starfield of chars 323 | @lp txa 324 | pha 325 | tay 326 | lda StarfieldRow,x 327 | 328 | sta @smc1+1 329 | ldx #58+25 330 | cmp #58+25 331 | bcc @low 332 | ldx #58+50 333 | @low stx @smc3+1 334 | txa 335 | sec 336 | sbc #25 337 | sta @smc2+1 338 | lda #starScreenChar 341 | sta zeroPointer+1 342 | ldx #25-1 343 | @smc1 lda #3 344 | sta (zeropointer),y 345 | lda zeropointer 346 | clc 347 | adc #40 348 | sta zeropointer 349 | bcc @clr 350 | inc zeropointer+1 351 | @clr inc @smc1+1 352 | lda @smc1+1 353 | @smc3 cmp #0 354 | bne @onscreen 355 | @smc2 lda #0 356 | sta @smc1+1 357 | @onscreen 358 | dex 359 | bpl @smc1 360 | 361 | pla 362 | tax 363 | dex 364 | bpl @lp 365 | 366 | lda #StarScreenCols 369 | sta zeroPointer+1 370 | ldx #25-1 371 | @lp1 stx @smcx+1 372 | ldx #0 373 | ldy #40-1 374 | @lp2 375 | lda starfieldCols,x 376 | sta (zeroPointer),y 377 | inx 378 | cpx #StarColourLimit 379 | bne @col 380 | ldx #0 381 | @col 382 | dey 383 | bpl @lp2 384 | lda zeroPointer 385 | clc 386 | adc #40 387 | sta zeroPointer 388 | bcc @hiOk 389 | inc zeroPointer+1 390 | @hiOk 391 | @smcx 392 | ldx #0 393 | dex 394 | bpl @lp1 395 | rts 396 | 397 | 398 | ; [DATA] ---------------------------------------------------------------------- 399 | 400 | ; Dark starfield so it doesnt distract from bullets and text 401 | starfieldCols 402 | 403 | byte 14,10,12,15,14,13,12,11,10,14 404 | byte 14,10,14,15,14,13,12,11,10,12 405 | 406 | ; Star positions, 40 X positions, range 58-107 407 | starfieldRow 408 | byte 058,092,073,064,091,062,093,081,066,094 409 | byte 086,059,079,087,080,071,076,067,082,095 410 | byte 100,078,099,060,075,063,084,065,083,096 411 | byte 068,088,074,061,090,098,085,101,097,077 412 | 413 | 414 | 415 | --------------------------------------------------------------------------------