/*
  
   After many previous attempts, I am having one final effort to create a C version
   of Tailgunner!  (and so far I'm delighted to report that it is going well...)

   The code here is not the actual tailgunner program yet, it's still primarily me testing
   and debugging components that will be needed for that program.  This source file contains
   the Vectrex drawing code.  The pre-computed flight paths are generated by genpath.c in
   this directory.

   To reduce the runtime overhead in the Vectrex implementation of Tailgunner,
   we are copying the style of the original arcade version by pre-computing
   the flight paths.  Each flight path is likely to use about 1K of Eprom so
   the number of unique flight paths will be somewhat restricted compared to
   the arcade game, but hopefully there will be enough to make the game playable.

   This source file will also compile on linux for the 3.5inch SPI display which uses
   a framebuffer driver (it copies whatever is written to the framebuffer over to
   the LCD at regular intervals, but not fast enough (with the current driver) for
   full 30Hz updates.) However it is primarily intended for compiling for the Vectrex -
   the Linux display support is supported primarily to enable a faster compile/edit/run
   cycle during development.

     On my Pi Zero with an HDMI display enabled and the 3.5 inch LCD on SPI being used for
     the game, you need to use the map:01 option in cmdline.txt:
     console=serial0,115200 console=tty1 root=PARTUUID=9cb46872-02 rootfstype=ext4 fsck.repair=yes rootwait cfg80211.ieee80211_regdom=US fbcon=map:01

   Coordinate space is X:-512:511 Y:-512:511 Z:0:1023  Viewer is at [0,0,0]

*/

#ifndef __linux
#define VECTREX 1
#endif

#ifdef VECTREX

// You *must* compile with -O2 option

#include <vectrex.h>
#define set_scale(A) dp_VIA_t1_cnt_lo = A
#define int8_t int
#define uint8_t unsigned int
#define int16_t long

#else

#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>

#include "linux_graphics.h"

#endif // not VECTREX

// MAKE SURE THAT LINUX DISPLAY LOOKS LIKE VECTREX DISPLAY:
#include "drawship.c"
#include "demo_flightpath.h"


// #################################### Main entrypoint ########################################


#ifdef __linux
int main(int argc, char **argv) {
#else
int main(void) {
#endif
  static object_t *ship[4] = { &model1, &model2, &model3, &model4 };
  uint8_t Frame;

#ifdef USE_FB
  fbgl_key_t key;
#endif

#ifndef VECTREX
  if (argv[1] != NULL && *argv[1] == '/') {
    (void)InitGraphics(argv[1]);
  } else {
    (void)InitGraphics("/dev/fb1"); // or NULL for default...
  }
#endif

#ifdef USE_FB
  key = 'H';
#endif

  // plug in the first wave data

  // first ship
  ship[0]->rx = ship1_wave1_rx;
  ship[0]->ry = ship1_wave1_ry;
  ship[0]->rz = ship1_wave1_rz;
  ship[0]->x = ship1_wave1_sx;
  ship[0]->y = ship1_wave1_sy;
  ship[0]->scale = ship1_wave1_sc;
  ship[0]->steps = SHIP1_WAVE1_FRAMES;
  ship[0]->edge = model1_edge;
  ship[0]->edge_count = MODEL1_EDGES;
  ship[0]->vertex = model1_vertex;
  ship[0]->vertex_count = MODEL1_POINTS;

  // second ship
  ship[1]->rx = ship2_wave1_rx;
  ship[1]->ry = ship2_wave1_ry;
  ship[1]->rz = ship2_wave1_rz;
  ship[1]->x = ship2_wave1_sx;
  ship[1]->y = ship2_wave1_sy;
  ship[1]->scale = ship2_wave1_sc;
  ship[1]->steps = SHIP2_WAVE1_FRAMES;
  ship[1]->edge = model1_edge;
  ship[1]->edge_count = MODEL1_EDGES;
  ship[1]->vertex = model1_vertex;
  ship[1]->vertex_count = MODEL1_POINTS;

  // third ship
  ship[2]->rx = ship3_wave1_rx;
  ship[2]->ry = ship3_wave1_ry;
  ship[2]->rz = ship3_wave1_rz;
  ship[2]->x = ship3_wave1_sx;
  ship[2]->y = ship3_wave1_sy;
  ship[2]->scale = ship3_wave1_sc;
  ship[2]->steps = SHIP3_WAVE1_FRAMES;
  ship[2]->edge = model1_edge;
  ship[2]->edge_count = MODEL1_EDGES;
  ship[2]->vertex = model1_vertex;
  ship[2]->vertex_count = MODEL1_POINTS;

  Frame = 0U;
  for (;;) {

    Wait_Recal();
    Reset0Ref();
    Intensity_7F();

#ifdef USE_FB
    key = fbgl_poll_key(); // poor library interface - short term hack
    if (key == FBGL_KEY_ESCAPE || key == 'Q') {
      fbgl_destroy(&fb);
      exit(EXIT_SUCCESS);
    }
#endif

    // The use of fixed x offsets below is temporary until I generate compatible flightpaths for all three at once...
#ifdef TEST_ALL_THREE
    if (Frame < ship[0]->steps-1) project_object(ship[0], ship[0]->rx[Frame], ship[0]->ry[Frame], ship[0]->rz[Frame], ship[0]->scale[Frame], ship[0]->x[Frame]+40, ship[0]->y[Frame]);
    if (Frame < ship[1]->steps-1) project_object(ship[1], ship[1]->rx[Frame], ship[1]->ry[Frame], ship[1]->rz[Frame], ship[1]->scale[Frame], ship[1]->x[Frame],    ship[1]->y[Frame]);
    if (Frame < ship[2]->steps-1) project_object(ship[2], ship[2]->rx[Frame], ship[2]->ry[Frame], ship[2]->rz[Frame], ship[2]->scale[Frame], ship[2]->x[Frame]-20, ship[2]->y[Frame]);
#else
    if (Frame < ship[2]->steps-1) project_object(ship[2], ship[2]->rx[Frame], ship[2]->ry[Frame], ship[2]->rz[Frame], ship[2]->scale[Frame], ship[2]->x[Frame], ship[2]->y[Frame]);
#endif

    if (Frame == 254U) {
#ifdef USE_FB
      fbgl_destroy(&fb);
      exit(EXIT_SUCCESS);
#else
      Frame = 0U;
#endif
    }

    Frame += 1U;
  }
}
