include "inc/cmdsys.plh"
//include "inc/lines.plh"
include "inc/vblank.plh"
include "dhgr.tk/inc/dhgrlib.plh"
include "dhgr.tk/inc/dhgrutils.plh"
import fillshape
  //
  // Dither matrices
  //
  const DITHER0   = $00
  const DITHER25  = $04
  const DITHER50  = $06
  const DITHER75  = $07
  const DITHER100 = $0F
  predef setPattern(clr1, clr2, dither)#0
  predef patrnRect(left, top, right, bottom)#0
  predef solidRect(left, top, right, bottom)#0
  predef startPoly(x, y)#0
  predef addVertex(x, y)#0
  predef patrnPoly(x, y)#0
  predef solidPoly(x, y)#0
  predef solidEllip(xorg, yorg, width, height)#0
  predef patrnEllip(xorg, yorg, width, height)#0
  predef frame(left, top, right, bottom, thickness)#0
end

sysflags resxtxt1|reshgr1|resxhgr1
//
// ViewScreen coordinates
//
const VIEW_LEFT7   = 3
const VIEW_RIGHT7  = 17
const VIEW_WIDTH7  = VIEW_RIGHT7 - VIEW_LEFT7
const VIEW_LEFT    = VIEW_LEFT7  * 7 // 21
const VIEW_RIGHT   = VIEW_RIGHT7 * 7 // 119
const VIEW_WIDTH   = VIEW_RIGHT  - VIEW_LEFT
const VIEW_TOP     = 24
const VIEW_BOTTOM  = 122
const VIEW_HEIGHT  = VIEW_BOTTOM - VIEW_TOP
const VIEW_ORGX    = (VIEW_LEFT+VIEW_RIGHT)/2
const VIEW_ORGY    = (VIEW_TOP+VIEW_BOTTOM)/2
//
// Enterprise sprites
//
struc t_sprite
  var spr_xorg
  var spr_yorg
  var spr_width
  var spr_height
  var spr_pixmap
  var spr_bl7
end
res[t_sprite * 8] ncc1701
char[12] sprFile = "ENT.UP.SPR"
char[12]         = "ENT.UR.SPR"
char[12]         = "ENT.RT.SPR"
char[12]         = "ENT.DR.SPR"
char[12]         = "ENT.DN.SPR"
char[12]         = "ENT.DL.SPR"
char[12]         = "ENT.LT.SPR"
char[12]         = "ENT.UL.SPR"
const ENT_W7 = 5
const ENT_H  = 43
const ENT_SZ = ENT_W7*4*ENT_H
//
// Random seed
//
var rndseed = $A64D
def random#1
  rndseed = (rndseed << 8) ^ ((rndseed & $7FFF) >> 7) + $62B3
  return rndseed
end
//
// Draw components
//
def drawSurround#0
  //
  // Viewscreen surround
  //
  dcgrColor(CLR_GREY)
  dhgrClearBl7(0,           0,           SCR_WIDTH7, VIEW_TOP)
  dhgrClearBl7(0,           VIEW_BOTTOM, SCR_WIDTH7, VIEW_TOP)
  dhgrClearBl7(0,           VIEW_TOP,    VIEW_LEFT7, VIEW_HEIGHT)
  dhgrClearBl7(VIEW_RIGHT7, VIEW_TOP,    VIEW_LEFT7, VIEW_HEIGHT)
  setPattern(CLR_BLACK, CLR_GREY, DITHER50)
  patrnRect(0, VIEW_BOTTOM+VIEW_TOP, SCR_WIDTH-1, SCR_HEIGHT-1)
  //
  // Above viewscreen ceiling
  //
  setPattern(CLR_BLACK, CLR_GREY, DITHER50)
  startPoly(0, 0)
  addVertex(SCR_WIDTH-1, 0)
  addVertex(VIEW_RIGHT+3-1, VIEW_TOP-6)
  patrnPoly(VIEW_LEFT-3, VIEW_TOP-6)
  //
  // Below viewscreen bump-out
  //
  setPattern(CLR_GREY, CLR_WHITE, DITHER50)
  startPoly(VIEW_LEFT-3,    VIEW_BOTTOM+5)
  addVertex(VIEW_RIGHT+3-1, VIEW_BOTTOM+5)
  addVertex(SCR_WIDTH-1,    VIEW_BOTTOM+VIEW_TOP-1)
  patrnPoly(0,              VIEW_BOTTOM+VIEW_TOP-1)
  //
  // Viewscreen frame
  //
  dcgrColor(CLR_DRKBLUE)
  frame(VIEW_LEFT-3, VIEW_TOP-3, VIEW_RIGHT+3-1, VIEW_BOTTOM+3-1, 3)
  dcgrColor(CLR_MEDBLUE)
  frame(VIEW_LEFT-2, VIEW_TOP-2, VIEW_RIGHT+2-1, VIEW_BOTTOM+2-1, 1)
end
def drawRails#0
  dcgrColor(CLR_ORANGE)
  dhgrClearBl7(0,     132, 40/7, 1)
  dhgrClearBl7(107/7, 132, 40/7, 1)
  dcgrColor(CLR_MAGENTA)
  dhgrClearBl7(0,     133, 40/7, 7)
  dhgrClearBl7(107/7, 133, 40/7, 7)
  dcgrColor(CLR_BLACK)
  solidRect( 20, 140,  24, 191)
  solidRect(115, 140, 119, 191)
end
def drawAlerts#0
  dcgrColor(CLR_ORANGE)
  frame( 1*7-2, 40-2,  2*7+2-1, 80+2-1, 2)
  frame(18*7-2, 40-2, 19*7+2-1, 80+2-1, 2)
  dcgrColor(CLR_BLACK)
  dhgrClearBl7( 1, 40, 1, 40)
  dhgrClearBl7(18, 40, 1, 40)
end
def drawConsoles#0
  dcgrColor(CLR_MAGENTA)
  startPoly(70-30,          160)
  addVertex(70-30, SCR_HEIGHT-1)
  solidPoly(70-40, SCR_HEIGHT-1)
  startPoly(70+30-1,          160)
  addVertex(70+30-1, SCR_HEIGHT-1)
  solidPoly(70+40-1, SCR_HEIGHT-1)
  setPattern(CLR_BLACK, CLR_BROWN, DITHER50)
  startPoly(0,              160)
  addVertex(70-30,          160)
  addVertex(70-40, SCR_HEIGHT-1)
  patrnPoly(0,     SCR_HEIGHT-1)
  startPoly(70+30-1,              160)
  addVertex(SCR_WIDTH-1,          160)
  addVertex(SCR_WIDTH-1, SCR_HEIGHT-1)
  patrnPoly(70+40-1,     SCR_HEIGHT-1)
  dcgrColor(CLR_BLACK)
  startPoly(0,     170)
  addVertex(70-40, 170)
  addVertex(70-51, SCR_HEIGHT-1)
  solidPoly(0,     SCR_HEIGHT-1)
  startPoly(70+40-1,              170)
  addVertex(SCR_WIDTH-1,          170)
  addVertex(SCR_WIDTH-1, SCR_HEIGHT-1)
  solidPoly(70+51-1,     SCR_HEIGHT-1)
end
def drawNavigation#0
  dcgrColor(CLR_WHITE)
  startPoly(70-20,           150)
  addVertex(70+20-1,         150)
  addVertex(70+30-1, SCR_HEIGHT-1)
  solidPoly(70-30,   SCR_HEIGHT-1)
  setPattern(CLR_GREY, CLR_BROWN, DITHER50)
  patrnEllip(70, 170, 40, 35)
end
//
// Read Enterprise sprites
//
def readEnterprise#0
  var xorg, yorg, width, height, pixptr, t_ptr, f_ptr
  byte i

  t_ptr = @ncc1701
  f_ptr = @sprFile
  for i = 0 to 7
    xorg, yorg, width, height, pixptr = spriteRead(f_ptr)
    t_ptr=>spr_xorg   = xorg
    t_ptr=>spr_yorg   = yorg
    t_ptr=>spr_width  = width
    t_ptr=>spr_height = height
    t_ptr=>spr_pixmap = pixptr
    t_ptr=>spr_bl7  = heapalloc(ENT_SZ)
    dhgrSurfMem(OP_SRC, ENT_H, t_ptr=>spr_bl7, ENT_W7*4)
    dcgrColor(CLR_BLACK)
    dhgrClearBl7(0, 0, ENT_W7, ENT_H)
    dcgrPixmap(ENT_W7*7/2 - xorg,ENT_H/2 - yorg, width, height, pixptr)
    t_ptr = t_ptr + t_sprite
    f_ptr = f_ptr + 12
  next
end
//
// Animate stuff
//
def keypressed#1
  return ^$C000 & $80
end
def idleViewPlot(x)#0
  x = (x&63)+70-32
  dcgrHLin(x - 1, x + 1, VIEW_BOTTOM+3)
  dcgrHlin(x - 1, x + 1, VIEW_BOTTOM+4)
end
def newStar#3
  return 15 - (random & 30), 15 - (random & 30), random & 15
end
def idleStars#0
  byte xpos, star, nstars
  var starx, stary, starincx, starincy, starclr
  var x, y, incx, incy

  waitVBL; nstars = waitVBL / 50
  starx    = heapalloc(nstars*2)
  stary    = heapalloc(nstars*2)
  starincx = heapalloc(nstars*2)
  starincy = heapalloc(nstars*2)
  starclr  = heapalloc(nstars)
  nstars--
  for star = 0 to nstars
    repeat
      incx, incy, starclr->[star] = newstar
    until incx <> 0 and incy <> 0
    if starclr->[star] == 0; starclr->[star] = 15; fin
    starx=>[star]    = incx * (VIEW_WIDTH-1)/2
    stary=>[star]    = incy * (VIEW_HEIGHT-1)/2
    starincx=>[star] = incx
    starincy=>[star] = incy
  next
  xpos = 8
  star = 0
  while not keypressed
    dcgrColor(CLR_WHITE)
    idleViewPlot(xpos)
    dcgrColor(CLR_YELLOW)
    idleViewPlot(xpos-4)
    dcgrColor(CLR_ORANGE)
    idleViewPlot(xpos-8)
    dcgrColor(CLR_GREY)
    idleViewPlot(xpos-12)
    xpos = xpos + 4
    for star = 0 to nstars
      x = starx=>[star]
      y = stary=>[star]
      incx = x + starincx=>[star]
      incy = y + starincy=>[star]
      if  incx > (VIEW_WIDTH-1)*8  or incx < -VIEW_WIDTH*8 \
       or incy > (VIEW_HEIGHT-1)*8 or incy < -VIEW_HEIGHT*8
        repeat
          incx, incy, starclr->[star] = newStar
        until incx <> 0 and incy <> 0
        if starclr->[star] == 0; starclr->[star] = 15; fin
        starx=>[star]    = incx << 5
        stary=>[star]    = incy << 5
        starincx=>[star] = incx
        starincy=>[star] = incy
      else
        starx=>[star]    = incx
        stary=>[star]    = incy
        incx = starincx=>[star]
        incy = starincy=>[star]
        starincx=>[star] = incx + ((incx > 0 ?? incx + 7 :: incx - 7) >> 3)
        starincy=>[star] = incy + ((incy > 0 ?? incy + 7 :: incy - 7) >> 3)
      fin
      dcgrColor(CLR_BLACK)
      dcgrPixel((x >> 4) + VIEW_ORGX, (y >> 4) + VIEW_ORGY)
      dcgrColor(starclr->[star])
      dcgrPixel((starx=>[star] >> 4) + VIEW_ORGX, (stary=>[star] >> 4) + VIEW_ORGY)
    next
  loop
  getc
  heaprelease(starx)
end
def idleSpin#0
  var viewbuf, viewspan
  var i, k, oi, oj
  byte xpos

  //
  // Use back buffer
  //
  viewbuf, viewspan = dhgrAllocBl7Mem(VIEW_WIDTH, VIEW_HEIGHT)
  i    = @ncc1701
  k    = 0
  xpos = 0
  while not keypressed
    //
    // Rotate Enterprise
    //
    dhgrSurfMem(OP_SRC, VIEW_HEIGHT, viewbuf, viewspan)
    dcgrColor(CLR_DRKBLUE)
    dhgrClearBl7(0, 0, VIEW_WIDTH7, VIEW_HEIGHT)
    dcgrColor(CLR_GREEN)
    for oi = (xpos/4)&31 to VIEW_WIDTH-1 step 32
      dcgrVLin(0, VIEW_HEIGHT-1, oi)
    next
    for oi = (xpos/4)&63 to VIEW_HEIGHT-1 step 64
      dcgrHLin(0, VIEW_WIDTH-1, oi)
    next
    dhgrOp(OP_OR)
    dhgrMemBl7((VIEW_WIDTH7 - ENT_W7 + 1)/2, (VIEW_HEIGHT-ENT_H + 1)/2, \
               ENT_W7, ENT_H, \
               i=>spr_bl7, ENT_W7*4)
    dhgrSurfScr(OP_SRC)
    //waitVBL
    dhgrMemBl7(VIEW_LEFT7, VIEW_TOP, \
               VIEW_WIDTH7, VIEW_HEIGHT, \
               viewbuf, viewspan)
    i = i + t_sprite
    k++
    if k > 7
      k = 0
      i = @ncc1701
    fin
    //
    // Animate useless view screen lights
    //
    dcgrColor(CLR_WHITE)
    idleViewPlot(xpos)
    dcgrColor(CLR_YELLOW)
    idleViewPlot(xpos-4)
    dcgrColor(CLR_ORANGE)
    idleViewPlot(xpos-8)
    dcgrColor(CLR_GREY)
    idleViewPlot(xpos-12)
    xpos = xpos + 4
  loop
  heaprelease(viewbuf)
  getc
end
//
// Read sprites
//
readEnterprise
//
// Initialize
//
dhgrMode(DHGR_COLOR_MODE)
//
// Draw bridge
//
drawSurround
drawRails
drawAlerts
drawConsoles
drawNavigation
//
// Animate stars waiting for keypress
//
idleStars
idleSpin
//
// All done
//
dhgrMode(DHGR_TEXT_MODE)
done
