--- xandoz.c	2019-10-05 10:29:59.643225374 -0700
+++ xandoz-beta4.c	2019-10-04 19:17:41.116804199 -0700
@@ -1,5 +1,70 @@
 #include <vectrex.h>
 
+// position-independent code to draw a circle at x,y extracted from circle.bin using:
+#ifdef NEVER
+#include <stdio.h>
+#include <stdlib.h>
+int main(int argc, char **argv) {
+  FILE *circ = fopen("pang8_0.bin", "rb");
+  int c1, c2, c3, c4;
+  c1 = fgetc(circ);  c2 = fgetc(circ);  c3 = fgetc(circ);  c4 = fgetc(circ);
+  for (;;) {
+    if (c1 == EOF) exit(1);
+    if (c1 == c2 && c3 == c4 && c2 == c3 && c1 == 'x') break; // remainder of file is relocatable code!
+    c1 = c2; c2 = c3; c3 = c4; c4 = fgetc(circ);
+  }
+  fprintf(stdout, "const unsigned char drawcirc[] = {\n ");
+  c1 = 15; c3 = 0;
+  for (;;) {
+    c2 = fgetc(circ);
+    if (c2 == EOF) break;
+    fprintf(stdout, " %3d,", c2);
+    c3++; if ((c3&c1) == 0) fprintf(stdout, "\n ");
+  }
+  fprintf(stdout, "\n};\n");
+  exit(0);
+}
+#endif
+// the position-independent code in circle.asm follows the string "xxxx" which is used
+// as a delimeter...
+const unsigned char drawcirc[] = {
+  134, 204, 151,  12, 134, 129, 151,   0, 134,  79, 151,   1, 134, 132, 151,   0,
+   12,   0, 134, 152, 151,  11, 134, 127, 183, 208,   4, 134, 129, 151,   0, 134,
+  204, 151,  12, 134,  95, 151,   1, 134, 132, 151,   0,  12,   0, 134, 152, 151,
+   11,  55,   6, 151,   1,  15,   0,  52,   6, 134, 206, 151,  12,  15,  10,  12,
+    0, 215,   1,  15,   5,  53,   6,  77,  42,   4,  64,  40,   1,  74,  93,  42,
+    4,  80,  40,   1,  90, 231, 127, 170, 127, 198,  64, 129,  64,  35,  19, 129,
+  100,  35,   4, 134,   8,  32,   2, 134,   4, 213,  13,  39, 252,  74,  38, 253,
+   32,   4, 213,  13,  39, 252,  15,  11, 134, 128, 151,   0, 134, 246, 151,   1,
+  134, 129, 151,   0, 134, 255, 151,   1, 134, 238, 151,  12, 134,   1, 151,   0,
+  134, 253, 151,   1, 134, 250, 151,   1, 134, 246, 151,   1, 134, 226, 151,   1,
+  134, 129, 151,   0, 134, 128, 151,   0, 134,  10, 151,   1, 134, 129, 151,   0,
+  134, 226, 151,   1, 134,   1, 151,   0, 134, 246, 151,   1, 134, 250, 151,   1,
+  134, 253, 151,   1, 134, 255, 151,   1, 134, 129, 151,   0, 134,   1, 151,   1,
+  134,   1, 151,   0, 134,   3, 151,   1, 134,   3, 151,   1, 134,   6, 151,   1,
+  134,  10, 151,   1, 134,  30, 151,   1, 134, 129, 151,   0, 134, 128, 151,   0,
+  134, 246, 151,   1, 134, 129, 151,   0, 134,  30, 151,   1, 134,   1, 151,   0,
+  134,  10, 151,   1, 134,   6, 151,   1, 134,   3, 151,   1, 134,   1, 151,   1,
+  134, 129, 151,   0, 134, 204, 151,  12, 134, 111, 151,   1, 134, 132, 151,   0,
+   12,   0, 134, 152, 151,  11, 134,  65, 198, 131, 151,   1,  15,   0,  52,   6,
+  134, 206, 151,  12,  15,  10,  12,   0, 215,   1,  15,   5,  53,   6,  77,  42,
+    4,  64,  40,   1,  74,  93,  42,   4,  80,  40,   1,  90, 231, 127, 170, 127,
+  198,  64, 129,  64,  35,  19, 129, 100,  35,   4, 134,   8,  32,   2, 134,   4,
+  213,  13,  39, 252,  74,  38, 253,  32,   4, 213,  13,  39, 252,  57,
+};
+
+#define gosub(x,y,func) \
+  asm(" lda %0\n"                       \
+      " ldb %1\n"                       \
+      " ldu -16,s\n"                    \
+      " pshu d\n"                       \
+      " jsr _drawcirc\n" :                      /* outputs */ \
+                         : "g" (x),  "g" (y)    /* inputs */  \
+                         : "d", "x", "y", "u"); /* clobbered */
+
+void draw_circle(int x, int y) {
+  gosub(x,y,drawcirc);
+}
 // sound does not work yet.  As well as feedback sound for placing or failing
 // to place your mark, also need a little tune when either player wins.
 
@@ -110,44 +175,121 @@
 // scaling values.  First we position the level, then the square within the level, and
 // finally the letter itself.
 
+void Join(int c1, int r1, int l1,
+          int c2, int r2, int l2) {
+//            x       y       z
+//           col     row    layer
+
+//   Using global coordinates, locate the center of any square
+//                                                (found by inspection)
+//   Y(row, layer) = -72+(layer-1)*38+(row-1)*8
+//   X(row, column, layer) = -39+(row-1)*8+(column-1)*8
+//
+  int x1, y1, x2, y2;
+
+  if (((l1 == 4) && (l2 == 1))
+   || ((l1 == 1) && (l2 == 4))) { // only endpoints on extreme levels (1 and 4) need special handling
+    // Long vector draws have to be split because > 127 units
+
+    // not sure if a coding error or a compiler bug, but the /3 version fails
+    // on some particular inputs :-(
+    int Dc = 0; //= (c1-c2)/3;
+    int Dr = 0; //= (r1-r2)/3;  // Dr or Dc will be 0 if in the same plane.
+    int Dl = 0; //= (l1-l2)/3;
+
+    if (c2>c1) Dc = -1; else if (c2<c1) Dc = 1;
+    if (r2>r1) Dr = -1; else if (r2<r1) Dr = 1;
+    if (l2>l1) Dl = -1; else if (l2<l1) Dl = 1;
+
+    // A winning line from the computer is galling.
+    // Gallia est omnis divisa in partes tres
+    Join(c1,   r1,   l1,       c1-Dc,r1-Dr,l1-Dl);
+    Join(c1-Dc,r1-Dr,l1-Dl,    c2+Dc,r2+Dr,l2+Dl);
+    Join(c2+Dc,r2+Dr,l2+Dl,    c2,   r2,   l2);
+    return;
+  }
+
+//   int SY, SX;
+//  z -= 1; x -= 1; y -= 1;
+//  SX = y*16+x*16-127+51;   // 3,3,3 ->  3*16 + 3*16 - 127 +51 = 48+48 -127 +51
+//  SY = y*8+z*64-127;   //           3*16 + 3*75 - 127 -16 = 48 + 225 - 127 -16 = 273-127-16 = 130
+
+
+
+
+//  x1 = -39+(r1-1)*8+(c1-1)*8; y1 = -72+(l1-1)*38+(r1-1)*8;
+//  x2 = -39+(r2-1)*8+(c2-1)*8; y2 = -72+(l2-1)*38+(r2-1)*8;
+
+r1 -= 1; c1 -= 1; l1 -= 1;
+r2 -= 1; c2 -= 1; l2 -= 1;
+  x1 = r1*16+c1*16-127+51;   // 3,3,3 ->  3*16 + 3*16 - 127 +51 = 48+48 -127 +51
+  y1 = r1*8+l1*64-127;   //           3*16 + 3*75 - 127 -16 = 48 + 225 - 127 -16 = 273-127-16 = 130
+
+  x2 = r2*16+c2*16-127+51;   // 3,3,3 ->  3*16 + 3*16 - 127 +51 = 48+48 -127 +51
+  y2 = r2*8+l2*64-127;   //           3*16 + 3*75 - 127 -16 = 48 + 225 - 127 -16 = 273-127-16 = 130
+
+  Intensity_7F(); Reset0Ref(); set_scale(0x80);
+  Moveto_d(y1,x1); Lineto_d(y2-y1,x2-x1);
+}
 // I manually worked out a formula for going directly to the square independent of level, which
 // I used in the "Join" procedure to draw a (graphical) line through a winning line.  Using
 // that same formula here would eliminate one of the vector moves.  The only question is whether
 // the letters would be placed as perfectly within the boxes as they currently are, or whether
 // they would be a smidgeon off center depending on level (due to coarseness of the 256x256 grid)
 
-static inline void draw_X(int x, int y, int z) {
+static inline void draw_O(int x, int y, int z) {
+#ifdef DIAMOND_APPROXIMATION
   z -= 3; x -= 1; y -= 1; y *= 30;
   Reset0Ref(); set_scale(0xf0); Moveto_d(z*40+3, -44);
   set_scale(0x41);
   MoveRel((x<<5)-x, y);MoveRel(y-3, 0);
   set_scale(0x10); LineRel(96, 40); MoveRel(-40,-40); LineRel(-16, 40);
+#else
+  int SY, SX;
+  Reset0Ref();
+  z -= 1; x -= 1; y -= 1;
+  SX = y*16+x*16-127+51;   // 3,3,3 ->  3*16 + 3*16 - 127 +51 = 48+48 -127 +51
+  SY = y*8+z*64-(z>>1)-127;   //           3*16 + 3*75 - 127 -16 = 48 + 225 - 127 -16 = 273-127-16 = 130
+  draw_circle(SY,SX);
+#endif
 }
 
-static inline void draw_O(int x, int y, int z) {
+static inline void draw_X(int x, int y, int z) {
+#ifdef DIAMOND_APPROXIMATION
   z -= 3; x -= 1; y -= 1; y *= 30;
   Reset0Ref(); set_scale(0xf0); Moveto_d(z*40+3, -44);
   set_scale(0x41); MoveRel((x<<5)-x, y);MoveRel(y, 0);
   set_scale(0x0c); LineRel(16, 32); LineRel(80, 32); LineRel(-16, -32); LineRel(-80, -32);
+#else
+  int SY, SX;
+//  0 1 2 3
+//  0 0 1 2
+//  0 0 2 4
+  z -= 1; x -= 1; y -= 1;
+  SX = y*16+x*16-127+51;   // 3,3,3 ->  3*16 + 3*16 - 127 +51 = 48+48 -127 +51
+  SY = y*8+z*64-(z>>1)-127;   //           3*16 + 3*75 - 127 -16 = 48 + 225 - 127 -16 = 273-127-16 = 130
+  Reset0Ref(); set_scale(0x80); Moveto_d(SY,SX);
+  set_scale(0x10); MoveRel(-70,-16); LineRel(127, 40); MoveRel(-54,-40); LineRel(-4, 40);
+#endif
 }
 
 void DrawGrid(int z) {
   z -= 3;
-  Reset0Ref(); set_scale(0xf0); Moveto_d(z*40, -50);
+  Reset0Ref(); set_scale(0xd2); Moveto_d(z*39-2, -57);
   set_scale(0x40);
-                   Lineto_d(124, 124);
-  Moveto_d(0, 31); Lineto_d(-124, -124);
-  Moveto_d(0, 31); Lineto_d(124, 124);
-  Moveto_d(0, 31); Lineto_d(-124, -124);
-  Moveto_d(0, 31); Lineto_d(124, 124);
+                   Lineto_d(62, 124);
+  Moveto_d(0, 31); Lineto_d(-62, -124);
+  Moveto_d(0, 31); Lineto_d(62, 124);
+  Moveto_d(0, 31); Lineto_d(-62, -124);
+  Moveto_d(0, 31); Lineto_d(62, 124);
 
-  Reset0Ref(); set_scale(0xf0); Moveto_d(z*40, -50);
+  Reset0Ref(); set_scale(0xd2); Moveto_d(z*39-2, -57);
   set_scale(0x40);
-                    Lineto_d(0, 124);
-  Moveto_d(31, 31); Lineto_d(0, -124);
-  Moveto_d(31, 31); Lineto_d(0, 124);
-  Moveto_d(31, 31); Lineto_d(0, -124);
-  Moveto_d(31, 31); Lineto_d(0, 124);
+                   Lineto_d(0, 124);
+  Moveto_d(16,31); Lineto_d(0, -124);
+  Moveto_d(16,31); Lineto_d(0, 124);
+  Moveto_d(16,31); Lineto_d(0, -124);
+  Moveto_d(16,31); Lineto_d(0, 124);
 }
 
 
@@ -226,28 +368,28 @@
 void DrawMenu(int selected) {
   Intensity_5F();
   if (selected == FLIP_REQUESTED) Intensity_7F();
-  Print_Str_d(-60, 50, "FLIP\x80");
+  Print_Str_d(-60, 40, "FLIP\x80");
   if (selected == FLIP_REQUESTED) Intensity_5F();
   if (selected == SCRAMBLE_REQUESTED) Intensity_7F();
-  Print_Str_d(-40, 50, "SCRAMBLE\x80");
+  Print_Str_d(-40, 40, "SCRAMBLE\x80");
   if (selected == SCRAMBLE_REQUESTED) Intensity_5F();
   if (selected == INVERT_REQUESTED) Intensity_7F();
-  Print_Str_d(-20, 50, "INVERT\x80");
+  Print_Str_d(-20, 40, "INVERT\x80");
   if (selected == INVERT_REQUESTED) Intensity_5F();
   if (selected == ROTATE_REQUESTED) Intensity_7F();
-  Print_Str_d(0, 50, "ROTATE\x80");
+  Print_Str_d(0, 40, "ROTATE\x80");
   if (selected == ROTATE_REQUESTED) Intensity_5F();
   if (selected == TUMBLE_REQUESTED) Intensity_7F();
-  Print_Str_d(20, 50, "TUMBLE\x80");
+  Print_Str_d(20, 40, "TUMBLE\x80");
   if (selected == TUMBLE_REQUESTED) Intensity_5F();
   if (selected == WHIRL_REQUESTED) Intensity_7F();
-  Print_Str_d(40, 50, "WHIRL\x80");
+  Print_Str_d(40, 40, "WHIRL\x80");
   if (selected == WHIRL_REQUESTED) Intensity_5F();
   //if (selected == HELP_REQUESTED) Intensity_7F();
-  //Print_Str_d(60, 50, "HELP\x80");
+  //Print_Str_d(60, 40, "HELP\x80");
   //if (selected == HELP_REQUESTED) Intensity_5F();
   if (selected == QUIT_REQUESTED) Intensity_7F();
-  Print_Str_d(80, 50, "QUIT\x80");
+  Print_Str_d(80, 40, "QUIT\x80");
 }
 
 int check_human_input(int request) {
@@ -525,45 +667,7 @@
     return sinsymmetry(angle256&127U);
 }
 
-void Join(int c1, int r1, int l1,
-          int c2, int r2, int l2) {
-//            x       y       z
-//           col     row    layer
-
-//   Using global coordinates, locate the center of any square
-//                                                (found by inspection)
-//   Y(row, layer) = -72+(layer-1)*38+(row-1)*8
-//   X(row, column, layer) = -39+(row-1)*8+(column-1)*8
-//
-  int x1, y1, x2, y2;
-
-  if (((l1 == 4) && (l2 == 1))
-   || ((l1 == 1) && (l2 == 4))) { // only endpoints on extreme levels (1 and 4) need special handling
-    // Long vector draws have to be split because > 127 units
-
-    // not sure if a coding error or a compiler bug, but the /3 version fails
-    // on some particular inputs :-(
-    int Dc = 0; //= (c1-c2)/3;
-    int Dr = 0; //= (r1-r2)/3;  // Dr or Dc will be 0 if in the same plane.
-    int Dl = 0; //= (l1-l2)/3;
-
-    if (c2>c1) Dc = -1; else if (c2<c1) Dc = 1;
-    if (r2>r1) Dr = -1; else if (r2<r1) Dr = 1;
-    if (l2>l1) Dl = -1; else if (l2<l1) Dl = 1;
-
-    // A winning line from the computer is galling.
-    // Gallia est omnis divisa in partes tres
-    Join(c1,   r1,   l1,       c1-Dc,r1-Dr,l1-Dl);
-    Join(c1-Dc,r1-Dr,l1-Dl,    c2+Dc,r2+Dr,l2+Dl);
-    Join(c2+Dc,r2+Dr,l2+Dl,    c2,   r2,   l2);
-    return;
-  }
 
-  Intensity_7F(); set_scale(0xff); Reset0Ref(); 
-  x1 = -39+(r1-1)*8+(c1-1)*8; y1 = -72+(l1-1)*38+(r1-1)*8;
-  x2 = -39+(r2-1)*8+(c2-1)*8; y2 = -72+(l2-1)*38+(r2-1)*8;
-  Moveto_d(y1,x1); Lineto_d(y2-y1,x2-x1);
-}
 
 int main(void)
 {
@@ -572,7 +676,7 @@
   int tick = 0;
   unsigned int flash_timer = 0;
   unsigned int lockout_timer = 0;
-  int HintLoc = -110;
+  int HintLoc = 127; //-110;
   unsigned long hint_timer = 0L;
 #define HINT_DELAY 1000L
   int buttons;
@@ -637,6 +741,7 @@
     }
     // now draw board...
     Wait_Recal(); // sets dp to d0, and pos at 0, 0  No drawing above this line.
+
     if (sound_wanted) {
       // trying to replicate http://vectorgaming.proboards.com/thread/1850/explosion-snd-example-never-before
       // but not working too well!!!
@@ -762,7 +867,7 @@
     if (status_ticker > 0U) {
       Reset0Ref();
       //set_scale(0xdf);
-      Print_Str_d(0, -100, status);
+      Print_Str_d(-15, -100, status);
       status_ticker -= 1U;
     }
 
@@ -786,7 +891,7 @@
       }
 
       if (step_x || step_y || step_z) {
-        hint_timer = 0L; HintLoc = -110; // reset timeout if any button pressed...
+        hint_timer = 0L; HintLoc = 127; /*-110;*/ // reset timeout if any button pressed...
         status[0] = '\x80'; status[1] = '\0'; status_ticker = 0;
       }
 
@@ -844,9 +949,9 @@
       step_x = step_y = step_z = place_mark = 0;
       } // lockout timer
       tick = 0;
-      if (hint_timer >= HINT_DELAY) {
-        HintLoc++; if (HintLoc == 110) HintLoc = -110;
-      }
+      //if (hint_timer >= HINT_DELAY) {    // no longer scrolling this...
+        //HintLoc++; if (HintLoc == 110) HintLoc = -110;
+      //}
     } // animation delay
     if (lockout_timer) lockout_timer -= 1U; // every frame
     if (hint_timer < 32767L) hint_timer += 1L; // max out to avoid wraparound
