rem ------------------------------------------------------ rem --Atari 2600 Video Game Program --- rem ------------------------------------------------------ rem --SuperCharger Space Space Invaders! 9/1/2017 --- rem ------------------------------------------------------ rem --FLASHBACK BASIC and SUPERCHARGER BASIC compatible -- rem ------------------------------------------------------ rem --This game uses display Lists like the A8! ---- rem --Alpha builds 1-4 cross-compiled OK ---- rem --9/11/2017 Beta 1 compiles for the AFP (Flashback BASIC) but will need to be rem --crunched in order to compile under SuperCharger BASIC: rem --SuperCharger BASIC has 4K free to BASIC while Flashback BASIC has 5K, like a VIC-20 :) rem --9/21/2017 Beta 4; needed to swap u & s CAM X axis, on level 2 for the Criss-Cross pattern rem --12/2/2018 Atari Flashback 9 HDMI Model hotfix added rem ------------------------------------------------------ rem ----------------------------------------- rem ---init section, runs once: ------------- rem ----------------------------------------- " cld; 20181202 Atari Flashback Hotfix (virtual 6502 always boots in decmimal mode)" initscore score=0 grabinit rem -------------variables-------------------------------------- rem v offset for invaders to descend rem t and z are variable toggles, w is counter toggle rem -- r used to control what direction (back or forth) for one DLI rem -- q used to control back/forth dir for the other DLI full of Invaders! rem -- w used to control skill level (1=30 FPS Animation of Invaders, 2=15 FPS, 60 HZ all) rem u and s are the CAM x axis for the bottom/top DLI's full of space invaders! rem p player (Vaus ship against Space Invaders) x axis, inits at 10, middle rem virtualworld(18), virtualworld(19) double Vaus Cannon x,y coordinates rem f vaus cannons fired rem -- i,j,k,l - reusable temp vars rem g lap counter, descends every 4 laps? rem virtualworld 18 & 19 twin missile launch x,y coordinates rem XXX unused: virtualworld 20 & 21 target missle 1 coordinates rem virtualworld 22 missle 1 locked? rem virtualworld 23 & 24 target missle 2 coordinates rem virtualworld 25 missle 2 locked? rem score,px,py,bx,by free -----------! rem virtualworld 40,41,42,43,44,45,46,47 free! rem x,y robot1Missile x,y rem h,m robot2missile x,y rem n,o robot3missile x,y rem virtualworld 20,21,32,33 x,y and seek x,y for robot1 rem virtualworld 28,29,30,31 x,y and seek x,y for robot2 rem virtualworld 34,35,36,37 x,y and seek x,y for robot3 rem virtualworld 38,39 robot 4 x,y coordinates rem var1,var2 robot4missle x,y rem --------------------------------------------------------------- e=0: rem fleet count rem MUSICINDEX=10 loadplayer1(0):loadplayer0(8):t=0:BYTErowoffset=120 rem doublewide NUSIZ1=$05 rem -- set color palette registers (occupy top 1.5 rows of virtual world) v=0: rem controls descent of DLI filled space invaders! p=10 rem set byterowoffset... rem option to reverse dir drawboard rem --clear virtualworld for j=0 to 239:virtualworld(j)=0:next j for j=0 to 9:i=10*j:i=i+40:j=j-1:rowcolors(j) = i if j<8 then player0colors(j)=i+4 next j rem ----draw board, 1st 3 rows is 2,3,4, next 3 are 5,6,7 for y= 3 to 11 step 2 for x = 14 to 76 step 5 vwpixel(x,y,on) next x,y for y= 4 to 10 step 2 for x = 17 to 77 step 5 vwpixel(x,y,on) next x,y rem draw Vaus: vwpixel(10,19,on):vwpixel(11,19,on) rowcolors(8)=$cc:color Vaus rowcolors(9)=0 scrollvirtualworldtoggle=1 BITIndex=0 BYTErowoffset=120:rem move cam one screen down rem gosub reversi:rem do this if reset on start? ;) rem return rem define robot x,y coordinates: rem rem virtualworld(20)=39:virtualworld(21)=8:rem x,y for robot1 rem virtualworld(32)=0:virtualworld(33)=0: rem redundant clearing of robot1 x,y seek rem rem virtualworld(28)=34:virtualworld(29)=8:rem x,y for robot2 rem virtualworld(30)=0:virtualworld(31)=0: rem redundant clearing of robot2 x,y seek rem rem virtualworld(34)=44:virtualworld(35)=8: rem x,y for robot3 rem virtualworld(36)=0:virtualworld(37)=0: rem clearing of robot3 x,y seek rem rem virtualworld(38)=55:virtualworld(39)=7: rem x,y for robot4 rem rem y=0:m=0:o=0:var1=0:rem clear robot 1-4's missile x coordinates return reversi s=71:q=1:u=0:r=0 rem ------------------------------------------------ rem end init section (implicit return)-------------- rem ------------------------------------------------ rem ------------------------------------------------ rem ---:the next comment line is used by the compiler rem ---gameloop subroutine, runs every frame: --- rem ------------------------------------------------ rem -- 20190420 musical soundshower SID inspired enhancement from GATECREASHER Demo! rem -- bx and by used (and px and py still are free), so: rem add it TODO >done ------------------------------------------------------ rem -- is score score? yes, 1 based... rem -- Ramp up game difficulty and create new AI musical themes: rem if score<2 then by=27 else by=10:rem medium, new music AI theme from the algorythm rem if score<2 then by=22 else by=16:rem medium, new music AI theme from the algorythm if score<2 then by=16 else by=11:rem medium, new music AI theme from the algorythm rem if score=1 then by=18:rem hard, new music AI theme from the algorythm rem if score=2 then by=14:rem really hard rem if score>2 then by=10:rem experts only! rem vaus hit? if missile0y=5 then i=missile0x:gosub checkvaus rem - bug: one call needed to be relocated above... OK, both before anything happens. if missile1y=5 then i=missile1x:gosub checkvaus if t=0 then goto runloop1:rem deactivated DLI! : BYTErowoffset=120:scrollvirtualworldtoggle=35:gosub DLI: scrollvirtualworldtoggle=0:return: rem run this DLI every other frame rem -- otherwise... rem 20190420 continued, musical soundshower: rem if bx>by then bx=0:SUSTAINFORFRAMES=9:AUDC0=0 else bx=bx+1 if bx>by then bx=0:SUSTAINFORFRAMES=18:AUDC0=0 else bx=bx+1 rem --- cool code for relative vertical panning with a DLI CAM view (was combined with another DLI in the other vertical blanks gameloop) rem if t=1 then BYTErowoffset=v*12:h=BITIndex:BITIndex=u:vwpixel(29,5,bindplayer1):scrollvirtualworldtoggle=30:gosub DLI:BITIndex=h:BYTErowoffset=120 rem return rem -- it is: if t=1 then if w<>0 then goto wnot3a : rem should match reset used for combined DLI call in bottom blank if q<>0 then goto qnot0 if s<71 then s=s+1 else q=1 if s=71 then g=g+1:rem increment lap if v=4 then COLUBK=$32 goto qnot1 qnot0 if s<>0 then s=s-1 else q=0:rem was 0 qnot1 j=virtualworld(21)+v:j=j-3:i=virtualworld(20):rem j=5+v rem 20170921 BUG - h was getting reused, it is a robots missle coordinate! rem h=BITIndex k=BITIndex:BITIndex=s BYTErowoffset=36:vwpixel(i,j,bindplayer1) rem ----launch robot missile 1 if visible rem *** speedbump, move it? if y>0 then missile1x=x:missile1y=y else missile1x=0:missile1y=0 i=v*12 BYTErowoffset=36-i rem timing fix, 3 row display list: COLUP1=150:scrollvirtualworldtoggle=30+v:gosub DLI: COLUP1=150:scrollvirtualworldtoggle=1+v:gosub DLI: rem display list is now two rows (gets combined with 3 from the other vertical blank) rem BITIndex=h BITIndex=k BYTErowoffset=120 wnot3a scrollvirtualworldtoggle=0 return runloop1 rem if player1x>0 and y=0 then x=player1x:y=player1y:missile1x=x:missile1y=y:goto done_missile_1 if player1x>15 and y=0 then x=player1x:y=player1y:rem missile1x=x:missile1y=y:rem goto done_missile_1 done_missile_1 rem multiplex second player 1 instance rem j=8+v COLUP1=255 rem i=v*12:BYTErowoffset=36-i rem h=BITIndex k=BITIndex:BITIndex=s BYTErowoffset=72 j=virtualworld(29)+v:i=virtualworld(28) vwpixel(i,j,bindplayer1):BITIndex=h:BYTErowoffset=120 BITIndex=k:rem new - another missile bug 20170921 if y=0 and player1x>7 then h=player1x:m=player1y:rem trading this opt for more space... missile1x=h:missile1y=m:goto done_missile_2 rem ----launch robot missile 1 if visible if m>0 then missile1x=h:missile1y=m else missile1x=0:missile1y=0 done_missile_2 if f=0 then goto donecannons: rem cannons............... docannons rem Hit a space invader? if virtualworld(22)=1 then j=virtualworld(23):i=virtualworld(24):vwpixel(i,j,flip) rem 2nd cannon hit a space invader? if virtualworld(25)=1 then j=virtualworld(26):i=virtualworld(27):vwpixel(i,j,flip) rowcolors(8)=$cc:i=virtualworld(18):j=virtualworld(19):rem j init's at 18, above paddle rem clear previous? (alternately create a laser/blowup sound): if j<>18 and virtualworld(22)=0 and virtualworld(25)=0 then f=0:goto donecannons rem 20170907 DEBUG, K=14+v, not 15+v! that is why rockets froze one line early, they should freeze when invaders reach them. k=14+v:rem check for start of dynamic offset, if rockets entered the DLI bands... rem 20170907 DEBUG -- ...removed it... leaving in 11+v... not sure if it is necessary...? something else is blocking missle launching when blocks are at 18, just above the paddle if j=k then j=11: rem i=u+i:rem jump to start of dli zones if j>11 then goto notinzone rem ---- patch criss-cross pattern here, cannons must switch from u to s offset for the two DLI cam's since they are no longer synced on level 2 (criss-cross) rem i=u+i:rem old code didn't show on top DLI (missing fluid crossover) 20170921 if j>5 then i=u+i else i=s+i:rem ---- use DLI cam's x index if r=1 then i=i-1 else i=i+1 notinzone rem if j ... todo... if virtualworld(22)=0 and j<>18 then goto skipm1 rem if vwpixel(i,j,flip)<>0 then gosub robotfindskitten:e=e+1:virtualworld(22)=0:AUDC0=8:AUDF0=player0y:SUSTAINFORFRAMES=9 else virtualworld(22)=1:virtualworld(23)=j:virtualworld(24)=i:rem block invader destroyed if vwpixel(i,j,flip)<>0 then gosub robotfindskitten:e=e+1:virtualworld(22)=0:AUDC0=8:AUDF0=player0y:SUSTAINFORFRAMES=9 else virtualworld(22)=1:virtualworld(23)=j:virtualworld(24)=i:rem block invader destroyed skipm1 if virtualworld(25)=0 and j<>18 then goto skipm2 i=i+1 if vwpixel(i,j,flip)<>0 then gosub robotfindskitten:e=e+1:virtualworld(25)=0:AUDC0=8:AUDF1=player1y:SUSTAINFORFRAMES=9 else virtualworld(25)=1:virtualworld(26)=j:virtualworld(27)=i:rem block invader destroyed skipm2 virtualworld(19)=j-1 donecannons return rem savespace1 if vwpixel(i,j,flip)<>0 then gosub robotfindskitten:e=e+1:virtualworld(px)=0:AUDC0=px/6:AUDF0=3:SUSTAINFORFRAMES=9 else virtualworld(px)=1:px=px+1:virtualworld(px)=j:px=px+1:virtualworld(px)=i:rem block invader destroyed return robotfindskitten rem ------ next free robot finds destroyed block rem FIFO QUEUE: check if robots are available and assign target: if virtualworld(32)=0 then virtualworld(32)=i:virtualworld(33)=j:return:rem robot1 assigned if virtualworld(30)=0 then virtualworld(30)=i:virtualworld(31)=j:return:rem robot2 assigned if virtualworld(36)=0 then virtualworld(36)=i:virtualworld(37)=j:return:rem robot3 assigned rem return:rem --- end robotfindskitten rem ------------------------------------------------------------- rem end game loop (implicit return)----------------- rem ------------------------------------------------------------- rem /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - TOP/BOTTOM VERTICAL BLANK DIVIDER! rem ------------------------------------------------------------- rem ---gameloop2 subroutine, runs every frame: -- rem ------------------------------------------------ rem ------------------------------------------------ rem ------------------------------------------------ t=1-t rem -- run this DLI if toggle t is 0:, horizontal slide, swaps x as bitindex and puts bintindex back... if t=0 then goto runloop2:rem freeing this DLI, add load!: rem z=1-z:return:x=x-z:BYTErowoffset=120:h=BITIndex:BITIndex=x:scrollvirtualworldtoggle=8:gosub DLI:scrollvirtualworldtoggle=0:BITIndex=h:return else COLUPF=100 rem -- otherwise run this DLI: rem byterowoffset is 120 for 1st DL w=w+1 if w<>1 then goto wnot3 if r<>0 then goto rnot0 if u<71 then u=u+1 else r=1 goto rnot1 rnot0 if u<>0 then u=u-1 else r=0 rnot1 rem j=7+v j=virtualworld(35)+v:j=j-0:i=virtualworld(34) k=BITIndex:BITIndex=u:w=0:BYTErowoffset=72:vwpixel(i,j,bindplayer0) rem BITIndex=k:rem new again 20170921....check below on dli call, k is reassigned to BITIndex if player0x>23 and o=0 then n=player0x:o=player0y:missile0x=n:missile0y=o:goto done_missile_3 rem ----launch robot missile 3 if visible if o>0 then missile0x=n:missile0y=o else missile0x=0:missile0y=0 done_missile_3 i=12*v:BYTErowoffset=BYTErowoffset-i:scrollvirtualworldtoggle=33+v:gosub DLI:scrollvirtualworldtoggle=0:BITIndex=k:return wnot3 return runloop2 if virtualworld(36)=0 then goto skip_assign_robot3 if virtualworld(34)=virtualworld(36) and virtualworld(35)=virtualworld(37) then virtualworld(36)=0:goto skip_assign_robot3 if virtualworld(34)virtualworld(36) then virtualworld(34)=virtualworld(34)-1 if virtualworld(35)virtualworld(37) then virtualworld(35)=virtualworld(35)-1 skip_assign_robot3 if virtualworld(32)=0 then goto skip_assign_robot1 if virtualworld(20)=virtualworld(32) and virtualworld(21)=virtualworld(33) then virtualworld(32)=0:goto skip_assign_robot1 if virtualworld(20)virtualworld(32) then virtualworld(20)=virtualworld(20)-1 if virtualworld(21)virtualworld(33) then virtualworld(21)=virtualworld(21)-1 skip_assign_robot1 if virtualworld(30)=0 then goto skip_assign_robot2 if virtualworld(28)=virtualworld(30) and virtualworld(29)=virtualworld(31) then virtualworld(30)=0:goto skip_assign_robot2 if virtualworld(28)virtualworld(30) then virtualworld(28)=virtualworld(28)-1 if virtualworld(29)virtualworld(31) then virtualworld(29)=virtualworld(29)-1 skip_assign_robot2 rem move or clear robot missiles if y>0 then y=y-1 if m>0 then m=m-1 if o>0 then o=o-1 if var2>0 then var2=var2-1 z=1-z rem rem space saving!!!! rem fix! -------------------------- flip animate Robots: rem rem 20170921 add this back .... if z=1 then REFP0=0:REFP1=0 else REFP0=255:REFP1=255 rem flip player1, player0 if z=1! else flip 'em back: j=virtualworld(39)+v:i=virtualworld(38): rem j=6+v k=BITIndex:BITIndex=u:w=0:BYTErowoffset=72 vwpixel(i,j,bindplayer0):rem multiplexed sprite (2nd 0) init with game logic... if var2=0 and player0x>25 then var1=player0x:var2=player0y if var2>0 then missile0x=var1:missile0y=var2 done_missile_4 rem rem rem i=v*12:BYTErowoffset=BYTErowoffset-i rem BITIndex=h BITIndex=k rem move vaus: BYTErowoffset=120 rem if z=0 then goto slowervaus if joy0left=1 and p>0 then p=p+1:vwpixel(p,19,flip):p=p-2:vwpixel(p,19,on):goto notmovingright rem if joy0right=1 and p<18 then vwpixel(p,19,flip):p=p+2:vwpixel(p,19,on):p=p-1 if joy0right=0 then goto notmovingright if p>17 then goto notmovingright vwpixel(p,19,flip) p=p+2 vwpixel(p,19,on) p=p-1 notmovingright rem return slowervaus rem virtualworld(8)=$cc if joy0fire=1 and f=0 then f=1:virtualworld(18)=p:virtualworld(19)=18: rem the other vertical blank code pics this up. rem check reset: if SWCHB|%11111110<>255 then gosub initscore if g<5 then return invadersdescend g=0:v=v+1:scrollvirtualworldtoggle=1:rem invaders descend rem push coloring down: j=8-v for i=j to 0 step -1 k=i-1 if i=0 then rowcolors(i)=rowcolors(9) else rowcolors(i)=rowcolors(k) next i score=score+1 rem if e>69+score then gosub grabinit:gosub reversi:MUSICINDEX=125:rem --- next level has reversal pattern! if e>69+score then gosub grabinit:gosub reversi:rem MUSICINDEX=125:rem 20190420 OM? --- next level has reversal pattern! rem ??? if v=1 then rowcolors(9)=0 else i=v-2:rowcolors(i)=0 return checkvaus rem --------------------20190421 Single ship hit will now end/resets game j=p+1:j=j*8:k=j+25 rem j=p*8:k=j+25 if i>=j and i