prog8/examples/c64/starfield.p8

164 lines
5.0 KiB
Lua

; Galencia starfield ported to Prog8. Original: https://github.com/JasonAldred/C64-Starfield
; This is for the C64 only.
%option no_sysinit
main {
const uword starScreenChar = $0400 ; Screen address
const uword StarScreenCols = $d800 ; Character attribute address
const uword charBase = $3000 ; Address of our character set
const uword star1Init = charBase+$1d0 ; Init address for each star
const uword star2Init = charBase+$298
const uword star3Init = charBase+$240
const uword star4Init = charBase+$2e0
const uword star1Limit = charBase+$298 ; Limit for each star
const uword star2Limit = charBase+$360 ; Once limit is reached, they are reset
const uword star3Limit = charBase+$298
const uword star4Limit = charBase+$360
const uword star1Reset = charBase+$1d0 ; Reset address for each star
const uword star2Reset = charBase+$298
const uword star3Reset = charBase+$1d0
const uword star4Reset = charBase+$298
const uword staticStar1 = charBase+$250 ; 2 Locations for blinking static stars
const uword staticStar2 = charBase+$1e0
const ubyte starColourLimit = 20 ; use values 1 to 20
; Galencia uses these values
; 1 = mono
; 2 = duo
; 20 = full colour
; 4 x pointers for moving stars
uword @zp starfieldPtr1
uword @zp starfieldPtr2
uword @zp starfieldPtr3
uword @zp starfieldPtr4
ubyte rasterCount ; Counter that increments each frame
sub start () {
sys.set_irqd()
sys.memset(charBase, 8*256, 0) ; clear charset data
c64.EXTCOL = 0
c64.BGCOL0 = 0
c64.VMCSB = (charBase/1024) | %00010000 ; Characters at $3000
initStarfield()
createStarScreen()
repeat {
sys.waitvsync()
rasterCount ++
doStarfield()
}
}
sub doStarfield() {
; This routine does 3 things:
; 1) Erases stars
; 2) Moves stars
; 3) Draws stars in new position
@(starfieldPtr1) = 0
@(starfieldPtr2) = 0
@(starfieldPtr3) = 0
@(starfieldPtr4) = 0
if rasterCount & 1 !=0 {
starfieldPtr1++
if starfieldPtr1==star1Limit
starfieldPtr1=star1Reset
}
starfieldPtr2++
if starfieldPtr2==star2Limit
starfieldPtr2=star2Reset
if rasterCount & 3 == 0 {
starfieldPtr3++
if starfieldPtr3==star3Limit
starfieldPtr3=star3Reset
}
starfieldPtr4 += 2
if starfieldPtr4==star4Limit
starfieldPtr4=star4Reset
; 2 static stars that flicker
if rasterCount >= 230
@(staticStar1) = 0
else
@(staticStar1) = 192
if rasterCount ^ $80 >= 230
@(staticStar2) = 0
else
@(staticStar2) = 192
; Plot new stars
@(starfieldPtr1) |= 3
@(starfieldPtr2) |= 3
@(starfieldPtr3) |= 12
@(starfieldPtr4) |= 48
}
sub initStarfield() {
starfieldPtr1 = star1Init
starfieldPtr2 = star2Init
starfieldPtr3 = star3Init
starfieldPtr4 = star4Init
}
sub createStarScreen() {
; Creates the starfield charmap and colour charmap
; This routine paints vertical stripes of colour into the colourmap
; so the stars are different colours
; It also plots the correct characters to the screen, wrapping them around
; at the correct char count to give to the starfield effect.
uword @zp ptr
ubyte x
for x in 0 to 39 {
ubyte limit
ubyte char = starfieldRow[x]
if char >= 58+25
limit = 58+50
else
limit = 58+25
ubyte start = limit - 25
ptr = starScreenChar
repeat 25 {
ptr[x] = char
ptr += 40
char ++
if char == limit
char = start
}
}
; Fill colour map with vertical stripes of colour for starfield
ptr = StarScreenCols
ubyte ci = 0
repeat 25 {
for x in 0 to 39 {
ptr[x] = starfieldCols[ci]
ci ++
if ci==starColourLimit
ci=0
}
ptr += 40
}
}
; Dark starfield so it doesnt distract from bullets and text
ubyte[20] starfieldCols = [
14,10,12,15,14,13,12,11,10,14,
14,10,14,15,14,13,12,11,10,12
]
; Star positions, 40 X positions, range 58-107
ubyte[40] starfieldRow = [
058,092,073,064,091,062,093,081,066,094,
086,059,079,087,080,071,076,067,082,095,
100,078,099,060,075,063,084,065,083,096,
068,088,074,061,090,098,085,101,097,077
]
}