static inline void set_scale(unsigned int scale) {*(volatile unsigned char *)0xD004 = scale;}
static inline void displaylist(const int *list) { Draw_VLp((int *)list); };

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

DEFINE(MINUS)
  move_rel_xy(4,8),  // to 8,4
  line_rel_xy(14,0), // to 8,20
  move_rel_xy(4,-8), // to 0,24
ENDDEF(MINUS)

DEFINE(N0)
  move_rel_xy(0,24), // to 0,24
  line_rel_xy(16,0), // to 16,24
  line_rel_xy(0,-24), // to 16,0
  line_rel_xy(-16,0), // to 0,0
  line_rel_xy(0,24), // to 0,24
  move_rel_xy(24,-24), // to 24,0
ENDDEF(N0)

DEFINE(N1)
  move_rel_xy(8,0), // to 8,0
  line_rel_xy(0,24), // to 8,24
  move_rel_xy(16,-24), // to 24,0
ENDDEF(N1)

DEFINE(N2)
  move_rel_xy(0,24), // to 0,24
  line_rel_xy(16,0), // to 16,24
  line_rel_xy(0,-12), // to 16,12
  line_rel_xy(-16,0), // to 0,12
  line_rel_xy(0,-12), // to 0,0
  line_rel_xy(16,0), // to 16,0
  move_rel_xy(8,0), // to 24,0
ENDDEF(N2)

DEFINE(N3)
  line_rel_xy(16,0), // to 16,0
  move_rel_xy(-8,12), // to 8,12
  line_rel_xy(8,0), // to 16,12
  move_rel_xy(0,-12), // to 16,0
  line_rel_xy(0,24), // to 16,24
  line_rel_xy(-16,0), // to 0,24
  move_rel_xy(24,-24), // to 24,0
ENDDEF(N3)

DEFINE(N4)
  move_rel_xy(0,24), // to 0,24
  line_rel_xy(0,-12), // to 0,12
  line_rel_xy(16,0), // to 16,12
  move_rel_xy(-8,0), // to 8,12
  line_rel_xy(0,-12), // to 8,0
  move_rel_xy(16,0), // to 24,0
ENDDEF(N4)

DEFINE(N5)
  line_rel_xy(16,0), // to 16,0
  line_rel_xy(0,12), // to 16,12
  line_rel_xy(-16,0), // to 0,12
  line_rel_xy(0,12), // to 0,24
  line_rel_xy(16,0), // to 16,24
  move_rel_xy(8,-24), // to 24,0
ENDDEF(N5)

DEFINE(N6)
  move_rel_xy(0,12), // to 0,12
  line_rel_xy(16,0), // to 16,12
  line_rel_xy(0,-12), // to 16,0
  line_rel_xy(-16,0), // to 0,0
  line_rel_xy(0,24), // to 0,24
  move_rel_xy(24,-24), // to 24,0
ENDDEF(N6)

DEFINE(N7)
  move_rel_xy(8,0), // to 8,0
  line_rel_xy(8,24), // to 16,24
  line_rel_xy(-16,0), // to 0,24
  move_rel_xy(24,-24), // to 24,0
ENDDEF(N7)

DEFINE(N8)
  line_rel_xy(16,0), // to 16,0
  move_rel_xy(-16,24), // to 0,24
  line_rel_xy(16,0), // to 16,24
  move_rel_xy(-16,-12), // to 0,12
  line_rel_xy(16,0), // to 16,12
  move_rel_xy(0,12), // to 16,24
  line_rel_xy(0,-24), // to 16,0
  move_rel_xy(-16,24), // to 0,24
  line_rel_xy(0,-24), // to 0,0
  move_rel_xy(24,0), // to 24,0
ENDDEF(N8)

DEFINE(N9)
  move_rel_xy(16,24), // to 16,24
  line_rel_xy(-16,0), // to 0,24
  line_rel_xy(0,-12), // to 0,12
  line_rel_xy(16,0), // to 16,12
  move_rel_xy(0,12), // to 16,24
  line_rel_xy(0,-24), // to 16,0
  move_rel_xy(4,0), // to 24,0
ENDDEF(N9)

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

static inline void show_digit(int digit)
{
  displaylist(digitlist[(int)digit]);
}
static void position_and_scale(int absx, int absy, unsigned int scale)
{
  Reset0Ref();
  set_scale(0x7f);
  Moveto_d(absy, absx);
  set_scale(scale);
}
static void SHOW_SIGNED_NUM(long int num, int absx, int absy, unsigned int scale) { // left-aligned
  int digit, zeroes;

  // If scale is 0, this draws a number starting at the current position, which is at the origin
  // of the previous number offset by the number width.

  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 SHOW_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((int)-num);
}

static void SHOW_UNSIGNED_NUM(unsigned long int num, int absx, int absy, unsigned int scale) { // left-aligned
  int digit, zeroes;

  // If scale is 0, this draws a number starting at the current position, which is at the origin
  // of the previous number offset by the number width.

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

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

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

  digit = 0;
  zeroes = 1; // CLRing is shorter
  // max 11 add/subtracts...
  if (num >= 40000) { num -= 40000UL; digit += 4; zeroes = 0; }
  if (num >= 20000) { num -= 20000UL; digit += 2; zeroes = 0; }
  if (num >= 10000) { num -= 10000UL; 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((int)num);
}
