// First of several components for building a vectrex game.
// This one implements a title animation. Then you enter your game.
#include <vectrex.h>

typedef enum {WAITING, MOVING, STOPPING, DONE} STATE;
STATE state = WAITING; // set to DONE to skip intro animation
#define set_scale(s) do { VIA_t1_cnt_lo = s; } while (0)
static long reset_size;
struct cartridge_t // from cartridge.c unfortunately
{
	char copyright[11];			// copyright string, must start with "g GCE" and must end with "\x80"
	const void* music;			// 16 bit memory adress of title music data
	signed int title_height;	// signed 8 bit value, height of game title letters
	unsigned int title_width;	// unsigned 8 bit value, width of game title letters
	int title_y;				// signed 8 bit value, y coordinate of game title
	int title_x;				// signed 8 bit value, x coordinate of game title
	char title[]; 				// game title string, must end with "\x80\x00"
};

extern struct cartridge_t game_header __attribute__((section(".cartridge"))); // dropped const.

void fake_title(int x, int y) {
    Reset0Ref();
    set_scale(0x70);
    Moveto_d(y,x);
    *(volatile long *)0xC82A = reset_size;
    Print_Str_d(69,-45, game_header.title);
    Reset0Ref();
    set_scale(0x70);
    Moveto_d(y,x);
    set_scale(0x38); Moveto_d(0,1);
    *(volatile long *)0xC82A = (long)0xf848; // ht wd
    Print_Str_d(21,-38, game_header.copyright);
}

static int sin, cos;

void play_game(void) {
  // your game code for one frame goes here
  // random silly program here as a space-filler
#ifdef ORIG
  static long sin = 0L, cos = 100L, prevsin = 0L, prevcos = -7349L;
  int i,j; long dx, dy;
  Wait_Recal();
  Intensity_7F();
  Reset0Ref();
  set_scale(0x30);
  Moveto_d(0,0);
  for (i = 0; i < 44; i++) { // segments in line
    for (j = 0; j < 2; j++) { // length of line
      sin = sin - (dx=(cos >> 4));
      cos = cos + (dy=(sin >> 4));
    }
    Draw_Line_d((int)(prevcos-cos),(int)(sin-prevsin));
    prevsin=sin; prevcos=cos;
  }
#else
  int i, dx, dy;
  Wait_Recal();
  Intensity_7F();
  Reset0Ref();
  set_scale(0x80);
  sin = 8; cos = 99;
  Moveto_d(-80,0);Draw_Line_d(1,8);
  for (i=0;i < 48;i++) { // segments in line
    dx = cos>>4;
    sin = sin + dx;
    dy = sin>>4;
    cos = cos - dy;
    Draw_Line_d(dy,dx);
  }
  Draw_Line_d(1,-18);
  Reset0Ref();
  sin = 8; cos = 99;
  Moveto_d(-80,0);Draw_Line_d(1,-8);
  for (i=0;i < 48;i++) { // segments in line
    dx = cos>>4;
    sin = sin + dx;
    dy = sin>>4;
    cos = cos - dy;
    Draw_Line_d(dy,-dx);
  }
  Draw_Line_d(1,18);
  set_scale(0x68);
  Reset0Ref();
  Intensity_3F();
  {static int RX = 100, RY = 0;
    Moveto_d(0,0); Draw_Line_d(RY, -RX);
    dx = RX>>4;
    RY = RY + dx;
    dy = RY>>4;
    RX = RX - dy;
  }
#endif
}

int main(void)
{
  int delay = 127;
  sin = -96; cos = 1;
  reset_size = *(volatile long *)0xC82A;
  for (;;) {

    switch (state) {
      case WAITING:  Wait_Recal();
                     Intensity_7F();
                     fake_title(cos-31, sin);
                     delay -= 1;
                     if (delay == 0) {
                       state = MOVING;
                       delay = 2; // loops/2
                     }
                     break;
      case MOVING:   Wait_Recal();
                     Intensity_7F();
                     sin = sin - (cos >> 4);
                     cos = cos + (sin >> 4);
                     fake_title(cos-31, sin);
                     if (sin == -96 && cos == 1) {
                       delay -= 1;
                       if (delay == 0) {
                         state = STOPPING;
                         delay = 0x7F;
                       }
                     }
                     break;
      case STOPPING: Wait_Recal();
                     Intensity_a((unsigned int)delay);
                     fake_title(cos-31, sin); // fade out
                     delay -= 1;
                     if (delay == 0) state = DONE;
                     break;
      case DONE:     play_game();
                     break;
    }

  }
  return 0;
}