 rem ---------------------------------------------------------
 rem ---Ring Raiders C64 Atari 2600 SuperCharger BASIC program 
 rem ---Protect the 9 Rings of Saturn with Photon Torpedoes & Rainbows 
 rem ---Star Raiders and Star Ship genre
 rem ----------------------------------------------------------------------------------
 rem --- 20250131 Replaced twingling stars with dancing Stars on the tennuous stages
 rem --- 20250131 Added light twinkling starfields to tennuous ring stages
 rem --- 20250131 Added C64 texture mapping enhancements to RC8:
 rem --- 1. Parallex meteor starfield vanishes on tennuous Ring stages (too busy)
 rem --- 2. Dynamic Ring formations emerge. This is a nice Fx.
 rem --- 20250129 backporting RC8 enhancements from Atari 2600 release
 rem --- 20241019 Added twinkling stars and stars moving Fx behind Rings
 rem --- 20241019 Color coded TIE Fighter class status indicator 
 rem --- 20241012 Added 3D TIE Fighter 
 rem --- Hi score timer persist hi score every 5 minutes if current hi exceeded....
 rem --- 29241010 Patched Tracker module to return to main SID tune after edit
 rem --- 20241007 RC5 reset MUSICINDEX to zero when exiting Editor (minor)
 rem --- 20241003 RC4 add the ability to display and edit pattern [freeze display hear sound Tx]
 rem --- 20241002 SIDFx try changing SID4,SID5,SID6 arrays ... test dynamic instrument revision...
 rem --- 20241002 RC3 increase speed on warp (always fast forward)...
 rem --- 20240921 added photon torpedeoes to 3d cube cargo ship too 
 rem --- and increased challenge for missed photon torpedoes...
 rem ---20240920 added explosion when Saucer or 3D cube are hit (4 frames...)
 rem    and when Saucher or 3D cube impact the Ring (ring pieces in explosion)
 rem ---20240920 Saucer shoots Photo Torpedeo at player if above horizon or close (alt w/sidewinder)
 rem ---no harm to player if Torpedeo is dodged...
 rem ---20240919 adding horizontal drift to 3D objects (testing optimization)
 rem ---20240918 tuned relative spatial movement coordinate geometry for 3D floating Fx 
 rem ---20240911 horizon expansion demo b, multicolor frontier 
 rem ---(scale sprites across 3 expanding color illusion zones like Rainbow Walker!)
 rem ---20240903 Last Star Fighter 3D / 2.5D expanding rings like Buck Rogers/Solaris perspective
 rem ---20240830 inspiration from Star Raiders cover art showing Saturns Rings.

 rem ------------------------------------------------------
 rem ---Tracker script programmable demo in the game:    --
 rem ------------------------------------------------------
 rem ---Holding the Button long enough loads a new SID 
 rem ---moving stick in 4 directions plays chords or subtunes  
 rem ---when held or released, main tune resumes after.
 rem ---New Tracker controls:
 rem ---shift-lock or holding left shift = Space Waltz mode 
 rem ---left shift + left = new SID using algoritm 2
 rem ---left shift + right = Starts Tracker Editor 
 rem ---left shift + up/down = algorithms revise SID instrument array (Tracker has 39 instruments)  
 rem ------------------------------------------------------
 rem --- sid 21/31 ring 5 nice combination...
 rem ----------------------------------------------------------------------------------
 rem -- variable map
 rem -- p color seed var (excludes 0, background color black)
 rem -- q,r temp vars used by color routines
 rem -- m delay counter (in frames) to call palette switching routine
 rem -- t alt frame toggle (0,1)
 rem -- n Fx for palette switching (0 color chaser, 1 red & blue, 2, b&w greyscale, etc)
 rem -- x,y,z,w,v screamer x,y,pos index,sprite animation,player0/missile0 size bitmask 
 rem -- f counter for next SID (130 frames button held)
 rem -- e,h sidewinder weapon x,y
 rem -- g = Photo Torpedo, missle1 in action and used in rebuidmusic levelup (repos missile)
 rem -- s - 1 up slow, 2 down slow (when stick is not engaged)
 rem -- l Rainbow Rings frames delay duration
 rem -- o holds n index
 rem -- k enemy weapon toggle (alternates) sidewider or Saucers Photon Torpedeo 
 rem -- i,j saucer and 3d cube explosion state (0 no explosion), i is reused in rebuildmusic
 rem ---u extra saucer or cube attack
 rem ---var1 used to hook left shift/shift-lock/bwcolor & and stick up/down to Tx instruments
 rem ---var1,var2,bx,by,score used by Tracker Editor (cannot Tx instruments from Editor)
 rem ---px hiscore timeout (3 minutes play to obtain highest score/ StarShip scoring system
 rem -- py (0/1) toggle between green 3Dcube and 3D TIE Fighter
 rem -----------------------------------------
 rem ---init section, runs once: -------------
 rem -----------------------------------------


 rem --- 20241002 SIDFx try changing SID4,SID5,SID6 arrays ... test dynamic instrument revision:
 gosub rebuildsid456a

 missile1x=80:s=1
 h=45:k=0
 rem for x=1 to 20:gosub rebuildmusic:next x
 data titles "RINGWORLD=0     RAINBOWMETER=000  SID=00"       

 for x=0 to 60
 rem IF x<40 then y=80+x:w=titles(x):w=w-64:DisplayList3Shadow(y)=w:rem titles(x)-65
 iF x<4 then y=80+x:w=titles(x):w=w-64:DisplayList3Shadow(y)=w :rem titles(x)-65
 iF x<37 and x>33 then y=80+x:w=titles(x):w=w-64:DisplayList3Shadow(y)=w :rem titles(x)-65
 DisplayList3Shadow(87)=128
 rem 20241005 preserve initial musical score... 
 if x<20 then gosub rebuildmusic:rem advance SID
 rem if x<53 then gosub rebuildmusic:rem advance SID
 next x
 DisplayList3Shadow(154)=53:rem display 5 as median SID 4,5,6 set SID Orchestra reference got playah...
 
 DisplayList3Shadow(119)=48:DisplayList3Shadow(118)=48

 rem hiscore 
 DisplayList3Shadow(105)=48:DisplayList3Shadow(106)=48:DisplayList3Shadow(107)=48
 q=1:r=6
 rem n=1
 n=0:o=1:l=160:rem Rainbow warp bonus stage on startup!

 rem debug 20250129 RC8 testing color combinations on tennuous rings:
 rem n=10: rem somehow resets to 1 instead (n was reset to 1 asssssabove, moved test)


 rem start on ring 10 for debugging additional tennuous ring colors and Fx in RC8 enhancement
 rem DisplayList3Shadow(85)=49+8:rem debug view additional Rings 1st
 DisplayList3Shadow(85)=49:rem Starts on RING 1

initscore 
 DisplayList3Shadow(111)=48:DisplayList3Shadow(110)=48
 DisplayList3Shadow(109)=48
 return

incp
 p=p+1
 if p=16 then p=1
 return

decp
 p=p-1
 if p=0 then p=15
 return

newsidewinder
 rem 20240920 alternate sidewinder with Saucers Photon Tordpedeo if Saucer is far away:
 rem 20240921 allow 3dcube to use photo torpedeo if Saucer is too far away... 
 if k<>0 then goto knot0
repeatphotonshot
 if player1y>45 then k=1:e=player1x+4:h=player1y-3:return 
 rem - this launches more photon torpedoes...
trythis
 k=1:e=x:h=y:return
knot0
 k=0 
 e=0:h=screamers(z):z=z+1
 return

 rem releasesaucer
 rem player1y=0:gosub decreasescore:i=0:rem i is explosion flag
 rem return

rebuildsaucer
 player1y=92:player1x=screamers(z):z=z+1:rem too aggressive... k=0:gosub newsidewinder
 rem if crashes? if m=3 then k=0:gosub newsidewinder
 rem works k=0:gosub newsidewinder
 return

 rem release3dcube
 rem y=0:gosub decreasescore:j=0:v=0:rem i is explosion flag v is scaling facor
 rem return

rebuild3dcube
 y=92:x=screamers(z):z=z+1
 return

screamerrender rem -----------------------------------------------------------------
 rem moving this to fix cube animation! otherise some w values missed 
 rem --- dont think this can move...
 rem 20250129 imported enhancement from Atari 2600 release of RC8 tuning object animation (not a bug) if w<4 then w=w+1 else w=0
 rem 3D cube and Tie Fighters look better at this animation rate:
 if w<4 then w=w+t else w=0
 if y=0 then v=0:y=92:x=screamers(z):z=z+1
 if z>32 then z=0

 y=y-2
 rem if y<2 then COLUBK=15:y=0
 rem if y<2 then y=0:v=0:gosub decreasescore: rem change back color fx removed, add sound Fx?
 if y<2 then j=5:player0y=7:gosub decreasescore:gosub decreasescore: rem change back color fx removed, add sound Fx?

 rem push to outside loop when t=1

 rem sprite 1 multiplexed alternate () sidewider weapon (e,h)
 if k=0 then e=e+4:player0colors(1)=4:goto donek
 h=h-6:player0colors(1)=h/2
 if e<80 then e=e+5 else e=e-5:rem homing beam, check if within range when hit [decrease score]
donek 
 rem if h<5 then gosub newsidewinder:rem altenates with saucher photon torpedeo
 rem wait for wraparound to reach ...
 if h>245 then gosub decreasescore:gosub newsidewinder:rem altenates with saucher photon torpedeo
 if e>160 then gosub decreasescore:gosub newsidewinder:rem altenates with saucher photon torpedeo 
 if z>32 then z=0
skipnextj

 rem sprite 2
 if player1y=0 then gosub rebuildsaucer 
 if z>32 then z=0
 rem flip sprite 4 different ways, backwards/upsidedown:

 if i=0 then goto normalsaucer else i=i-1
 if i=1  then loadplayer1(64):REFP1=0:rem 40 is explosion sequence animatino
 if i=2 then loadplayer1upsidedown(56):REFP1=255
 if i=3 then loadplayer1upsidedown(48):REFP1=0
 if i=4 then loadplayer1(40):REFP1=255
 if i=0 then gosub rebuildsaucer:gosub maybesaucerattack
 goto donesaucer
normalsaucer
 if w=0  then loadplayer1(24):REFP1=0:rem 24 is Saucer
 if w=1 then loadplayer1upsidedown(24):REFP1=255
 if w=2 then loadplayer1upsidedown(24):REFP1=0
 if w=3 then loadplayer1(24):REFP1=255
 player1y=player1y-4
donesaucer


 rem --changing back color bad Fx --- if player1y<4 then COLUBK=1:player1y=0
 if player1y<4 then player1y=7:i=5:gosub decreasescore:gosub decreasescore:rem add sound Fx?
 
 rem now scale sprite based on zone using NUSIZ0 000 , 101, 111 (last 3 bits)

 d=0:rem v&%00000000 --------- d is a tempvar, not using v (v is preserved)
 if player1y<31 then d=%00000111:goto donescaleplayer1
 if player1y<52 then d=%00000101
donescaleplayer1
 rem if missile1y<31 then d=d|%00110000:goto donescaleplayer1b
 if missile1y<52 then d=d|%00110000

donescaleplayer1b rem and (missile 1 too)
 NUSIZ1=d   :rem v&%00000000

 if r>0 then COLUP1=r else COLUP1=15

 return
 
 rem tilemap screamers to relative BITIndex 
 rem data screamers 1,5,10,4,15,11,19,3,7,2,18,16,12,6,15,3,18,1,4,7,11,4,14,17,12,13,2,3,16,4,17,18,3,19,5,6,11,14,8,19,13,2,14,19,1,5,4,12

 rem overlay x,y coordinates
 data screamers 10,50,100,40,150,110,30,90,152,8,16,45,20,130,95,115,150,110,30,90,152,80,20,40,150,125,22,110,5

 rem if screamers hit last row increment border color or flash screen for M frames (better, M can set COLUBK=0)

increasescore 
 rem if t=1 then return
 DisplayList3Shadow(111)=DisplayList3Shadow(111)+1
 if DisplayList3Shadow(111)<>58 then return
 DisplayList3Shadow(111)=48:DisplayList3Shadow(110)=DisplayList3Shadow(110)+1 
 
 rem doubling Rainbow Warp Bonus Round Time o=n:n=0:l=160:rem Rainbow Rings Fx!
 o=n:n=0:l=255:rem Rainbow Rings Fx!
 
 rem 20250129 Addint Tennuous Rings stage enhancement from Atari 2600 RC8 release:
 gosub testr


 if DisplayList3Shadow(110)<>58 then return
 DisplayList3Shadow(110)=48:DisplayList3Shadow(109)=DisplayList3Shadow(109)+1 

 return

advancepallette
 
 rem 20250129 expanding from 9 to 21 Rings with Tennuous Rings, from Atari 2600 RC8 release if n<9 then n=n+1 else n=1 
 if n<20 then n=n+1 else n=1
 
 r=paletter(n):q=paletteq(n)
 DisplayList3Shadow(85)=48+n
 return

decreasescore rem --- only take away points in 1's and 10 digit column... encourages 100 point incremental goals!
 if DisplayList3Shadow(111)>48 then DisplayList3Shadow(111)=DisplayList3Shadow(111)-1:return
 if DisplayList3Shadow(110)=48 then return
 DisplayList3Shadow(111)=53:DisplayList3Shadow(110)=DisplayList3Shadow(110)-1 
 return

 rem ------------------------------------------------
 rem ---gameloop subroutine, runs every frame:    ---
 rem ------------------------------------------------

 rem 30/25 or 60/50 Hz Fx: leave MBR filter on/off in template

 scrollvirtualworldtoggle=1

 t=1-t:rem toggles variable between 0 and 1

 rem 202409919 Horizontal cross drift for 3D objects --------
horozontaldrift
 if m<>2 then goto horozontaldrift2
 if screamers(z)<40 then player1x=player1x+3:goto donehorizontaldrift else player1x=player1x-2:goto donehorizontaldrift
horozontaldrift2 
 if m<>5 then goto donehorizontaldrift
 if screamers(z)<60 then x=x+2 else x=x-2:rem ai drift driven off of z index to center on z axis ;) 
 rem ... remember to seed random generator for z...
donehorizontaldrift
 rem --------------------------------------------------------

 if l>0 then l=l-1
 if l=1 then n=o:gosub advancepallette
 rem ---this  caused ineresting Fx on scaled 3D cube, perhaps make intermittent? v=%00000000
 if t=0 then goto skipt1: rem need this for sidewinder?
 rem flip sprite 4 different ways, backwards/upsidedown:
 rem py alternates with 40 and 72 (cube or ship, shoud have different color too)
 if j=0 then goto load3dcubenormally else j=j-1
 if j=1  then loadplayer0(64):REFP0=0
 if j=2 then loadplayer0upsidedown(56):REFP0=255
 if j=3 then loadplayer0upsidedown(48):REFP0=0
 if j=4 then loadplayer0(40):REFP0=255
 if j=0 then py=1-py:DisplayList3Shadow(87)=DisplayList3Shadow(87)+py:gosub rebuild3dcube:gosub maybesaucerattack:rem maybe3dcubeattack too! :)
 player0colors(0)=8-j
 goto done3dcube

load3dcubenormally

 rem TIE Fighter 
 if py=0 then goto load3dcube 
 rem player0colors(0)=player0y/20
 rem player0colors(0)=15:rem player0x/16
 if DisplayList3Shadow(87)=144 then DisplayList3Shadow(87)=128 else player0colors(0)=DisplayList3Shadow(87)&%01111111
 if w=0 then loadplayer0(72):REFP0=0
 if w=1 then loadplayer0upsidedown(80):REFP0=0
 if w=2 then loadplayer0(72):REFP0=255
 if w=3 then loadplayer0(96):REFP0=255
 goto almostdone3dcube

 
load3dcube rem green
 player0colors(0)=5
 if w=0  then loadplayer0(8):REFP0=0
 if w=1 then loadplayer0upsidedown(8):REFP0=255
 if w=2 then loadplayer0upsidedown(8):REFP0=0
 if w=3 then loadplayer0(8):REFP0=255
almostdone3dcube
 player0y=y:player0x=x 
done3dcube

 if y<31 then v=%00000111:goto donescaleplayer0 else v=0
 rem if y<52 then v=%11110101:goto donescaleplayer0
 if y<52 then v=%00000101:rem goto donescaleplayer0

donescaleplayer0
 rem NUSIZ0=v
 rem goto skipt0
skipt1 rem now using missile1, not skipped... no multiplexing
 rem if e=0 or t=1 then goto skipt0
 rem t0 -- multiplex sidewinder:
 rem flip sprite 4 different ways, backwards/upsidedown:
 
 missile0y=h:missile0x=e

 if h<48 then v= v|%11110000
 NUSIZ0=v
 
 if w>2 then missile0y=missile0y-2 else missile0y=missile0y+2 
 
donescaleplayer0a

skipt0
 rem -----------------------------------------------------
 




 m=m+1 
 
 
 rem -- 20240921 deactivating this - to hectic to watch double speed palette switching on top of fast scrolling...
 rem if m<>3 then goto skipdoublespeedscroll: rem -----------faster palette switching when speeding
 rem if joy0up=1 or joy0down=1 then goto fasterinmotion
skipdoublespeedscroll

 rem 20250131 twinkle stars in sparse starfield (exists only on tennuous Ring stages)
 rem if m=0 then TileCharacters(3)=32 then TileCharacters(3)=46 else TileCharacters(3)=32
 rem if m<>6 and TileCharacters(0)<>32 then goto skiptwinkling
 rem twinkling starfield on 1/4 of tilepixels
 rem if TileCharacters(0)=32 and t=1 then TileCharacters(1)=46 else TileCharacters(1)=32
 if m=6 and TileCharacters(0)=32 then gosub lightstarfield:goto skiprowcoloring

skiptwinkling


 if m<7 then goto skiprowcoloring 
 m=0 

 rem 20250131 blank space for tennous Rings (was too busy) and dynamic Ring formations Fx!
 rem parallex starfield and meteor field was too busy with tennuous Rings
 if TileCharacters(0)=32 then goto blankspace
 if TileCharacters(0)<>123 and t=1 then TileCharacters(0)=123 else TileCharacters(0)=46
 if TileCharacters(3)<>123 and t=0 then TileCharacters(3)=123 else TileCharacters(3)=46

 rem if TileCharacters(0)<>123 and t=1 then TileCharacters(0)=123:TileCharacters(1)=46 else TileCharacters(0)=46:TileCharacters(1)=123
 rem if TileCharacters(3)<>123 and t=0 then TileCharacters(3)=123:TileCharacters(2)=46 else TileCharacters(3)=46:TileCharacters(2)=123
 rem too fast if TileCharacters(0)<>123 then TileCharacters(0)=123:TileCharacters(3)=46 else TileCharacters(0)=46:TileCharacters(3)=123
 
 goto doneblankspace
blankspace
 
 if BackgroundTileCharacters(0)<223 or BackgroundTileCharacters(0)>250 then BackgroundTileCharacters(0)=223:goto bctap
 BackgroundTileCharacters(0)=BackgroundTileCharacters(0)+1
bctap
 BackgroundTileCharacters(3)=BackgroundTileCharacters(0)+2
 BackgroundTileCharacters(2)=BackgroundTileCharacters(0)+3
 BackgroundTileCharacters(1)=BackgroundTileCharacters(0)+4
 

doneblankspace



fasterinmotion
 rem if q=6 and r=1 then COLUBK=2 else COLUBK=0:rem 20250131 initial screen background
 rem if r=1 and q=6 then COLUBK=2
 COLUBK=0
 d=q:q=r:r=d:rem swap q and r
 gosub alternaterowcolors
 if s=1 and joy0up=0 then BYTErowoffset=BYTErowoffset-12:
 if s=2 and joy0down=0 then BYTErowoffset=BYTErowoffset+12:rem slow drift down
 return:rem 20250129 porting overcycle patch from 2600 release, remove this if it stops the cool ZX81 Fx in the editor when compiling for 30Hz/25Hz
skiprowcoloring
 
 if score>0 then goto donehit:rem 20241005 (tracker editor is active)

 rem set right/left ring boundries?
 rem if joy0right=1 and BITIndex<71 then MUSICINDEX=45:BITIndex=BITIndex+1:s=1:gosub adjustright
 rem if joy0left=1 and BITIndex>0 then MUSICINDEX=75:BITIndex=BITIndex-1:s=1:gosub adjustleft
 if joy0right=1 then MUSICINDEX=45:BITIndex=BITIndex+1:s=1:gosub adjustright
 if joy0left=1 then MUSICINDEX=75:BITIndex=BITIndex-1:s=1:gosub adjustleft


 if joy0up=1 then MUSICINDEX=160:BYTErowoffset=BYTErowoffset-12:s=1:gosub speedup:goto pickupmain

 rem 20241002 warp forward when The Rainbow is active
 rem superflous, joy0up already 0 if n=0 and joy0up=0 then BYTErowoffset=BYTErowoffset-12:s=1:gosub speedup:goto pickupmain
 if n=0 then BYTErowoffset=BYTErowoffset-12:s=1:gosub speedup:goto pickupmain

 if joy0down=1 then MUSICINDEX=230:BYTErowoffset=BYTErowoffset+12:s=2:gosub slowdown 

pickupmain
 if SWCHB|%11110111=247 and t=1 then SUSTAINFORFRAMES=SUSTAINFORFRAMES+1:gosub shiftlocktogglebw

 rem hit something? stream colors and allow a new palette to be selected if not in motion...
 rem --------------- 
 
 rem 20240921 hitting floating pieces of the ring or photon torpedoes does not increase score:
 rem (but missing them decreases score)
 if CXPPMM & %01000000>0 then k=0:gosub newsidewinder:CXCLR=0:goto donehit:rem hit satellite 
 
 rem if  CXM1P & %01000000>0 then player1y=92:player1x=missile0x:CXCLR=0:gosub increasescore:goto donehit:rem --- rainbow pushes triangle back to top!
 if  CXM1P & %01000000>0 then i=5:CXCLR=0:gosub increasescore:goto donehit:rem --- rainbow pushes triangle back to top!


 rem tst if  CXM1P & %10000000>0 then y=92:v=0:x=player1x+7:CXCLR=0:gosub increasescore
tst if  CXM1P & %10000000>0 then j=5:CXCLR=0:gosub increasescore


donehit

 rem 20241007 -- persist hi score with px counter
 if px>29 then gosub persisthiscore
 if f=0 then px=px+1

 if joy0fire=1 and f=0 then f=130 else f=f-1:return 
 
rebuildmusic
 rem create new musical score and instrument defs:"
 for i=0 to 255
 if i=44 or i=74 or i=159 or i=229 then goto skipnote
 d=MusicData(i)&%00011111
 MusicData(i)=d+3:rem 3
skipnote 
 next i:DisplayList3Shadow(119)=DisplayList3Shadow(119)+1
 i=0:rem restore i variable to 0 state, used for explosion status of Saucer
 if DisplayList3Shadow(119)=58 then DisplayList3Shadow(119)=48:DisplayList3Shadow(118)=DisplayList3Shadow(118)+1
 return

slowdown
 if m>2 then return
 if y<96 then y=y+1
 if player1y<96 then player1y=player1y+1
 if h<94 then h=h+1:rem missile0y=missile0y+1
 return

speedup
 rem y ... if player0y>4 then player0y=player0y-1
 if t=1 then return
 if y>4 then y=y-1
 if player1y>4 then player1y=player1y-1
 if h>4 then h=h-1:rem missile0y=missile0y-1

 return

adjustleft
 x=x+5
 player1x=player1x+5
 if t=1 then e=e+2:rem missile0x=missile0x+3
 return

adjustright
 x=x-5
 player1x=player1x-5
 if t=1 then e=e-2:rem missile0x=missile0x-3
 return

maybesaucerattack
 u=u+1
 if u=5 then u=0:k=0:gosub newsidewinder

 return

 rem data paletter 5,5,2,3,12,4,14,7,8,1
 rem data paletteq 13,13,6,14,11,10,6,8,4,15
 rem 20250129 expanding to 21 color combinations with Tennuous Rings:
 rem data paletter 5,5,2,3,12,4,14,7,8,1,6,12,10,2,15,2,4,13,15,1,4
 rem data paletteq 13,13,6,14,11,10,6,8,4,15,1,10,8,4,12,10,10,7,7,3,3
 rem remix:
 data paletter 5,6,13,10,2,2,4,13,15,1,5,2,3,12,4,14,7,8,1,6,12,4
 data paletteq 13,8,7,8,4,10,10,7,7,3,13,6,14,11,10,6,8,4,15,1,10,3


 rem ------------------------------------------------
 rem ---gameloop2 subroutine, runs every frame:    --
 rem ------------------------------------------------
 rem COLUBK=12
 if missile1y=0 and joy0fire=1 and g<>15 then g=15:rem flag in action
 if g=15 then missile1y=missile1y+2 else goto skipmissile1 

 if missile1y>96 then g=0:missile1y=0:missile1x=80
 if joy0left=1 and t=0 then missile1x=missile1x-4
 if joy0right=1 and t=1 then missile1x=missile1x+4
skipmissile1
 if score=0 then return:rem score is musical score being edited :)

 rem ---- call tracker editor ------
 if SUSTAINFORFRAMES<5 then SUSTAINFORFRAMES=5:rem SUSTAINFORFRAMES+1

 if score=1 then MUSICINDEX=0:gosub drawtrackergui:score=2:return
 if score>1 then by=score-2:bx=MUSICINDEX+by:gosub doedit:rem edit all 5!
 rem if score=2 then bx=MUSICINDEX:gosub doedit:rem edit v1 note
 rem if score=3 then bx=MUSICINDEX+1:gosub doedit:rem v1 instrument
 rem checknext if score=7 then goto checknext:rem debug on next
 return

 rem ------------------------------------------------------------------------
 rem --- relocated subroutines from 1st gameloop (reserved memory exceeded):
 rem ------------------------------------------------------------------------

rebuildsid456a rem 20241002 rebuild instrument defintions - sounds better
 for bx=0 to 32
 SID4(bx)=SID4(bx)+2:rem SID4(bx)=SID4(bx)&%11110111:mask squelch off
 rem test squelch, interesting not 100% effective SID4(bx)=SID4(bx)^%00001000
 SID5(bx)=SID5(bx)+2
 SID6(bx)=SID6(bx)+2
 next bx
 DisplayList3Shadow(154)=DisplayList3Shadow(154)+1
 return 

rebuildsid456b rem 20241002 rebuild instrument defintions - reverse direction
 for bx=0 to 32
 SID4(bx)=SID4(bx)-2:rem SID4(bx)=SID4(bx)&%11110111
 SID5(bx)=SID5(bx)-2
 SID6(bx)=SID6(bx)-2
 next bx
 DisplayList3Shadow(154)=DisplayList3Shadow(154)-1
 return 

rebuildmusic2
 rem create new musical score and instrument defs:"
 for i=0 to 255
 if i=44 or i=74 or i=159 or i=229 then goto skipnote2
 d=MusicData(i)&%00001111
 MusicData(i)=d+5:rem 3
skipnote2 
 next i:DisplayList3Shadow(119)=DisplayList3Shadow(119)+1
 i=0:rem restore i variable to 0 state, used for explosion status of Saucer
 if DisplayList3Shadow(119)=58 then DisplayList3Shadow(119)=48:DisplayList3Shadow(118)=DisplayList3Shadow(118)+1
 MUSICINDEX=0
 return




shiftlocktogglebw rem ---- either bw color switch or left shift/shift lock thrown
 rem ---------
 if var1=0 and joy0up=1 then var1=1:gosub rebuildsid456a:return
 if var1=0 and joy0down=1 then var1=1:gosub rebuildsid456b:return
 if var1=0 and joy0left=1 then var1=2
 if var1=1 and joy0up=0 and joy0down=0 then var1=0
 if var1=2 and joy0left=0 then var1=0:gosub rebuildmusic2:rem avoid starting left subtune

 if joy0right=1 then score=1:rem was gosub editpattern
 return

persisthiscore
 rem DisplayList3Shadow(109),DisplayList3Shadow(110),DisplayList3Shadow(111)
 px=0:m=3:COLUBK=5
 rem goto setthiscore:rem debug

 if DisplayList3Shadow(109) < DisplayList3Shadow(105) then goto resetscore
 if DisplayList3Shadow(109) = DisplayList3Shadow(105) and DisplayList3Shadow(110) < DisplayList3Shadow(106) then goto resetscore
 if DisplayList3Shadow(110) = DisplayList3Shadow(106) and DisplayList3Shadow(111) < DisplayList3Shadow(107) then goto resetscore

sethiscore 
 DisplayList3Shadow(105)=DisplayList3Shadow(109):DisplayList3Shadow(106)=DisplayList3Shadow(110):DisplayList3Shadow(107)=DisplayList3Shadow(111)
resetscore
 gosub initscore: rem same as below
 rem DisplayList3Shadow(109)=48:DisplayList3Shadow(110)=48:DisplayList3Shadow(111)=48 
 return

alternaterowcolors rem expects i and j to have colors
 if n=0 then gosub incp:q=p
 rowcolors(8)=q: rem bottom row
 rowcolors(7)=q:rem 2nd up from bottom
 rowcolors(6)=q:rem 3rd up from bottom

 if n=0 then gosub incp:r=p
 rowcolors(5)=r:rem 4th up from bottom
 rowcolors(4)=r:rem 5th up from bottom
 
 if n=0 then gosub incp:q=p
 rowcolors(3)=q:rem 6th up from bottom
 
 if n=0 then gosub incp:r=p
 rowcolors(2)=r:rem 7th up from bottom

 rem one more row...
 if n=0 then gosub incp:q=p
 rowcolors(1)=q:rem 6th up from bottom
 
 rem --keep top 3 rows black for fade fx over the horizon

 rowcolors(0)=0:rem 2nd
 rowcolors(9)=0:rem top row
 rem rowcolors(1)=0:rem 3rd


 rem 20250129 backporting Rainbow warp palette swiching improvement, should be 4 back not 6... if n=0 then gosub decp:gosub decp:gosub decp:gosub decp:gosub decp:gosub decp
 if n=0 then gosub decp:gosub decp:gosub decp:gosub decp

 rem -- this looks better on C64?
 gosub decp
 gosub decp
 
 gosub screamerrender
 return

testr rem --- 20250129 this is the tennuous Ring routine imported from the Atari 2600 release of RC8
 rem --- need to call it before the rainbow warp (remember to increase warp time...)
 for f=239 to 0 step -1
 rem virtualworld(f)=0
 rem f=virtualworld(f)
 rem virtualworld(f)=f^255
 virtualworld(f)=virtualworld(f)^255
 next f

 rem 20250131 adding Fx to replace meteor starfield parallex petscii on tennuous rings
 if TileCharacters(0)<>32 then goto tcnot32
 TileCharacters(0)=31:rem revert to parallex starfield over meteor field logic
 BackgroundTileCharacters(0)=111
 BackgroundTileCharacters(1)=111
 BackgroundTileCharacters(2)=111
 BackgroundTileCharacters(3)=111

 return
tcnot32
 rem clear starfield meteor field and queue dynamic changes for 1 2 & 3
 TileCharacters(0)=32:TileCharacters(1)=32
 TileCharacters(2)=32:TileCharacters(3)=32
 rem BackgroundTileCharacters(0)=222

 return


 rem -----------------------TRACKER EDITOR INGAME------------------------------
 rem editpattern rem --- input causes CRT jump like a ZX80 at 30/25 Hz
 rem ------------color coded editor with syntax checking, like vim or vi ;)

doedit
 rem hilight cursor
 if score=2 then DisplayList3ShadowColor(8)=1:DisplayList3ShadowColor(9)=1:DisplayList3ShadowColor(31)=14:goto editj:rem 1st datum 
 if score=3 then DisplayList3ShadowColor(8)=14:DisplayList3ShadowColor(9)=14:DisplayList3ShadowColor(13)=1:DisplayList3ShadowColor(14)=1:goto editj
 if score=4 then DisplayList3ShadowColor(13)=14:DisplayList3ShadowColor(14)=14:DisplayList3ShadowColor(18)=1:DisplayList3ShadowColor(19)=1:goto editj
 if score=5 then DisplayList3ShadowColor(18)=14:DisplayList3ShadowColor(19)=14:DisplayList3ShadowColor(23)=1:DisplayList3ShadowColor(24)=1:goto editj
 if score=6 then DisplayList3ShadowColor(23)=14:DisplayList3ShadowColor(24)=14:DisplayList3ShadowColor(28)=1:DisplayList3ShadowColor(29)=1:goto editj
 if score=7 then DisplayList3ShadowColor(28)=14:DisplayList3ShadowColor(29)=14:DisplayList3ShadowColor(31)=1
editj
 if joy0right=0 and joy0up=0 and joy0down=0 and var1=1 then var1=0:rem same input scheme to move joystick incrementally
 if joy0up=1 and var1=0 and score=7 then var1=1:score=2:gosub skipcontrols:return:rem next pattern
 if joy0down=1 and var1=0 and score=7 then var1=1:score=2:gosub skipcontrols:return:rem next pattern


 if joy0up=1 and MusicData(bx)<38 and var1=0 then var1=1:MusicData(bx)=MusicData(bx)+1:SUSTAINFORFRAMES=0:gosub PlayMusic:MUSICINDEX=MUSICINDEX-5:gosub drawtrackergui:SUSTAINFORFRAMES=SUSTAINFORFRAMES+1
 if joy0down=1 and MusicData(bx)>0 and var1=0 then var1=1:MusicData(bx)=MusicData(bx)-1:SUSTAINFORFRAMES=0:gosub PlayMusic:MUSICINDEX=MUSICINDEX-5:gosub drawtrackergui:SUSTAINFORFRAMES=SUSTAINFORFRAMES+1
 
 if joy0right=1 and var1=0 then var1=1:score=score+1:rem edit next 
 rem 20241010 patched to prevent right tune from always launching after editing (tied to event)
 if joy0right=0 and score=8 then score=0:gosub cleartrackergui:DisplayList3ShadowColor(31)=14:MUSICINDEX=0:SUSTAINFORFRAMES=0:rem done
 
 return:rem goto doedit

cleartrackergui
 for bx=0 to 79
 by=120+bx:rem var2=trkedit(bx):var2=var2-64
 rem if bx>30 then by=by+40:rem labels on next line 
 if bx>30 and bx < 40 then by=by+40:DisplayList3Shadow(by)=DisplayList3Shadow(88) else DisplayList3Shadow(by)=DisplayList3Shadow(88):rem labels on next line 

 next bx
 return

skipcontrols bx=MUSICINDEX+9
 if MusicData(bx)=0 then MUSICINDEX=MUSICINDEX+10 else MUSICINDEX=MUSICINDEX+5

 SUSTAINFORFRAMES=0:gosub PlayMusic:rem want next pattern 0 duration setting increments MUSICINDEX by 5
 MUSICINDEX=MUSICINDEX-5
 SUSTAINFORFRAMES=SUSTAINFORFRAMES+1
 rem bx=MUSICINDEX+4
 rem if MusicData(bx)=0 then MUSICINDEX=MUSICINDEX+5:goto skipcontrols
 rem if MusicData(bx)=0 then goto skipcontrols:rem control auto advances music player to next pattern

 gosub drawtrackergui
 return

drawtrackergui
 rem COLUBK=6
 var1=1:rem init to wait to release joystick
 data trkedit "PATTERN INST NOTE INST NOTE LENNEXT DONE"       

 for bx=0 to 39
 by=120+bx:var2=trkedit(bx):var2=var2-64
 if bx>30 then by=by+40:rem labels on next line 
 DisplayList3Shadow(by)=var2 
 next bx
 rem display MUSICINDEX...
 rem test
 rem MUSICINDEX=0
 if MUSICINDEX<100 then DisplayList3Shadow(164)=48:bx=MUSICINDEX:goto donewithmusicindex100s
 if MUSICINDEX>=200 then DisplayList3Shadow(164)=50:bx=MUSICINDEX-200:goto donewithmusicindex100s
 DisplayList3Shadow(164)=49:bx=MUSICINDEX-100
donewithmusicindex100s
 bx=bx/10:by=b:rem (modulus remainder in temp variable b)
 bx=bx+48:by=by+48
 DisplayList3Shadow(165)=bx
 DisplayList3Shadow(166)=by
 rem ----v1 note
 var2=MusicData(MUSICINDEX)
 rem var2=12
 if var2>29 then DisplayList3Shadow(168)=51:bx=var2-30:goto donev1tens
 if var2>19 then DisplayList3Shadow(168)=50:bx=var2-20:goto donev1tens
 if var2>9 then DisplayList3Shadow(168)=49:bx=var2-10:goto donev1tens
 DisplayList3Shadow(168)=48:bx=var2
donev1tens
 DisplayList3Shadow(169)=bx+48
 rem --- instrument v1
 bx=MUSICINDEX+1:var2=MusicData(bx)
 rem var2=12
 if var2>29 then DisplayList3Shadow(173)=51:bx=var2-30:goto donev1tens2
 if var2>19 then DisplayList3Shadow(173)=50:bx=var2-20:goto donev1tens2
 if var2>9 then DisplayList3Shadow(173)=49:bx=var2-10:goto donev1tens2
 DisplayList3Shadow(173)=48:bx=var2
donev1tens2
 DisplayList3Shadow(174)=bx+48
 rem --- v2 note
 bx=MUSICINDEX+2:var2=MusicData(bx)
 rem var2=12
 if var2>29 then DisplayList3Shadow(178)=51:bx=var2-30:goto donev1tens3
 if var2>19 then DisplayList3Shadow(178)=50:bx=var2-20:goto donev1tens3
 if var2>9 then DisplayList3Shadow(178)=49:bx=var2-10:goto donev1tens3
 DisplayList3Shadow(178)=48:bx=var2
donev1tens3
 DisplayList3Shadow(179)=bx+48
 rem --- instrument v2
 bx=MUSICINDEX+3:var2=MusicData(bx)
 rem var2=12
 if var2>29 then DisplayList3Shadow(183)=51:bx=var2-30:goto donev1tens4
 if var2>19 then DisplayList3Shadow(183)=50:bx=var2-20:goto donev1tens4
 if var2>9 then DisplayList3Shadow(183)=49:bx=var2-10:goto donev1tens4
 DisplayList3Shadow(183)=48:bx=var2
donev1tens4
 DisplayList3Shadow(184)=bx+48
 rem -- duration 
 bx=MUSICINDEX+4:var2=MusicData(bx)
 rem var2=12
 if var2>29 then DisplayList3Shadow(188)=51:bx=var2-30:goto donev1tens5
 if var2>19 then DisplayList3Shadow(188)=50:bx=var2-20:goto donev1tens5
 if var2>9 then DisplayList3Shadow(188)=49:bx=var2-10:goto donev1tens5
 DisplayList3Shadow(188)=48:bx=var2
donev1tens5
 DisplayList3Shadow(189)=bx+48
 return
 rem ------------------end--TRACKER EDITOR INGAME------------------------------

lightstarfield
 rem if BYTErowoffset>144 and TileCharacters(1)=32 then TileCharacters(1)=46 else TileCharacters(1)=32

 rem good... if BYTErowoffset=0 or BYTErowoffset=48 or BYTErowoffset=96 or BYTErowoffset=144 or BYTErowoffset = 216 then  TileCharacters(1)=46 else TileCharacters(1)=32
 rem if BYTErowoffset=0 or BYTErowoffset=48 or BYTErowoffset=96 or BYTErowoffset=144 or BYTErowoffset > 216 then  TileCharacters(1)=46 else TileCharacters(1)=32
 rem if BYTErowoffset < 190 then return
 rem 3 Stars triangulate
 if TileCharacters(2)=46 then TileCharacters(1)=32:TileCharacters(2)=32:TileCharacters(3)=46:return
 if TileCharacters(1)=46 then TileCharacters(1)=32:TileCharacters(2)=46:TileCharacters(3)=32:return
 if TileCharacters(1)=32 then TileCharacters(1)=46:TileCharacters(2)=32:TileCharacters(3)=32

 return


virtualworld
xxxxxxxx...............................................................xxxx.....xxxx........
xxx..xxx..............................................................x..x.....xxxxx........
xxx..xxx....xxxxxx...............................xxxx................xxxx.....xxxx.x........
xxxXXXXx....x....x...............................x..x...............x..x.....xxxx..x........
............x....x...............................xxxx..............x.xx.....xxxx...x........
............xxxxxx............xxxxx...............................xxxx.....xxxx....x........
.............................xxxxxxxx.............................xxxx.....xxx.....x........
............................xxxxxxxxxxx...........x...............xxxx.....xxx.....x........
..x....xxxxxx.....xx.......xxxxxxxxxxxxx.........xxx..............xxxx.....xxx.....x........
..xxx....xxxx..xxxxx........xxxxxxxxxx..........xxxxx.............xxxx.....xxx.....x........
..xxx..........xx............xxxxxxxx..........xxxxxxx............xxxx.....xxx....x.........
..............................xxxxxx..............................xxxx.....xxx...x..........
..................................................................xxxx.....xxx..x...........
.....................................................xx........x..xxxx.....xxxx.............
xxxxxxx..............................................xxx....................................
x..x..x..............................................xxxx...................................
xxxxxxx..............................................xxxxx............................x.....
x..x..x..............xxxxxxxxxx......................xxxxxx..........................xxx....
.xxxxxx..............xxxxxxxxxx......................xxxxxxx........................x...x...
.....................xxxxxxxxxx......................xxxxxxxx........................xxx....

sprites
..xxxx..
.xXXXXx.
XX.xx.XX
XxxxxxXX
x.XXXX.x
XX....XX
.xxxxxx.
..xxxx..

........
..xxxxxx
.x....xx
x....x.x
xxxxx..x
x...x.x.
x...xx..
xxxxx...

X.......
........
.xxxxxx.
xx..XXxx
x.xxxxXx
x.xx...x
xx....xx
.xxxxxx.
24
...x....
..xxx...
.x.xxx..
x..xxxx.
.x.xxxx.
..xxxx..
...xx...
........

........
........
........
........
........
........
........
........
40
x....x..
........
...x..x.
.x...x..
.xxx.x..
.x..x..x
..xxx.x.
x...x...

........
..x..x..
...x....
...x.x..
..xx.x..
..x.x...
...xx.x.
........

........
........
........
...x....
...x.x..
..x.x...
...x....
........

........
........
........
........
...x.x..
...xx...
........
........

72
..X.....
.X.XX...
X.XXXX.X
..XXX.X.
.....X..
........
........
........

........
........
X..XX..X
X.XXXX.X
X.XX.X.X
X..XX..X
........
........

........
........
.X.....X
XX.XX.XX
XXXXXXXX
XX.XX.XX
.X.....X
........

........
X.....X.
XX.XX.Xx
xXXXXXXX
.X.XX.XX
..x....x
........
........


player0colors 5,4,4,4,15,15,15,15


chiptunes
1,23,1,31,12
1,16,1,31,4
1,15,1,31,8
0,0,0,0,14
1,23,1,31,12
1,16,1,31,8
1,15,1,31,15
1,31,1,31,35
0,0,0,0,0
45
1,15,1,7,15
1,13,1,7,15
1,15,1,31,12
1,15,1,31,12
1,15,1,31,12
0,0,0,0,24
75
1,15,1,7,7
1,13,1,7,15
1,15,1,31,7
1,15,1,31,12
1,15,1,31,6
0,0,0,0,12
1,15,1,7,15
1,13,1,7,7
1,15,1,31,15
1,15,1,31,6
1,15,1,31,12
0,0,0,0,24
1,29,1,19,20
1,31,1,23,20
1,29,1,19,20
1,31,1,23,20
0,0,0,0,0
160
1,31,1,31,15
1,31,1,23,15
1,29,1,19,15
1,31,1,23,15
8,24,8,20,8
10,24,10,20,8
8,24,8,20,4
12,9,12,7,4
8,24,8,20,8
10,24,10,20,15
8,24,8,20,8
10,24,10,20,8
8,24,8,20,4
0,0,0,0,0
230
10,24,10,20,4
8,24,8,20,4
10,24,10,20,4
8,24,8,20,4
10,24,10,20,4
7,27,7,27,8



EXT
RA
8,24,8,20,95

7,27,7,27,8
7,13,7,13,8
7,6,7,6,8
0,0,0,0,4
7,27,7,27,8
7,6,7,6,8
7,6,7,6,8
12,3,12,2,4
12,5,12,2,4
7,27,7,27,8
7,13,7,13,8
7,6,7,6,8
0,0,0,0,4
7,27,7,27,8
7,6,7,6,8
7,6,7,6,8
12,3,12,2,4
12,5,12,2,4
0,0,0,0,0

                                                               