#define GCC6809 1 // ONLY ON VIDE SYSTEM. Is there a predefined symbol I can test instead?

#ifdef NOTGCC6809
#undef GCC6809 // (sorry, couldn't find an easier way yet.  Makefile fixes the problem...)
#endif

#ifdef VECTREX /* predefined by cmoc - don't define this with GCC for Vectrex */
#undef GCC6809

#include <vectrex/bios.h>

#define debugstr(s) /* ignore */

#define signed16 short
#define unsigned16 unsigned short
#define signed8 char
#define unsigned8 unsigned char
#define boolean int
#define const /* const not supported in cmoc - const arrays require a #pragma */
#define inline /* also not supported by cmoc */

// NOTE: only use inline when a procedure is called only once, to save the 4 bytes of the JSR/RTS
// Don't use inline to make code faster if it also makes it larger (except for very carefully curated tight inner loops)

#pragma vx_copyright "2017"
#pragma vx_title_pos -64,-79
#pragma vx_title_size -8, 80
//#pragma vx_title_size -8, 80
#pragma vx_title "B A   R   100"
#pragma vx_music vx_music_1

// this is to speed up the starfield.  Need a version for GCC too.
static void safedots(uint8_t nr_dots, int8_t* list) { // not convinced this is correct.  Don't know if the fault is here or at point of call.
  asm {
    PSHS    X,Y,U,D,CC,DP  ; err on the side of safety until I get this working...
    JSR     DP_to_D0
    LDA     nr_dots
    STA     $C823       ; Vec_Misc_Count
    LDX     list
    JSR     $F2D5       ; Dot_List
    PULS    DP,CC,D,U,Y,X
  }
}
#define dots(n,a) safedots((n)-1,a)  /* BIOS uses n-1 so correct it here. */

static void displaylist(int8_t* list) {  /* tested and works */
  // scale is already set up.
  asm {
    PSHS    X,Y,U,D,CC,DP  ; err on the side of safety until I get this working...
    JSR     DP_to_D0
    LDX     list
    JSR     Draw_VLp
    PULS    DP,CC,D,U,Y,X
  }
}

#else /* not cmoc */

#ifdef GCC6809

#include <vectrex.h>  // I think this is Chris's version.  Planning to switch to Peer's C library

#define debugstr(s) /* ignore */

#define signed16 long
#define unsigned16 unsigned long
#define signed8 signed char
#define unsigned8 unsigned char
#define boolean int

// Under GCC, using default header file/library.
// Need to add dots (and lines, not used yet)

// some assembly required...
#define jsrx(v, func)       asm("ldx %0\n\t" \
                                "jsr " #func "\n\t" : : "g" (v) : "d", "x")
#define Draw_VLp(ra) jsrx(ra, 0xF410)   // (pattern y x)* 0x01 

static inline void intensity(unsigned8 brightness) {Intensity_a(brightness);}
static inline void dot(signed8 y, signed8 x) {Dot_d((int)y, (int)x);}
static inline void move(signed8 y, signed8 x) {Moveto_d((int)y, (int)x);}
static inline void reset_beam(void) {Reset0Ref();}
static inline void set_scale(unsigned8 scale) {/*VIA_t1_cnt_lo*/ *(volatile unsigned char *)0xD004 = scale;}
static inline void line(signed8 y, signed8 x) {*(volatile unsigned char *)0xC823 = 0; Draw_Line_d((int)y, (int)x);}
static inline void lines(unsigned8 size, const signed8 *array) { (void)size; (void)array; }
static inline void dots(unsigned8 size, const signed8 *array) { (void)size; (void)array; }
static inline void displaylist(const signed8 *list) { Draw_VLp(list); }
static inline void wait_retrace(void) {Wait_Recal();}

const int stardots[8] = {
  -60, 10,
  71, 50,
  57, -69,
  -66,-61,
};

int rotated[8];

static inline void scale(unsigned int scalefac) {/*VIA_t1_cnt_lo*/ *(volatile unsigned int *)0xD004 = scalefac;}
static inline void rotate(unsigned int angle, unsigned int points, const int *original, int *rotated)
{
  *(volatile unsigned int *)0xC836 = angle;
  *(volatile unsigned int *)0xC823 = points-1;
  Rot_VL((int *)original, rotated);
}

#define signed16 long
#define unsigned16 unsigned long
#define signed8 signed char
#define unsigned8 unsigned char
#define boolean int

#else /* anything except gcc for the 6809 */

#include <stdio.h>

#ifndef __GNUC__
#define inline /* GCC extension not available elsewhere - https://gcc.gnu.org/onlinedocs/gcc/Inline.html#Inline */
#endif

// Portable version - generate a debug trace only!

#define debugstr(s) printf("// %s\n", s)

static inline void wait_retrace(void) {fflush(stdout); printf("  wait_retrace();\n");}
static inline void move(char y, char x) {printf("  move(%d, %d);\n", (int)y, (int)x);}
static inline void line(char y, char x) {printf("  line(%d, %d);\n", (int)y, (int)x);}
#define lines(size, array) printf("  lines(%d, %s);\n", (int)((unsigned char)(size)), #array)
#define dots(size, array) printf("  dots(%d, %s);\n", (int)((unsigned char)(size)), #array)
#define displaylist(array) do { printf("  displaylist(%s);\n", #array); (void)array; } while (0)
static inline void dot(char y, char x) {printf("  dot(%d, %d);\n", (int)y, (int)x);}
static inline void reset_beam(void) {printf("  reset_beam();\n");}
static inline void set_scale(unsigned char scale) {printf("  set_scale(%d);\n", (int)((unsigned char)scale));}
static inline void intensity(char brightness) {printf("  intensity(%d);\n", (int)brightness);}

#define signed16 short
#define unsigned16 unsigned short
#define signed8 char
#define unsigned8 unsigned char
#define boolean int

#endif /* not GCC6809 */

#endif /* not cmoc */

#define MAX_BRIGHTNESS (0x7f)
#define fp2_14 /* SIGNED */ signed16 /* we use a restricted range (2.14) fixed point for trig support */

static signed16 Debug;

// All const arrays in cmoc must come in this section.
// Also, static scalars cannot be explicitly initialised
//  - do so with assignments at program start instead.
// (Need to check if they're all set to 0 on startup)

#ifdef VECTREX
#pragma const_data start
#endif

#ifdef GCC6809
#define IN_ROM __attribute__ ((section(".text")))
#else
#define IN_ROM
#endif

/* Shields get a special proc because they're one continuous line */
static const signed8 shieldvec[] IN_ROM = {
  24,24,  96,-96, 24,24, -72,72, -72,-72, 24,-24, 96,96, 24,-24, -72,-72, -72,72
};

static const signed8 crosshair[] IN_ROM = { 
  (signed8)-1, (signed8)-30, 0,  0, 15, 20,   (signed8)-1, 0, (signed8)-115, 0, (signed8)-15, 20,
  (signed8)-1, 30, 0,   0, (signed8)-10, 20,  (signed8)-1, (signed8)-10, 0,  0, (signed8)-10, 10,
  (signed8)-1, 0, 10,   0, (signed8)-15, 10,  (signed8)-1, 0, (signed8)-30,  0, (signed8)-20, 15,
  (signed8)-1, 105, 0,  0, (signed8)-20, 15,  (signed8)-1, 0, (signed8)-30,  0, (signed8)-20, 10,
  (signed8)-1, 0, 10,   0, (signed8)-10, 10,  (signed8)-1, (signed8)-10, 0,
  1
};

static const fp2_14 sine[65] IN_ROM =  {
    0,        402,    803,   1205,   1605,   2005,   2404,   2801,    3196,    3589,   3980,   4369,   4756,   5139,   5519,   5896,
    6269,    6639,   7005,   7366,   7723,   8075,   8423,   8765,    9102,    9434,   9759,  10079,  10393,  10701,  11002,  11297,
    11585,  11866,  12139,  12406,  12665,  12916,  13159,  13395,    13622,  13842,  14053,  14255,  14449,  14634,  14810,  14978,
    15136,  15286,  15426,  15557,  15678,  15790,  15892,  15985,    16069,  16142,  16206,  16260,  16305,  16339,  16364,  16379,
    16384 // => 1.0
};

#ifdef NOT_YET
// remove asintab until it is needed?  See how small the code can go...

// I've checked the results (see asin_test.c) and they're close enough for game work...
// Can halve the size of this table easily by using rotational symmetry around 0.
// (same as first part of sin table optimisation)

static const fp2_14 asintab[129] IN_ROM = { // multiply by 360 for degrees, by 256 for angles
                               // (float)asintab[x]*(360.0) / (1<<14) would be directly equivalent to scratch's asin
                               // but we want asintab[x]>>6 for 256 angles
  -4096,  -3770,  -3634,  -3530,  -3442,  -3365,  -3294,  -3230,  -3169,  -3112,  -3058,  -3007,  -2958,  -2911,  -2865,  -2821,
  -2778,  -2737,  -2696,  -2657,  -2619,  -2581,  -2544,  -2508,  -2473,  -2438,  -2404,  -2371,  -2338,  -2306,  -2274,  -2242,
  -2211,  -2181,  -2151,  -2121,  -2091,  -2062,  -2033,  -2005,  -1977,  -1949,  -1921,  -1894,  -1867,  -1840,  -1813,  -1787,
  -1760,  -1734,  -1709,  -1683,  -1658,  -1632,  -1607,  -1583,  -1558,  -1533,  -1509,  -1485,  -1460,  -1436,  -1413,  -1389,
  -1365,  -1342,  -1319,  -1295,  -1272,  -1249,  -1226,  -1203,  -1181,  -1158,  -1136,  -1113,  -1091,  -1069,  -1046,  -1024,
  -1002,   -980,   -959,   -937,   -915,   -893,   -872,   -850,  -829,   -807,   -786,   -765,   -743,   -722,   -701,   -680,
  -659,   -638,   -617,   -596,   -575,   -554,   -533,   -513,  -492,   -471,   -450,   -430,   -409,   -389,   -368,   -347,
  -327,   -306,   -286,   -265,   -245,   -224,   -204,   -183,  -163,   -143,   -122,   -102,    -82,    -61,    -41,    -20,
  0,                                                             // X=-X: antisymmetric
};
#endif

#define DEFINE(name) static const signed8 name[] IN_ROM = {
#define move_rel_xy(x,y) 0 /*MOVE*/, ((signed8)y), ((signed8)x)
#define line_rel_xy(x,y) (signed8)-1 /*LINE*/, ((signed8)y), ((signed8)x)
//#define move_rel_xy(x,y) 0 /*MOVE*/, (signed8)((int)y), (signed8)((int)x)
//#define line_rel_xy(x,y) (signed8)-1 /*LINE*/, (signed8)((int)y), (signed8)((int)x)
#define ENDDEF(name) 1 /*STOP*/ }; static void SHOW_##name(void) { displaylist(name); }

#include "font.h"

#include "recording.h"


#ifdef VECTREX
#pragma const_data end
#endif

static const signed8 *digitlist[10] = {
  N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
};

#include "placard.h"

// 16 bit maths, no floats.

static signed16 rseed;
static inline signed16 urandom16(void)
{
  // VECTREX HAS A BUILT-IN RANDOM THAT WE CAN USE!
  // (though it doesn't seem very good - this may be better and faster)
  return (rseed = (rseed * 2053) + 13849);
}

static inline unsigned16 irand(signed16 max) {
  // returns int 0..max-1
  return (unsigned16)(urandom16() % max); // probably not very random, but this is a video game, not crypto
}

static inline signed16 pickrandom(signed16 low, signed16 high)
{
  // We'll just assume that high > low...
  return (signed16)irand(high-low+1)+low;  // pick a random integer between low and high inclusive.
}

#ifdef NOTYET
static unsigned8 numdigits(signed16 num)
{
  if (num < 0) return 1+numdigits(-num);
  if (num < 10) return 1U;
  if (num < 100) return 2U;
  if (num < 1000) return 3U;
  if (num < 10000) return 4U;
  return 5U;
}
#endif

static signed8 pxy[32];
static signed16 pxa[16], pya[16];

static signed16 star_x1(unsigned8 idx) {
  unsigned8 xtype = (idx>>2)&3, ytype = idx&3;

  idx = xtype ^ ytype; // four types of star trail ...
  if (idx == 0) { // left edge
    return -((signed16)127<<3);
  } else if (idx == 2) { // right edge
    return (signed16)127<<3;
  } else { // top or bottom edges
    return pickrandom(-127, 127)<<3;  // could use Scratch's random byte directly...
  }
}

static signed16 star_y1(unsigned8 idx) {
  unsigned8 xtype = (idx>>2)&3, ytype = idx&3;

  idx = xtype ^ ytype; // four types of star trail ...
  if (idx == 1) { // top edge
    return (signed16)127<<3; // right edge
  } else if (idx == 3) { // bottom edge
    return -((signed16)127<<3);
  } else {
    return pickrandom(-127, 127)<<3;
  }
}

#define abs(x) (x<0?-x:x)
static inline boolean clipoff(signed16 x, signed16 y)
{
  return ((abs(x)+abs(y)) < 0x20); // diamond
  //  return ( (-(signed16)0x20 <= x) && (x < (signed16)0x20) && (-(signed16)0x12 <= y) && (y < (signed16)0x12));  // rectangle
}
#undef abs

static void move_star(unsigned8 starno)
{
  signed16 x, y;

  x = pxa[starno]; y = pya[starno];       // coordinate space is 0,0 center!
  x = ((x<<5)-x)>>5; y = ((y<<5)-y)>>5;   // move stars closer to the center, ie towards 0
  if (clipoff((signed16)x>>(signed16)4,(signed16)y>>(signed16)4)) {  // ANSI C paranoia
    x = star_x1(starno); y = star_y1(starno); // reset when they disappear
  }
  pxa[starno] = x; pya[starno] = y;
}

static inline void plot_star(unsigned8 starno)
{
  signed16 brightx, brighty;
  if (pxa[starno] < 0) brightx = -pxa[starno]; else brightx = pxa[starno];
  brightx = (brightx>>3)&127;
  if (pya[starno] < 0) brighty = -pya[starno]; else brighty = pya[starno];
  brighty = (brighty>>3)&127;
  // take this out if we don't want fading over distance...
  // If we don't adjust individual star intensities, we can use
  // the 'dots()' procedure to draw them all at once...
  intensity((char)((brightx+brighty)>>1)); // good enough approximation for hypotenuse :-)
  dot((signed8)(pxa[starno]>>4),(signed8)(pya[starno]>>4));
  move((signed8)(-(pxa[starno]>>4)),(signed8)(-(pya[starno]>>4))); // correct back to 0,0 for next dot.
}

static inline void init_stars(void)
{
  unsigned8 i, star;

  for (star = 0U; star < 16U; star++) {
    pxa[star] = star_x1(star); pya[star] = star_y1(star);
    for (i=0; i < star*13; i++) move_star(star); // skew the starting points (QUICK HACK)
  }
}

static void stars(unsigned8 speed) // will always be centered on 0,0
{
  unsigned8 star;
  int i;

  debugstr("stars");

  for (star = 0U; star < 16U; star++) {
    for (i = 0U; i < speed; i++) move_star(star);
  }

  for (star = 0U; star < 16U; star++) {
    if ((star & 15) == 0) {
      // control the frequency that the beam is reset!
      // Use a smaller mask if there is jitter if only
      // doing this once every 16 stars
      reset_beam();
      set_scale(0xD0);
      move(0, 0);
    }
    plot_star(star);
  }
return; // have not yet got drawlist version working :-(

 {
  int angle=63, sc = (int)0xFF;
  for (;;) {
    for (i = 0; i < 0x30; i++) {
      Wait_Recal();
      *(volatile char *)0xC823 = 3;
      Intensity_a(((unsigned int)sc-(unsigned int)0xBF)/2U);
      scale((unsigned int)sc-(unsigned int)0xBF);
      Dot_List((void *)stardots);  Reset0Ref(); 
 
      rotate((unsigned int)((angle+11)&63), (unsigned int)4, stardots, rotated);
      *(volatile char *)0xC823 = 3;
      Intensity_a(((unsigned int)sc-(unsigned int)0x7F)/2U);
      scale((unsigned int)sc-(unsigned int)0x7F);
      Dot_List((void *)rotated);   Reset0Ref();     

      rotate((unsigned int)((angle+14)&63), (unsigned int)4, stardots, rotated);
      *(volatile char *)0xC823 = 3;
      Intensity_a(((unsigned int)sc-(unsigned int)0x3F)/2U);
      scale((unsigned int)sc-(unsigned int)0x3F);
      Dot_List((void *)rotated);   Reset0Ref();     

      rotate((unsigned int)((angle+4)&63), (unsigned int)4, stardots, rotated);
      *(volatile char *)0xC823 = 3;
      scale((unsigned int)sc);
      Intensity_a(((unsigned int)sc)/2U);
      Dot_List((void *)rotated);        
      sc -= 4;
    };
  }
 }

  reset_beam();
  set_scale(0x70);
  for (star = 0U; star < 16U; star++) {
    pxy[star+star] = (signed8)((signed16)(((signed16)pxa[(star+1)&15] >> (signed16)4) - ((signed16)pxa[star] >> (signed16)4)));
    pxy[star+star+1] = (signed8)((signed16)(((signed16)pya[(star+1)&15] >> (signed16)4) - ((signed16)pya[star] >> (signed16)4)));
  }
  move((signed8)((signed16)pxa[0]>>(signed16)4), (signed8)((signed16)pya[1]>>(signed16)4));
  dots(16, pxy);
}

static void position_and_scale(signed8 absx, signed8 absy, signed16 scale)
{
  reset_beam();
  set_scale(0x7f);
  move(absy, absx);
  set_scale((unsigned8)scale);
}

static inline void position_and_scale_and_intensity(signed8 absx, signed8 absy, signed16 scale, unsigned8 bright)
{
  position_and_scale(absx, absy, scale);
  intensity(bright);
}

/* Shields on the vectrex are sideways wrt the 'real' tailgunner */
static void draw_shields(unsigned8 scale)
{
  const signed8 *ptr = shieldvec;
  signed16 i;
  signed8 x1, y1;

  debugstr("draw_shields");

  position_and_scale(0, 0, scale);

  //  24,24,  96,-96, 24,24, -72,72, -72,-72, 24,-24, 96,96, 24,-24, -72,-72, -72,72
  move(shieldvec[18], shieldvec[0]); /* Should move the starting point into the array... */
  for (i = 0; i < 10; i++) {         /* DRAW THE VECTOR */
    y1 = (*ptr++); x1 = (*ptr++);
    line(y1, x1);                    // Swapped x for y because of portrait mode Vectrex display
  }
}

static inline void Draw_crosshair(signed8 absx, signed8 absy)
{
  debugstr("Draw_crosshair");

  position_and_scale(absx, absy, 0x18);
  displaylist(crosshair);
}

/* 3d rendering */

static unsigned8 Credits;

static unsigned8 intro_rot;
static signed16 frame_number;
static unsigned8 global_flashing_intensity;

static signed16 HighScore;
static signed16 LastScore;
static signed16 Score;

#ifdef NOTYET
static signed16 UsingShields;
static signed16 Shields;
static signed16 shieldsegment;
static signed16 shieldsubticksleft;
#endif

static inline fp2_14 sinsymmetry(unsigned8 angle128)
{
  // '>', not '>=', is a special case for sin(x)=1.0
  if (angle128 > 64U) return sine[128-angle128]; else return sine[angle128];
}

static inline fp2_14 fp2_14_sin(signed16 angle256)
{
  if ((unsigned8)angle256 >= 128U) return -sinsymmetry((unsigned8)(angle256-128)&127); else return sinsymmetry((unsigned8)angle256&127);
}

static inline fp2_14 fp2_14_cos(signed16 angle256)
{
  return fp2_14_sin(angle256+64); // implicit &255 in these unsigned8 parameters
}

// The revolving intro placard...

static void drawtgintro(unsigned8 scale, unsigned8 bright) {
  position_and_scale_and_intensity(0,0, (unsigned8)((signed16)scale*(signed16)2/(signed16)5), bright);
  displaylist((signed8 *)placard[((unsigned8)intro_rot+128)&255]);
}

static inline void show_digit(signed8 digit)
{
  displaylist(digitlist[(int)digit]);

#ifdef NEVER // previous version
  switch (digit) {
    case 0: SHOW_N0(); break;
    case 1: SHOW_N1(); break;
    case 2: SHOW_N2(); break;
    case 3: SHOW_N3(); break;
    case 4: SHOW_N4(); break;
    case 5: SHOW_N5(); break;
    case 6: SHOW_N6(); break;
    case 7: SHOW_N7(); break;
    case 8: SHOW_N8(); break;
    case 9: SHOW_N9(); break;
  }
#endif
}

static void SHOW_NUM(signed16 num, signed8 absx, signed8 absy, unsigned16 scale) { // left-aligned
  signed8 digit, zeroes;

  if (scale) position_and_scale(absx, absy, 0x20);

  // This replaces code that used divide by 10 and modulo 10.  Much faster.

  // handles full 16 bit range of -32768:32767  -  Uses negative numbers to avoid the issue of negating -32768

  if (num >= 0) num = -num; /* else MINUS(); */  // TO DO: add a font character for '-'.
  digit = 0;
  zeroes = 1; // CLRing is shorter
  // max 11 add/subtracts...
  if (num <= -20000) { num += 20000; digit += 2; zeroes = 0; }
  if (num <= -10000) { num += 10000; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  digit = 0;
  if (num <= -8000) { num += 8000; digit += 8; zeroes = 0; } else if (num <= -4000) { num += 4000; digit += 4; zeroes = 0; }
  if (num <= -2000) { num += 2000; digit += 2; zeroes = 0; }
  if (num <= -1000) { num += 1000; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  digit = 0;
  if (num <= -800) { num += 800; digit += 8; zeroes = 0; } else if (num <= -400) { num += 400; digit += 4; zeroes = 0; }
  if (num <= -200) { num += 200; digit += 2; zeroes = 0; }
  if (num <= -100) { num += 100; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  digit = 0;
  if (num <= -80) { num += 80; digit += 8; zeroes = 0; } else if (num <= -40) { num += 40; digit += 4; zeroes = 0; }
  if (num <= -20) { num += 20; digit += 2; zeroes = 0; }
  if (num <= -10) { num += 10; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  show_digit((signed8)-num);
}

static void Draw_lastscore(void)
{
  debugstr("Draw_lastscore");
  position_and_scale(-100,127,32);
  SHOW_SCORE();
  SHOW_NUM(LastScore, -98,113, 256);
}

static void Draw_highscore(void)
{
  debugstr("Draw_highscore");
  position_and_scale(40,127,32);
  SHOW_HIGH_SCORE();
  SHOW_NUM(HighScore, 52,113, 256);
}

static void Draw_insertcoin(void) // Not yet used
{
  debugstr("Draw_insertcoin");
  intensity(global_flashing_intensity<<1);
  position_and_scale(-40,-80,32);
  SHOW_INSERT_COIN();
}

static void Draw_start(void)
{
  debugstr("Draw_start");
  intensity(global_flashing_intensity<<1);
  position_and_scale(-39,-80,32);
  SHOW_PRESS_START();
}

static void Draw_credits(void)
{
  debugstr("Draw_credits");
  position_and_scale(-46,-30,48);
  SHOW_CREDITS();
  if (Credits > 9U) {
    SHOW_NUM(9, 0,0,0); // display any more than 9 as 9. (This is what many arcade machines did in real life)
  } else {
    SHOW_NUM(Credits, 0,0,0);
  }
}

static void Draw_ships_remaining(void)
{
  SHOW_NUM(10, 90,120, 64);
}

static void Draw_shields_remaining(void)
{
  SHOW_NUM(80, -5,127, 128);
}

static void Draw_score(void)
{
  SHOW_NUM(Score, -100,120, 64);
}

static void next_frame(void)
{
  // do things here that must be done on every frame, eg polling buttons/joystick
  debugstr("next_frame");
  wait_retrace();
  if ((frame_number & 16) == 0) {
    global_flashing_intensity += 4; // 16 frames of getting brighter
  } else {
    global_flashing_intensity -= 4; // then 16 frames of getting darker
  }
  frame_number++; // wraps.
  //SHOW_NUM(Debug, -100,-100, 128);
}

int main(void) { // cmoc doesn't allow argc, argv
  signed16 frames;
  unsigned8 placard_scale, placard_brightness;

  Debug = Score = HighScore = LastScore = rseed = frame_number = (signed16)(Credits = global_flashing_intensity = 0);

  init_stars();

  position_and_scale_and_intensity(0,0, 0x7f, MAX_BRIGHTNESS);

  Score = 72; HighScore = 2047; LastScore = 132; // only for demo.

  for (;;) {
    debugstr("main loop");

    // approaching banner:

    placard_scale = (unsigned8)((signed16)(0xFF-160));
    placard_brightness = (unsigned8)((signed16)(((signed16)MAX_BRIGHTNESS+(signed16)MAX_BRIGHTNESS-160)));
    intro_rot = 128;
    // start at 128 step by -2  end at 64 after one full revolution (128 + 32 steps)
    for (frames = 0; frames < 160; frames++) {
      next_frame();
      drawtgintro(placard_scale, placard_brightness>>1);
      placard_scale++; placard_brightness++;
      stars(1);
      intro_rot -= 2;
    }

    {signed16 i;
      for (i = 0; i < 2; i++) {
        placard_brightness = MAX_BRIGHTNESS&0xF8;
        while (placard_brightness != 0) {
          next_frame();
          drawtgintro(placard_scale, placard_brightness);
          stars(1);
          placard_brightness -= 8;
        }
        while (placard_brightness != (MAX_BRIGHTNESS&0xF8)) {
          placard_brightness += 8;
          next_frame();
          drawtgintro(placard_scale, placard_brightness);
          stars(1);
        }
      }
    }

    placard_brightness = MAX_BRIGHTNESS&0xF8;
    while (placard_brightness != 0) {
      next_frame();
      drawtgintro(placard_scale, placard_brightness);
      stars(1);
      placard_brightness -= 8;
    }

    //stars:
    debugstr("wait for coins...");
    global_flashing_intensity = 0; frame_number = 0; // start flashing from off position
    for (frames = 0; frames < 255; frames++) {
      next_frame();
      stars(1);
      if (frames < 80) {
        Draw_insertcoin();
        intensity(MAX_BRIGHTNESS);
        Draw_lastscore();
        Draw_highscore();
      } else if (frames < 160) {
        if (frames == 80) Credits += 1;
        if (frames == 120) Credits += 1;
        Draw_start();
        intensity(MAX_BRIGHTNESS);
        Draw_credits();
        Draw_lastscore();
        Draw_highscore();
      } else {
        intensity(MAX_BRIGHTNESS);
        Draw_ships_remaining();
        Draw_shields_remaining();
        Draw_score();
        Draw_crosshair((signed8)(fp2_14_sin(frames)>>8), (signed8)(fp2_14_cos(frames)>>8));
      }
    }
    Credits = 0;
    // shields:
    debugstr("shields...");
    for (frames = 0; frames < 200; frames++) {
      next_frame();
      if ((frames > 120) && (frames < 200)) {
        intensity((unsigned8)pickrandom(64,127));
        if (pickrandom(0,31)) draw_shields(0xF0);
      } else {
        Draw_crosshair((signed8)(fp2_14_sin(frames)>>8), (signed8)(fp2_14_cos(frames)>>8));
      }
      stars(1);
      intensity(MAX_BRIGHTNESS);
      Draw_ships_remaining();
      Draw_shields_remaining();
      Draw_score();
    }
    // whoosh:
    debugstr("whoosh...");
    for (frames = 0; frames < 64; frames++) {
      next_frame();
      stars(3);
      intensity((unsigned8)(64-frames)*2); // fade out
      Draw_ships_remaining();
      Draw_shields_remaining();
      Draw_score();
    }
  }
  return 0;
  SHOW_N0();
  SHOW_N1();
  SHOW_N2();
  SHOW_N3();
  SHOW_N4();
  SHOW_N5();
  SHOW_N6();
  SHOW_N7();
  SHOW_N8();
  SHOW_N9();
}
