Some early preliminary notes from the alpha vectrex-focused release of vbcc... I'll be updating
my copy of this as I use it. At the moment I'm only looking at it from the point of view of
being a replacement for the existing compiler. I'll leave the discussion of how we might implement
and what should go in to a completely new library for another time.

-------------------------------- Installation notes

bin files are 64 bit.  Fortunately I have qemu installed on my i686 system.
Might be worth supplying both 32 bit native binaries, and cross-platform portable 64-bit
fat binaries using APE (cosmocc).

Aside: the build process that enquires of the user about word signedness and size asks a lot
of questions that can be answered automatically, assuming that the questions are about the
host computer and not the target computer: see https://homepages.cwi.nl/~steven/enquire.html

-------------------------------- Libraries


        17.29 6809/Vectrex

        This is a port of vclib to the Vectrex. The config +vectrex will create a cartridge ROM
        image including a cartridge header.

Vectrex users programming in the Vide IDE include a "cartridge.c" file in their compilation
which is always linked first so that it is placed as the first part of the ROM code.  It is
available to the user so that they can adjust the ROM name and the screen ccordinates of the
header.  The significant content of the file contains this:

#include <vectrex.h>

struct cartridge_t
{
  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"
};
const struct cartridge_t game_header __attribute__((section(".cartridge"), used)) =
{
  .copyright              = "g GCE 2017\x80",     // change year if neccessary, do not change "g GCE"
  .music                  = &Vec_Music_1,         // taken from included headers
  .title_height   = -8,
  .title_width    = 80,
  .title_y                = -16,
  .title_x                = -72,
  .title                  = "GAME TITLE\x80"      // note that \x00 is automatically appended!
};

The format is slightly more complex than that but if the other features are wanted the user has
to replace the declarations above with the alternative format.  The difference is that the
title can be over multiple lines with separate x,y for each line. Only the string on the final
line is terminated by \0x80, the earlier ones are terminated by \0".  I think.  It's been some
time since I needed to use that format, I may have the details slightly wrong.

Anyway my point is that vbcc should not create a ROM header, the user does that in cartridge.h
[Again: I emphasize that this is only if we are trying to be compatible with the existing code
base.  For a new environment, creating the rom header differently would be fine.]

        The linker file vlink.cmd is used. The linker parameters mentioned in the following
        chapters can either be changed by modifying the linker file, or by adding the option
        --D<PARAM>=<VAL> on the command line invocation of vc.

        17.29.1 Memory

        The usable RAM region defaults to 0xC880..0xCBEA, the ROM region defaults to
        0x0000.0x8000. Those values can be changed by the linker parameters RAMSTART, RAMEND,
        ROMSTART, ROMEND. Data sections will be initialized by copying the init data from ROM
        to RAM.

Note that the ROM area on the Vectrex is actually 48K not 32K, though larger roms were not
used until relatively recently.  (There's also another small area that can be used as ROM
but I don't know of anyone using it yet due to the overhead of decoding it in a cartridge)

Nowadays some ROMs use multiple banks which Vide and GCC do support, although not very well.
There are a couple of different methods used to do bank switching, and especially if using
the 4-bank cartridges.  I'll seek out the details at some point.

There are a very small number of cartridges that support extra RAM.  The Vecfever is one
of them but you may be aware how few people have access to one.  In normal use it shouldn't
matter much to a 6809 compiler if an area that is normally in ROM is actually writable.  Almost
certainly an author would be handling that area of memory themself, explicitly in the code.

        17.29.2 Stack

        The stack pointer will be initialized to 0xCBEA. This value can be changed using the linker
        parameter __STACK. The stack size can be set using STACKLEN.

I believe when a Vectrex game rom is started, S is already initialised by the BIOS, and probably
should never be touched (other than through legitimate pushing and pulling...).  DP will also
have been initialised.  This should all be in existing Vectrex documentation, such as it is.

        17.29.3 Heap

        The free area up to __STACK-STACKLEN is used as heap.

No vectrex code in the current system under GCC and Vide uses the heap.  There are often only about
800 bytes left free for programs, so RAM is *extremely* tight: we don't want unused heap code or
variables taking up any space at all, if a heap library exists, not even the minimal 2 bytes that
would be needed for an empty freespace list.  Vectrex coders do their own space management, aggressively.
Usually by moving as much as humanly possible into ROM, with anything that can't go in ROM being
calculated on the fly rather than stored in RAM.  I can't emphasize enough how little RAM the Vectrex
leaves for the programmer afer the BIOS has taken what it needs.  Coders will even steal the odd byte
of BIOS RAM if they know that the BIOS is never going to use it during the run of their ROM.

        17.29.4 HW Registers

        TODO

        17.29.5 stdio

        If stdio functions are called, a 20x12 character buffer is used to handle text output. The
        screen will be refreshed when output functions are called and when the program terminates.
        Therefore the text will not be visible during calculations of a normal console C program.
        The function __conrefresh() can be called to trigger a screen refresh.

No-one uses stdio procedures.  There's no serial output on the Vectrex and text display is so slow
that drawing text (even with the built-in raster primitives) would severely affect program speed.
Potentially stdio might be useful with some flash cards such as the VecFever, with a serial device
that outputs to USB, but there's no standardised interface.  Easiest to just omit.

Some other standard headers that don't actually require code could usefully be available, if only
to make sources slightly more portable, eg stdint.h or limits.h  Headers with inline procedures or
macro definitions such as isdigit() etc would also be useful.  Library procedures that make sense
on the Vectrex would be acceptable, as long as nothing is pulled in by the linker when they're not
used.  GCC under Vide does not offer most of these headers, only <vectrex.h>.  It should!

        17.29.6 BIOS Interface

        TODO: not yet sure

        The header vectrex.h contains inline-assembly declarations or macros for Vectrex BIOS
        functions.

#define __D(x,y) ((((unsigned char)y)<<8)|((unsigned char)x))

#define __A __varsmodified("")

__A void Wait_Recal()="\tjsr\t0xf192";
__A void Intensity_a(char x)="\texg\ta,b\n\tjsr\t0xf2ab";
__A void Moveto_ab_7f(char x, char y)="\tlda\t0,s\n\tjsr\t0xf2fc";
__A void Moveto_d_7f(int)="\tjsr\t0xf2fc";
__A void Moveto_ab(char x, char y)="\tlda\t0,s\n\tjsr\t0xf312";
__A void Moveto_d(int)="\tjsr\t0xf312";
__A void Draw_Line_ab(char x, char y)="\tlda\t0,s\n\tjsr\t0xf3df";
__A void Draw_Line_d(int)="\tjsr\t0xf3df";
__A void Print_Str_d(int,__reg("u") void *)="\tjsr\t0xf37a";
__A void Print_Str_ab(char x,char y,__reg("u") void *)="\tlda\t0,s\n\tjsr\t0xf37a";
__A void Print_Str(__reg("u") void *)="\tjsr\t0xf495";


We do have a list of registers used and modfied by all the BIOS routines that can be
used to add attributes to the BIOS procedures, to help with optimising.  I don't know at
this point whether the assignment of parameters to GCC procedures uses the same mapping
to registers and stack parameters as vbcc, I need to read your docs on calling conventions,
or talk to you about them if not documented yet.

For reasons that you'll have to ask Chris and Peer about, the convention with the
existing Vectrex library is that coordinates are y,x rather than x,y.  Chris at least
is quite dogmatic about this being the preferred One True Way.  It's embedded in so
much code and documentation nowadays that it's unlikely we can persuade anyone to switch
to using x,y.

        Some functions take two coordinates in accumulators a and b. vbcc does not support
        accessing the accumulators separately. Therefore those functions are usually available in
        two versions. One version takes a 16bit argument containing the coordinates as lo-byte and
        hi-byte in the 16bit accumulator d.

        The macro _D(x,y) can be used to calculate the combined 16bit value from two coordinates.
        Using this API version is most efficient if the 16bit value can be calculated once and reused
        later, or if the coordinates are constants.

        Another API accepts two coordinates as separate parameters. This approach will usually
        be faster for dynamically calculated coordinates.

        Draw_Line_d(_D(0,0));
        Draw_Line_ab(x, y);

The GCC Vectrex library does support these names but the normal procedure used is
Draw_Line(int y, int x) which in vbcc would be better specified as Draw_Line(int8_t y, int8_t x)

An example of a definition of an existing procedure as it might be implemented in the vbcc Vectrex
library could be something like this:

#define asm(s) __asm(s) // Be more compatible with gcc syntax

void Print_Str_yx(int8_t y, int8_t x, char *s) {

  // assume vbcc calling conventions are that parameters are passed to this in A, B, Y respectively
  // and the BIOS procedure uses a,b as is, but passes the string in via U, then the code would look
  // like this:

  asm(" TFR Y,U");   // Move string 's' into the U register that Print_Str_d expects.
  asm(" JMP $F37A"); // Print_Str_d:
                     //    Uses DP (must be 0xD0), U, A, B
                     //    Outputs U (points to the byte after the terminating 0x80)
                     //    Corrupts A, B, X.
                     //    Other registers untouched.
                     // (Would be a JSR followed by an RTS so might as well save an instruction and JMP instead.)
}


        Chapter 17: C Library 185

        17.29.7 Floating Point

        Not yet implemented.

No-one ever uses floating point on the Vectrex, it's way too expensive at runtime.  There is some
use of fixed point but everyone has to write their own version.  Most code just uses integers,
usually 8 bit but also 16 bit where needed.  There is almost no use of 32-bit integers as arithmetic
on those is particularly expensive.

There is no floating point rom on the Vectrex so specific floating point procedures will have
to be written based on the Motorola ROM code, pulling in any subprocedures that are called.
The FP09 source code is available at https://gtoal.com/src/asm-expand/ including a macro
expander for the Motorola assember format that's hard to find an assembler for, plus the
bug-fixed https://gtoal.com/src/asm-expand/fp09/util.sa

(The .asm files in https://gtoal.com/src/asm-expand/fp09/ are the macro-expanded
versions of the original .sa files)
