// no debug relevant parts, since everything is done inline :-)
/*****************************************************************************/
/*                                                                           */
/*   VECTREX HP3000 Software Emulator              Copyright K.Wilkins 1996  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Title      : Vector Display driver software module                      */
/*                                                                           */
/*   File Name  : DISPLAY.C                                                  */
/*                                                                           */
/*   Author     : Keith Wilkins / C.S.                                       */
/*                                                                           */
/*   Version    : 1.20                                                       */
/*                                                                           */
/*   Desciption : This file contains the functions that drive the PC display */
/*                and set the modes up etc etc. A base plot routine is       */
/*                provided for displaying the vectrex screen.                */
/*                These functions only init the VECTOR based screen not the  */
/*                PC screen which is initialised in MAIN().                  */
/*                                                                           */
/*                The vector display functions use the fIO primatives from   */
/*                IO.C to plot pixels, this function maps from Vextrex       */
/*                pixels to REAL pixels. It also Plots pixels into the       */
/*                persistance handler area.                                  */
/*                                                                           */
/*                -Some function are now 'inline' functions                  */
/*                                                                           */
/*   Functions  : fVectorDisplayInit()    - Init the video display           */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Revision History:                                                       */
/*                                                                           */
/*   Version    Date    Who  Description of changes                          */
/*   -------    ----    ---  ----------------------                          */
/*                                                                           */
/*    0.01    14/03/93  K.W  Creation of empty file and descriptions         */
/*    1.00    05/08/96  K.W  Public release of DVE V1.0                      */
/*    1.20    20/10/96  C.S  Some function moved to inline status            */
/*                           Overlay stuff added, hash function...           */
/*                           new resolutions, div/shift...                   */
/*                                                                           */
/*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <standard.h>
#include <tools.h>

#include "io.h"
#include "display.h"
#include "vpalette.h"
#include "verror.h"
#include "vectrex.h"

#define BORDER_COLOUR       15  /* White border */
#define BACKGROUND_COLOUR   0   /* Black Background */

T_VOID   fBorderTriangleDraw(T_SLONG xl0, T_SLONG yl0, T_SLONG xl1, T_SLONG yl1, T_SLONG xl2, T_SLONG yl2,T_UWORD ink);
T_VOID   fOverlayTriangleDraw(T_SLONG xl0, T_SLONG yl0, T_SLONG xl1, T_SLONG yl1, T_SLONG xl2, T_SLONG yl2,T_UWORD ink);
T_VOID   fOverlayDrawLine(T_SWORD x1,T_SWORD y1,T_SWORD x2, T_SWORD y2, T_UWORD iColor);
T_VOID   fBorderLineDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen);
T_VOID   fBorderBlockDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen);
T_VOID   fBorderElipseDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen);

T_VOID   fOverlayBlockDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen);
T_VOID   fOverlayElipseDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen);

/************************************************/
/* 640x480,800x600,1024x768,1280x1024,1600x1200 */
/************************************************/
DISPLAYINFO display_infox_reset[RESOLUTION_COUNT];
DISPLAYINFO display_infox[RESOLUTION_COUNT]=
{
/******************************************************/
/* DivShftA   DivshftB   error scaled  error to 40000 */
/******************************************************/
          7,         9,
          7,         8,
          6,         9,
          6,         8,
          6,         7,
          8,         9,
};

T_UWORD divider_x_reset[RESOLUTION_COUNT];
T_UWORD divider_x[RESOLUTION_COUNT]={
          95,            // error  1.92 : 159
          76,            // error  6.06 : 400
          60,            // error  1.23 : 64
          45,            // error  1.64 : 64
          38,            // error 12.12 : 400
          175,           // error
};
DISPLAYINFO    display_infoy_reset[RESOLUTION_COUNT];
DISPLAYINFO    display_infoy[RESOLUTION_COUNT]=
{
/******************************************************/
/* DivShftA   DivshftB   error scaled  error to 40000 */
/******************************************************/

          7,         9,  // error 12 : 996
          7,         8,  // error 24 : 1584
          6,         9,  // error 13 : 676
          6,         8,  // error 87 : 3393
          6,         7,  // error 50 : 1650
          8,         11, // error
};

T_UWORD divider_y_reset[RESOLUTION_COUNT];
T_UWORD divider_y[RESOLUTION_COUNT]={
          92,            // error  1.92 : 159
          76,            // error  6.06 : 400
          60,            // error  1.23 : 64
          45,            // error  1.64 : 64
          38,            // error 12.12 : 400
          222,           // error
};
T_INT display_init_back=T_TRUE;

/*******************************************/
/* Decoded copies of all configs for speed */
/*******************************************/
T_UWORD iDivShiftAx=0;
T_UWORD iDivShiftBx=0;
T_UWORD iDivShiftAy=0;
T_UWORD iDivShiftBy=0;

T_SWORD iXOffset=0;
T_SWORD iYOffset=0;

T_SWORD iX1clip=0;
T_SWORD iY1clip=0;
T_SWORD iX2clip=0;
T_SWORD iY2clip=0;

/*****************************************/
/* Variables for refresh timing & adjust */
/*****************************************/
T_SWORD iLineSelected=-1;
T_SWORD iLineSelector=LINE_REFRESH_LIMIT;
T_ULONG lwRefreshMarker=0;

/**************************/
/* Line store definitions */
/**************************/
SDLINE line_store[LINESTORE_DEPTH];

/*****************************/
/* Hashing table definitions */
/*****************************/
T_SWORD line_freelist=0;
T_SWORD line_rootnode=-1;

T_SWORD hash_rootnodes[HASH_TABLE_SIZE];
T_SWORD hash_freelist=0;
SHASH hash_store[LINESTORE_DEPTH];

//T_SWORD diX1=0,diY1=0,diX2=0,diY2=0;
T_SWORD diX1=0,diY1=0,diX2=0,diY2=0;
T_SWORD hash_code=0,hash=0,line=0;
T_INT fDNoPicload=T_FALSE;


/***********************/
/* Overlay definitions */
/***********************/
T_PUCHAR overlay_line_starts[OVERLAY_LINE_COUNT];

/***********************************************/
/* prototype function for shift or div scaling */
/***********************************************/
//T_VOID (* fDisplayLineDraw)(T_SLONG,T_SLONG,T_SLONG,T_SLONG,T_UCHAR);
T_VOID (* scale)(T_PSWORD,T_PSWORD,T_PSWORD,T_PSWORD,T_SLONG,T_SLONG,T_SLONG,T_SLONG);

//T_VOID fDisplayLineDraw_div(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tBright);
//T_VOID fDisplayLineDraw_shift(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tBright);
T_SWORD get_x_line(T_SWORD x0,T_SWORD y0,T_SWORD x1,T_SWORD y1, T_SWORD x_searched);

/**************************************************************/
/* just 2 scaling functions... added for convinient DIV/SHIFT */
/* handling within overlay/border funtions                    */
/**************************************************************/
T_VOID scale_shift(T_PSWORD iX1, T_PSWORD iY1,  T_PSWORD iX2,  T_PSWORD iY2,
                 T_SLONG lX1, T_SLONG lY1, T_SLONG lX2, T_SLONG lY2)
{
 *iX1=(lX1>>iDivShiftAx) + (lX1>>iDivShiftBx);
 *iY1=(lY1>>iDivShiftAy) + (lY1>>iDivShiftBy);
 *iX2=(lX2>>iDivShiftAx) + (lX2>>iDivShiftBx);
 *iY2=(lY2>>iDivShiftAy) + (lY2>>iDivShiftBy);
}
T_VOID scale_div(T_PSWORD iX1, T_PSWORD iY1,  T_PSWORD iX2,  T_PSWORD iY2,
               T_SLONG lX1, T_SLONG lY1, T_SLONG lX2, T_SLONG lY2)
{
 *iX1=lX1/dividerx;
 *iY1=lY1/dividery;
 *iX2=lX2/dividerx;
 *iY2=lY2/dividery;
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fDisplayInit()                                            */
/*                                                                           */
/*   Author      : K.W / C.S.                                                */
/*                                                                           */
/*   Description : Clear the vector screen area and draw the border around   */
/*                 it to mark it out from the screen. Initialise all the     */
/*                 other bits and pieces.                                    */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : T_INTEAN T_TRUE if initialised OK else T_FALSE                 */
/*                                                                           */
/*****************************************************************************/

T_INT fDisplayInit(T_VOID)
{
 T_ULONG loop;
 T_PUCHAR ptr;
 PIXEL screen;
 screen=fIOGetScreenRes();
 /****************************/
 /* Initialise the line data */
 /****************************/
 if (bGblDisplayExactScaling==T_FALSE)
 {
  iDivShiftAx=display_infox[wGblDisplayMode].iDivShiftA;
  iDivShiftBx=display_infox[wGblDisplayMode].iDivShiftB;
  iDivShiftAy=display_infoy[wGblDisplayMode].iDivShiftA;
  iDivShiftBy=display_infoy[wGblDisplayMode].iDivShiftB;
  scale=scale_shift;
 }
 else
 {
  dividerx=divider_x[wGblDisplayMode];
  dividery=divider_y[wGblDisplayMode];
  scale=scale_div;
 }
 if ((ptr=fIOGetOverlayBuffer())==NULL)
  fFatal("fIOGetOverlayBuffer() returned NULL");
 for(loop=0;loop<OVERLAY_LINE_COUNT;loop++)
 {
  overlay_line_starts[loop]=ptr;
  ptr+=screen.iXpos;
 }
 fDisplayReset();
 return(T_TRUE);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fDisplayReset()                                           */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Reset the vector display function                         */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/
T_VOID fDisplayReset(T_VOID)
{
 T_SWORD loop;
 PIXEL screen;
 T_ULONG screenmem;

 for (loop=0;loop<256;loop++)
 {
  vpalette[loop][0]=vpalette_reset[loop][0];
  vpalette[loop][1]=vpalette_reset[loop][1];
  vpalette[loop][2]=vpalette_reset[loop][2];
  vpalette[loop][3]=vpalette_reset[loop][3];
 }
 bGblLightpenEnable=T_FALSE;
 bGblExtendedRam=T_FALSE;
 bGblDisplayFullRefresh=T_FALSE;
 rectengle_clipping_enable=T_TRUE;
 bGblGoggleGame=T_FALSE;
 wGblColor1Degrees=60;
 wGblColor2Degrees=60;
 wGblColor3Degrees=60;
 wGblImagerMode=0;
 wGblImagerXOffset=0;
 wGblImagerXOffset1=0;
 wGblImagerXOffset2=0;
 ImagerColorNow=255;
 imager_pulse_ticks=0;

 bGblOverlayEnable_reset=bGblOverlayEnable;

 lwGblClipX=lwGblClipX_reset;               // Clipping window top right
 lwGblClipY=lwGblClipY_reset;

 divider_x[0]=divider_x_reset[0];
 divider_y[0]=divider_y_reset[0];

 divider_x[1]=divider_x_reset[1];
 divider_y[1]=divider_y_reset[1];

 divider_x[2]=divider_x_reset[2];
 divider_y[2]=divider_y_reset[2];

 divider_x[3]=divider_x_reset[3];
 divider_y[3]=divider_y_reset[3];

 divider_x[4]=divider_x_reset[4];
 divider_y[4]=divider_y_reset[4];

 divider_x[5]=divider_x_reset[5];
 divider_y[5]=divider_y_reset[5];

 display_infox[0].iDivShiftA=display_infox_reset[0].iDivShiftA;
 display_infox[0].iDivShiftB=display_infox_reset[0].iDivShiftB;
 display_infoy[0].iDivShiftA=display_infoy_reset[0].iDivShiftA;
 display_infoy[0].iDivShiftB=display_infoy_reset[0].iDivShiftB;

 display_infox[1].iDivShiftA=display_infox_reset[1].iDivShiftA;
 display_infox[1].iDivShiftB=display_infox_reset[1].iDivShiftB;
 display_infoy[1].iDivShiftA=display_infoy_reset[1].iDivShiftA;
 display_infoy[1].iDivShiftB=display_infoy_reset[1].iDivShiftB;

 display_infox[2].iDivShiftA=display_infox_reset[2].iDivShiftA;
 display_infox[2].iDivShiftB=display_infox_reset[2].iDivShiftB;
 display_infoy[2].iDivShiftA=display_infoy_reset[2].iDivShiftA;
 display_infoy[2].iDivShiftB=display_infoy_reset[2].iDivShiftB;

 display_infox[3].iDivShiftA=display_infox_reset[3].iDivShiftA;
 display_infox[3].iDivShiftB=display_infox_reset[3].iDivShiftB;
 display_infoy[3].iDivShiftA=display_infoy_reset[3].iDivShiftA;
 display_infoy[3].iDivShiftB=display_infoy_reset[3].iDivShiftB;

 display_infox[4].iDivShiftA=display_infox_reset[4].iDivShiftA;
 display_infox[4].iDivShiftB=display_infox_reset[4].iDivShiftB;
 display_infoy[4].iDivShiftA=display_infoy_reset[4].iDivShiftA;
 display_infoy[4].iDivShiftB=display_infoy_reset[4].iDivShiftB;

 display_infox[5].iDivShiftA=display_infox_reset[5].iDivShiftA;
 display_infox[5].iDivShiftB=display_infox_reset[5].iDivShiftB;
 display_infoy[5].iDivShiftA=display_infoy_reset[5].iDivShiftA;
 display_infoy[5].iDivShiftB=display_infoy_reset[5].iDivShiftB;

 if (bGblDisplayExactScaling==T_FALSE)
 {
  iDivShiftAx=display_infox[wGblDisplayMode].iDivShiftA;
  iDivShiftBx=display_infox[wGblDisplayMode].iDivShiftB;
  iDivShiftAy=display_infoy[wGblDisplayMode].iDivShiftA;
  iDivShiftBy=display_infoy[wGblDisplayMode].iDivShiftB;
  scale=scale_shift;
 }
 else
 {
  dividerx=divider_x[wGblDisplayMode];
  dividery=divider_y[wGblDisplayMode];
  scale=scale_div;
 }

 screen=fIOGetScreenRes();
 iXOffset=screen.iXpos/2;
 iYOffset=screen.iYpos/2;
 if (bGblDisplayExactScaling==T_FALSE)
 {
  iX1clip=(lwGblClipX>>iDivShiftAx) + (lwGblClipX>>iDivShiftBx);
  iY1clip=(lwGblClipY>>iDivShiftAy) + (lwGblClipY>>iDivShiftBy);
  iX2clip=(-lwGblClipX>>iDivShiftAx) + (-lwGblClipX>>iDivShiftBx);
  iY2clip=(-lwGblClipY>>iDivShiftAy) + (-lwGblClipY>>iDivShiftBy);

  mausxmin=iXOffset-((20000>>iDivShiftAx)+(20000>>iDivShiftBx));
  mausxmax=iXOffset+((20000>>iDivShiftAx)+(20000>>iDivShiftBx));
  mausymin=iYOffset-((20000>>iDivShiftAy)+(20000>>iDivShiftBy));
  mausymax=iYOffset+((20000>>iDivShiftAy)+(20000>>iDivShiftBy));
 }
 else
 {
  iX1clip=lwGblClipX/dividerx;
  iY1clip=lwGblClipY/dividery;
  iX2clip=-lwGblClipX/dividerx;
  iY2clip=-lwGblClipY/dividery;

  mausxmin=iXOffset-20000/dividerx; // just in case a lightpen
  mausxmax=iXOffset+20000/dividerx; // will be enabled
  mausymin=iYOffset-20000/dividery;
  mausymax=iYOffset+20000/dividery;
 }
 iX1clip+=iXOffset;
 iY1clip+=iYOffset;
 iX2clip+=iXOffset;
 iY2clip+=iYOffset;

 /**************************************/
 /* Initialise Line store & hash table */
 /**************************************/
 for(loop=0;loop<LINESTORE_DEPTH-1;loop++)
 {
  line_store[loop].next_vector=loop+1;
  hash_store[loop].next_hash=loop+1;
 }
 line_store[loop].next_vector=-1;
 hash_store[loop].next_hash=-1;

 line_freelist=0;
 hash_freelist=0;

 line_rootnode=-1;

 for(loop=0;loop<HASH_TABLE_SIZE;loop++)
 {
  hash_rootnodes[loop]=-1;
 }

 if (bGblDisplayAutoRefresh)
  wGblDisplayLinePeriod=1;

 if (bGblGUIEnable==T_TRUE)
 {
  MOUSE_VERSTECKE
  hide_all_windows();
 }
 else
 {
  if (display_init_back==T_TRUE)
  {
   MOUSE_VERSTECKE
   hide_all_windows();
  }
 }

 fIOSetClipping(-1,-1,-1,-1); // unclipp everything !
 fDisplayClear();

 /********************************************/
 /* Initialise overlay memory to default ink */
 /********************************************/
 screen=fIOGetScreenRes();
 if ((overlay_memory)==NULL)
  fFatal("fIOGetOverlayBuffer() returned NULL");
 screenmem=(T_ULONG)screen.iXpos*(T_ULONG)screen.iYpos;
 memset(overlay_memory,wGblDisplayBaseColour<<4,screenmem);
 /***********************************************************/
 /* Now screen is reset then reload the Overlay if required */
 /***********************************************************/
 fDisplayLoadVOL();
 /*************************************************/
 /* Before exiting set the vector clipping region */
 /*************************************************/
 fIOSetClipping(iX1clip,iY1clip,iX2clip,iY2clip); // doesn't do much when overlay was loaded
 if (wGblImagerMode!=0)
 {
  /* initialise degrees of color wheel in system ticks */
  /* in lwGblWheelTicks is 1/2 turn of the wheel in ticks */
  /* wGblColor1Degrees+wGblColor2Degrees+wGblColor3Degrees should be 180 degrees */

  T_ULONG ltmp_all=wGblColor1Degrees+wGblColor2Degrees+wGblColor3Degrees;
  wGblColor1Degrees = (lwGblWheelTicks*wGblColor1Degrees)/ltmp_all;
  wGblColor2Degrees = (lwGblWheelTicks*wGblColor2Degrees)/ltmp_all;
  wGblColor3Degrees = (lwGblWheelTicks*wGblColor3Degrees)/ltmp_all;
  if (lwGblWheelTicks!=(wGblColor1Degrees+wGblColor2Degrees+wGblColor3Degrees))
  {
   wGblColor1Degrees+=lwGblWheelTicks-(wGblColor1Degrees+wGblColor2Degrees+wGblColor3Degrees);
  }

  if (wGblImagerMode==6)
  {
   if (bGblDisplayExactScaling==T_FALSE)
   {
    wGblImagerXOffset1=-(iXOffset+(-30000>>iDivShiftAx) + (-30000>>iDivShiftBx));
    wGblImagerXOffset2=screen.iXpos-((30000>>iDivShiftAx) + (30000>>iDivShiftBx))-iXOffset ;
    wGblImagerXOffset1=(wGblImagerXOffset1<<iDivShiftAx)+(wGblImagerXOffset1<<iDivShiftBx);
    wGblImagerXOffset2=(wGblImagerXOffset2<<iDivShiftAx)+(wGblImagerXOffset2<<iDivShiftBx);
   }
   else
   {
    wGblImagerXOffset1=-(iXOffset+(-30000/dividerx));
    wGblImagerXOffset2=screen.iXpos-(30000/dividerx)-iXOffset;
    wGblImagerXOffset1*=dividerx;
    wGblImagerXOffset2*=dividerx;
   }
/*
 0 muss so sein, dass ich noch -20000 darstellen kann
 und
 0 muss so sein, dass ich noch +20000 darstellen kann
*/
  }
//printf("\nxo1:%i, xo2:%i",wGblImagerXOffset1,wGblImagerXOffset2);
 }

 if (bGblGUIEnable==T_TRUE)
 {
  back_save(FORCED_SAVE);
  show_all_windows();
  MOUSE_ZEIGE
 }
 else
 {
  if (display_init_back==T_TRUE)
  {
   back_save(FORCED_SAVE);
   show_all_windows();
   MOUSE_ZEIGE
  }
 }
 display_init_back=T_FALSE;
}

T_VOID vector_refresh(T_VOID)
{
 T_SWORD iTmp;
 iTmp=line_rootnode;
 while(iTmp!=-1)
 {
  static T_SWORD iX1;
  static T_SWORD iY1;
  static T_SWORD iX2;
  static T_SWORD iY2;
  static T_SWORD iColour;
  static T_SWORD is_dot;
  iX1=line_store[iTmp].iX1;
  iY1=line_store[iTmp].iY1;
  iX2=line_store[iTmp].iX2;
  iY2=line_store[iTmp].iY2;
  iColour=line_store[iTmp].brightness;
  is_dot=line_store[iTmp].is_dot;

#define DEBUG_MSG
  if (blinetype==T_NORMAL)
  {
   if (bGblGoggleGame==T_TRUE)
   {
    #define DISPLAY_TICK_IMAGER
    T_INT imager_color_save=ImagerColorNow;
    ImagerColorNow=line_store[iTmp].imager_color;
    if (bGblOverlayEnable)
    {
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "mline.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "mline.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
    }
    else
    {
     #define LINE_WITH_COLOR
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "line.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "line.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
     #undef LINE_WITH_COLOR
    }
    #undef DISPLAY_TICK_IMAGER
    ImagerColorNow=imager_color_save;
   } //if (bGblGoggleGame=T_TRUE)
   else
   {
    if (bGblOverlayEnable)
    {
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "mline.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "mline.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
    }
    else
    {
     #define LINE_WITH_COLOR
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "line.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "line.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
     #undef LINE_WITH_COLOR
    }
    #undef DISPLAY_TICK_IMAGER
   } //else if (bGblGoggleGame=T_TRUE)
  } // if (blinetype==T_NORMAL)
  else
  {
   if (bGblGoggleGame==T_TRUE)
   {
    #define DISPLAY_TICK_IMAGER
    T_INT imager_color_save=ImagerColorNow;
    ImagerColorNow=line_store[iTmp].imager_color;
    if (bGblOverlayEnable)
    {
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "mline_aa.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "mline_aa.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
    }
    else
    {
     #define LINE_WITH_COLOR
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "line_aa.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "line_aa.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
     #undef LINE_WITH_COLOR
    }
    #undef DISPLAY_TICK_IMAGER
    ImagerColorNow=imager_color_save;
   } //if (bGblGoggleGame=T_TRUE)
   else
   {
    if (bGblOverlayEnable)
    {
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "mline_aa.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "mline_aa.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
    }
    else
    {
     #define LINE_WITH_COLOR
     if (framebuffer==FB_LINEAR)
     {
      #define DISPLAY_TICK_LINEAR
      #include "line_aa.cc"
      #undef DISPLAY_TICK_LINEAR
     }
     if (framebuffer==FB_BANKED)
     {
      #define DISPLAY_TICK_BANKED
      #define BANKED
      #include "line_aa.cc"
      #undef BANKED
      #undef DISPLAY_TICK_BANKED
     }
     #undef LINE_WITH_COLOR
    }
    #undef DISPLAY_TICK_IMAGER
   } //else if (bGblGoggleGame=T_TRUE)
  } // else if (blinetype==T_NORMAL)
  iTmp=line_store[iTmp].next_vector;
 }

}


T_VOID fBorderLineDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen)
{
 T_SWORD iX1,iY1,iX2,iY2;

 /**************************/
 /* Scale to screen coords */
 /**************************/
 lY1=-lY1;
 lY2=-lY2;
 scale(&iX1,&iY1,&iX2,&iY2,lX1,lY1,lX2,lY2);
 iX1+=iXOffset;
 iY1+=iYOffset;
 iX2+=iXOffset;
 iY2+=iYOffset;
 fIODrawLine(iX1,iY1,iX2,iY2,(T_SWORD)tPen);
}

T_VOID fBorderBlockDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen)
{
 T_SWORD iX1,iY1,iX2,iY2;

 /**************************/
 /* Scale to screen coords */
 /**************************/
 lY1=-lY1;
 lY2=-lY2;
 scale(&iX1,&iY1,&iX2,&iY2,lX1,lY1,lX2,lY2);
 iX1+=iXOffset;
 iY1+=iYOffset;
 iX2+=iXOffset;
 iY2+=iYOffset;
 fIODrawBox(iX1,iY1,iX2,iY2,(T_SWORD)tPen,T_TRUE);
}

T_VOID fBorderElipseDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lMajor,T_SLONG lMinor,T_UCHAR tPen)
{
 T_SWORD   iX1,iY1,iMajor,iMinor,row,result;
 T_DOUBLE  lsmaj2,lsmin2,ly2;

 /**************************/
 /* Scale to screen coords */
 /**************************/
 lY1=-lY1;
 scale(&iX1,&iY1,&iMajor,&iMinor,lX1,lY1,lMajor,lMinor);
 iX1+=iXOffset;
 iY1+=iYOffset;

 lsmaj2=pow(iMajor,2.0);
 lsmin2=pow(iMinor,2.0);

 for(row=0;row<=iMinor;row++)
 {
  ly2=pow((T_DOUBLE)row,2.0);
  result=floor(sqrt(lsmaj2-((ly2*lsmaj2)/lsmin2)));
  fIODrawLine(iX1-result,iY1-row,iX1+result,iY1-row,tPen);
  fIODrawLine(iX1-result,iY1+row,iX1+result,iY1+row,tPen);
 }
}

T_VOID fOverlayBlockDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lX2,T_SLONG lY2,T_UCHAR tPen)
{
 T_SWORD iX1,iY1,iX2,iY2;
 T_SWORD loop;
 PIXEL   screen;

 screen=fIOGetScreenRes();

 /**************************/
 /* Scale to screen coords */
 /**************************/
 lY1=-lY1;
 lY2=-lY2;
 scale(&iX1,&iY1,&iX2,&iY2,lX1,lY1,lX2,lY2);
 iX1+=iXOffset;
 iY1+=iYOffset;
 iX2+=iXOffset;
 iY2+=iYOffset;
 if(iX1>iX2)
  fSwapWord(&iX1,&iX2);
 if(iY1>iY2)
  fSwapWord(&iY1,&iY2);

 for(;iY1<=iY2;iY1++)
 {
  if(iY1>=0 && iY1<screen.iYpos)
  {
   for(loop=iX1;loop<=iX2;loop++)
   {
    if (loop>=0 && loop<screen.iXpos)
    {
     *(overlay_line_starts[iY1]+loop)=tPen;
    }
   }
  }
 }
}

T_VOID fOverlayElipseDraw(T_SLONG lX1,T_SLONG lY1,T_SLONG lMajor,T_SLONG lMinor,T_UCHAR tPen)
{
 T_SWORD   iX1,iY1,iMajor,iMinor,row,result,loop;
 double  lsmaj2,lsmin2,ly2;
 PIXEL   screen;

 screen=fIOGetScreenRes();

 /**************************/
 /* Scale to screen coords */
 /**************************/
 lY1=-lY1;
 scale(&iX1,&iY1,&iMajor,&iMinor,lX1,lY1,lMajor,lMinor);
 iX1+=iXOffset;
 iY1+=iYOffset;
 lsmaj2=pow(iMajor,2.0);
 lsmin2=pow(iMinor,2.0);

 for(row=0;row<=iMinor;row++)
 {
  ly2=pow((double)row,2.0);
  result=floor(sqrt(lsmaj2-((ly2*lsmaj2)/lsmin2)));
  if(iY1>=0 && iY1<screen.iYpos)
  {
   for(loop=iX1-result;loop<=iX1+result;loop++)
   {
    if(loop>=0 && loop<screen.iXpos)
    {
     *(overlay_line_starts[iY1-row]+loop)=tPen;
     *(overlay_line_starts[iY1+row]+loop)=tPen;
    }
   }
  }
 }
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fDisplayClear()                                           */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Cleans the screen area inside the vectrex screen area to  */
/*                 colour 0 (Background)                                     */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/

T_VOID fDisplayClear(T_VOID)
{
 fIOAreaClear(-1,-1,-1,-1,0);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fDisplayLoadVOL()                                         */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : Load/Initialise VOL (Vectrex OverLay) file                */
/*                                                                           */
/*   Accepts     : Char* pointer to file to load from                        */
/*                                                                           */
/*   Returns     : T_INT    T_TRUE=Init OK, T_FALSE=Init Fail                     */
/*                                                                           */
/*****************************************************************************/

T_INT fDisplayLoadVOL(T_VOID)
{
 T_PCHAR   current_path=NULL;
 T_UCHAR   filename[STRING_LENGTH];
 FILE    *pfINIfile;
 T_UCHAR   acBuffer[1024];

 T_UCHAR   *pcCommandName;
 T_UCHAR   *pcCommandType;
 T_UCHAR   *pcArgStr;

 T_ULONG   arglist[MAX_ARGS];
 T_ULONG   loop,argcount;

 T_SWORD   line=1;
 T_INT    debug=T_FALSE;
 T_INT    screen_fix=T_FALSE;

// File syntax definitions

// OVERLAY BLOCK <PEN> <X1> <Y1> <X2> <Y2>
// OVERLAY ELIPSE <PEN> <X1> <Y1> <major> <minor>
// overlay triangle pen x1 y1 x2 y2 x3 y3

// OVERLAY <ENABLE/DISABLE>

// OVERLAY_PCX0 FILENAME (PCX 256 color file with exact resolution! for resolution 0)
// OVERLAY_PCX1 FILENAME (PCX 256 color file with exact resolution! for resolution 1)
// OVERLAY_PCX2 FILENAME (PCX 256 color file with exact resolution! for resolution 2)
// OVERLAY_PCX3 FILENAME (PCX 256 color file with exact resolution! for resolution 1)
// OVERLAY_PCX4 FILENAME (PCX 256 color file with exact resolution! for resolution 2)
// OVERLAY_PCX5 FILENAME (PCX 256 color file with exact resolution! for resolution 2)

// LIGHTPEN
// FULLREFRESH

// EXTENDED_RAM

// BORDER BLOCK   <PEN> <INTENSITY> <X1> <Y1> <X2> <Y2>
// BORDER LINE    <PEN> <INTENSITY> <X1> <Y1> <X2> <Y2>
// BORDER ELIPSE  <PEN> <INTENSITY> <X1> <Y1> <major> <minor>
// border triangle pen INTENSITY x1 y1 x2 y2 x3 y3

// SCREEN CLIP    <X1> <Y1> <X2> <Y2>
// SCREEN OFFSET  <X1> <Y1>
// SCREEN COLOUR  <PEN> <INTENSITY> <RED> <GREEN> <BLUE>

// SCREEN DIVX   <RESOLUTION> <DIV>
// SCREEN DIVY   <RESOLUTION> <DIV>
// SCREEN SHIFTX   <RESOLUTION> <SHIFT A> <SHIFT B>
// SCREEN SHIFTY   <RESOLUTION> <SHIFT A> <SHIFT B>
// DEBUG

// Create the filename

 if (strcmp(acGblDefaultCartFileName,""))
  strcpy(filename,acGblDefaultCartFileName);
 else
  strcpy(filename,acGblROMImageFileName);
 if(strrchr(filename,'.')!=NULL)
  *(strrchr(filename,'.'))='\0';
 strcat(filename,".vol");

 current_path=get_current_path();
 if (GblVolDir!=NULL)
  change_directory(GblVolDir);
 if (f_file_exist(filename)==T_FALSE)
 {
  if (current_path!=NULL)
  {
   change_directory(current_path);
   free(current_path);
   current_path=NULL;
  }
 }

 for(loop=0;loop<MAX_ARGS;loop++)
  arglist[loop]=DUFF_VALUE;

 // Now use the INI file to overload the values
 if ((pfINIfile=fopen(filename,"rt"))!=NULL)
 {
  if (current_path!=NULL)
  {
   change_directory(current_path);
  }
  while(fgets(acBuffer,1024,pfINIfile)!=NULL)
  {
   strupr(acBuffer);
   if((pcCommandType=strtok(acBuffer," ,=:\n"))==NULL)
    strcpy(pcCommandType,"#");
   pcCommandName=strtok(NULL," ,=:\n");

   argcount=0;
   while ((pcArgStr=strtok(NULL," ,=:\n"))!=NULL)
   {
    arglist[argcount++]=atol(pcArgStr);
   }
   // Decode data
   if (strcmp(pcCommandType,"NO_SHADES")==0)
   {
    bGblNoShades=T_TRUE;
   }
   else if (strcmp(pcCommandType,"3D_IMAGER_GAME")==0)
   {
    if (bGblLightpenEnable==T_TRUE)
    {
     fFatal("Overlay init ERROR! No game has Lightpen + Imagers...");
    }
    bGblGoggleGame=T_TRUE;
   }
   else if (strcmp(pcCommandType,"WHEEL_TICKS")==0)
   {
    lwGblWheelTicks=atol(pcCommandName)/2;
   }
   else if(strcmp(pcCommandType,"COLOR_1_DEGREES")==0)
   {
    wGblColor1Degrees=atol(pcCommandName);
   }
   else if(strcmp(pcCommandType,"COLOR_2_DEGREES")==0)
   {
    wGblColor2Degrees=atol(pcCommandName);
   }
   else if(strcmp(pcCommandType,"COLOR_3_DEGREES")==0)
   {
    wGblColor3Degrees=atol(pcCommandName);
   }
   else if(strcmp(pcCommandType,"IMAGER_MODE")==0)
   {
    wGblImagerMode=atol(pcCommandName);
   }
   else if (strcmp(pcCommandType,"LOAD_COLORS_EXACT")==0)
   {
    bGblLoadColorsExact=T_TRUE;
   }
   else if (strcmp(pcCommandType,"EXTENDED_RAM")==0)
   {
    bGblExtendedRam=T_TRUE;          /* Animaction Ram 2K */
   }
   else if (strcmp(pcCommandType,"FULLREFRESH")==0)
   {
    bGblDisplayFullRefresh=T_TRUE;
   }
   else if (strcmp(pcCommandType,"LIGHTPEN")==0)
   {
    if (bGblGoggleGame==T_TRUE)
    {
     fFatal("Overlay init ERROR! No game has Lightpen + Imagers...");
    }
    bGblLightpenEnable=T_TRUE;
   }
   else if (strcmp(pcCommandType,"OVERLAY_PCX0")==0)
   {
    if (wGblDisplayMode==0)
    {
     if (fDNoPicload==T_FALSE)
     if (fIOload_pcx_overlay(pcCommandName)!=T_TRUE)
     {
      fFatal("Error loading PCX Overlay file");
     }
     rectengle_clipping_enable=T_FALSE;
    }
   }
   else if (strcmp(pcCommandType,"OVERLAY_PCX1")==0)
   {
    if (wGblDisplayMode==1)
    {
     if (fDNoPicload==T_FALSE)
     if (fIOload_pcx_overlay(pcCommandName)!=T_TRUE)
     {
      fFatal("Error loading PCX Overlay file");
     }
     rectengle_clipping_enable=T_FALSE;
    }
   }
   else if (strcmp(pcCommandType,"OVERLAY_PCX2")==0)
   {
    if (wGblDisplayMode==2)
    {
     if (fDNoPicload==T_FALSE)
     if (fIOload_pcx_overlay(pcCommandName)!=T_TRUE)
     {
      fFatal("Error loading PCX Overlay file");
     }
     rectengle_clipping_enable=T_FALSE;
    }
   }
   else if (strcmp(pcCommandType,"OVERLAY_PCX3")==0)
   {
    if (wGblDisplayMode==3)
    {
     if (fDNoPicload==T_FALSE)
     if (fIOload_pcx_overlay(pcCommandName)!=T_TRUE)
     {
      fFatal("Error loading PCX Overlay file");
     }
     rectengle_clipping_enable=T_FALSE;
    }
   }
   else if (strcmp(pcCommandType,"OVERLAY_PCX4")==0)
   {
    if (wGblDisplayMode==4)
    {
     if (fDNoPicload==T_FALSE)
     if (fIOload_pcx_overlay(pcCommandName)!=T_TRUE)
     {
      fFatal("Error loading PCX Overlay file");
     }
     rectengle_clipping_enable=T_FALSE;
    }
   }
   else if (strcmp(pcCommandType,"OVERLAY_PCX5")==0)
   {
    if (wGblDisplayMode==5)
    {
     if (fDNoPicload==T_FALSE)
     if (fIOload_pcx_overlay(pcCommandName)!=T_TRUE)
     {
      fFatal("Error loading PCX Overlay file");
     }
     rectengle_clipping_enable=T_FALSE;
    }
   }
   else if(strcmp(pcCommandType,"OVERLAY")==0)
   {
    if (strcmp(pcCommandName,"TRIANGLE")==0)
    {
     T_UWORD ink=((arglist[0]<<4)&0xf0);
     int x0=arglist[1];
     int y0=arglist[2];
     int x1=arglist[3];
     int y1=arglist[4];
     int x2=arglist[5];
     int y2=arglist[6];
     if (debug)
      fBorderTriangleDraw(x0,y0,x1,y1,x2,y2,ink);
     fOverlayTriangleDraw(x0,y0,x1,y1,x2,y2,ink);
    }
    else if(strcmp(pcCommandName,"BLOCK")==0)
    {
     T_UWORD   ink;
     if(argcount!=5)
      fFatal("OVERLAY BLOCK, incorrect number of paramaters, line %d of %s,",line,filename);
     ink=((arglist[0]<<4)&0xf0);
     if(debug)
      fBorderBlockDraw(arglist[1],arglist[2],arglist[3],arglist[4],ink+15);
     fOverlayBlockDraw(arglist[1],arglist[2],arglist[3],arglist[4],ink);
    }
    else if(strcmp(pcCommandName,"ELIPSE")==0)
    {
     T_UWORD   ink;

     if(argcount!=5)
      fFatal("OVERLAY ELIPSE, incorrect number of paramaters, line %d of %s,",line,filename);
     ink=((arglist[0]<<4)&0xf0);
     if(debug)
      fBorderElipseDraw(arglist[1],arglist[2],arglist[3],arglist[4],ink+15);
     fOverlayElipseDraw(arglist[1],arglist[2],arglist[3],arglist[4],ink);
    }
    else if(strcmp(pcCommandName,"ENABLE")==0)
    {
     bGblOverlayEnable=T_TRUE;
    }
    else if(strcmp(pcCommandName,"DISABLE")==0)
    {
     bGblOverlayEnable=T_FALSE;
    }
    else
    {
     fFatal("Bad/Missing command type for OVERLAY (%s) line %d of %s",pcCommandName,line,filename);
    }
   }
   else if(strcmp(pcCommandType,"BORDER")==0)
   {
    if (strcmp(pcCommandName,"TRIANGLE")==0)
    {
     T_UWORD ink=((arglist[0]<<4)&0xf0)+(arglist[1]&0x0f);
     int x0=arglist[2];
     int y0=arglist[3];
     int x1=arglist[4];
     int y1=arglist[5];
     int x2=arglist[6];
     int y2=arglist[7];
     fBorderTriangleDraw(x0,y0,x1,y1,x2,y2,ink);
    }
    else if(strcmp(pcCommandName,"BLOCK")==0)
    {
     T_UWORD   ink;
     if(argcount!=6)
      fFatal("BORDER BLOCK, incorrect number of paramaters, line %d of %s,",line,filename);
     ink=((arglist[0]<<4)&0xf0)+(arglist[1]&0x0f);

     fBorderBlockDraw(arglist[2],arglist[3],arglist[4],arglist[5],ink);
    }
    else if(strcmp(pcCommandName,"LINE")==0)
    {
     T_UWORD   ink;
     if(argcount!=6)
      fFatal("BORDER LINE, incorrect number of paramaters, line %d of %s,",line,filename);
     ink=((arglist[0]<<4)&0xf0)+(arglist[1]&0x0f);
     fBorderLineDraw(arglist[2],arglist[3],arglist[4],arglist[5],ink);
    }
    else if(strcmp(pcCommandName,"ELIPSE")==0)
    {
     T_UWORD   ink;
     if(argcount!=6) fFatal("BORDER LINE, incorrect number of paramaters, line %d of %s,",line,filename);
     ink=((arglist[0]<<4)&0xf0)+(arglist[1]&0x0f);
     fBorderElipseDraw(arglist[2],arglist[3],arglist[4],arglist[5],ink);
    }
    else
    {
     fFatal("Bad/Missing command type for BORDER (%s) line %d of %s",pcCommandName,line,filename);
    }
   }
   else if(strcmp(pcCommandType,"SCREEN")==0)
   {
    if(strcmp(pcCommandName,"CLIP")==0)
    {
     if(argcount!=4) fFatal("SCREEN CLIP, incorrect number of paramaters, line %d of %s,",line,filename);
     scale(&iX1clip,&iY1clip,&iX2clip,&iY2clip,arglist[0],arglist[1],arglist[2],arglist[3]);
     if(iX1clip>iX2clip)
      fSwapWord(&iX1clip,&iX2clip);
     if(iY1clip>iY2clip)
      fSwapWord(&iY1clip,&iY2clip);
     iX1clip+=iXOffset;
     iY1clip+=iYOffset;
     iX2clip+=iXOffset;
     iY2clip+=iYOffset;
    }
    else if(strcmp(pcCommandName,"COLOUR")==0)
    {
     T_UWORD   ink;
     if(argcount!=5)
      fFatal("SCREEN COLOUR, incorrect number of paramaters, line %d of %s,",line,filename);
     ink=((arglist[0]<<4)&0xf0)+(arglist[1]&0x0f);
     fIOsetink(ink,arglist[2],arglist[3],arglist[4]);
    }
    else if(strcmp(pcCommandName,"OFFSET")==0)
    {
     T_SWORD  xoffs,yoffs,dummy;
     if(argcount!=2)
      fFatal("SCREEN OFFSET, incorrect number of paramaters, line %d of %s,",line,filename);
     scale(&xoffs,&yoffs,&dummy,&dummy,arglist[0],arglist[1],arglist[0],arglist[1]);
     iXOffset+=xoffs;
     iYOffset+=yoffs;
     iX1clip+=xoffs;
     iY1clip+=yoffs;
     iX2clip+=xoffs;
     iY2clip+=yoffs;
     if (bGblDisplayExactScaling==T_FALSE)
     {
      mausxmin=iXOffset-((20000>>iDivShiftAx)+(20000>>iDivShiftBx));
      mausxmax=iXOffset+((20000>>iDivShiftAx)+(20000>>iDivShiftBx));
      mausymin=iYOffset-((20000>>iDivShiftAy)+(20000>>iDivShiftBy));
      mausymax=iYOffset+((20000>>iDivShiftAy)+(20000>>iDivShiftBy));
     }
     else
     {
      mausxmin=iXOffset-20000/dividerx;
      mausxmax=iXOffset+20000/dividerx;
      mausymin=iYOffset-20000/dividery;
      mausymax=iYOffset+20000/dividery;
     }
    }
    else if(strcmp(pcCommandName,"DIVX")==0)
    {
     if(argcount!=2)
      fFatal("SCREEN DIVX, incorrect number of paramaters, line %d of %s,",line,filename);
     if (arglist[0]>RESOLUTION_COUNT)
      fFatal("SCREEN DIVX, incorrect Resolution, line %d of %s,",line,filename);
     divider_x[arglist[0]]=arglist[1];
     screen_fix=T_TRUE;
    }
    else if(strcmp(pcCommandName,"DIVY")==0)
    {
     if(argcount!=2)
      fFatal("SCREEN DIVY, incorrect number of paramaters, line %d of %s,",line,filename);
     if (arglist[0]>RESOLUTION_COUNT)
      fFatal("SCREEN DIVY, incorrect Resolution, line %d of %s,",line,filename);
     divider_y[arglist[0]]=arglist[1];
     screen_fix=T_TRUE;
    }
    else if(strcmp(pcCommandName,"SHIFTX")==0)
    {
     if(argcount!=3)
      fFatal("SCREEN SHIFTX, incorrect number of paramaters, line %d of %s,",line,filename);
     if (arglist[0]>RESOLUTION_COUNT)
      fFatal("SCREEN SHIFTX, incorrect Resolution, line %d of %s,",line,filename);
     display_infox[arglist[0]].iDivShiftA=arglist[1];
     display_infox[arglist[0]].iDivShiftB=arglist[2];
     screen_fix=T_TRUE;
    }
    else if (strcmp(pcCommandName,"SHIFTY")==0)
    {
     if(argcount!=3)
      fFatal("SCREEN SHIFTY, incorrect number of paramaters, line %d of %s,",line,filename);
     if (arglist[0]>RESOLUTION_COUNT)
      fFatal("SCREEN SHIFTY, incorrect Resolution, line %d of %s,",line,filename);
     display_infoy[arglist[0]].iDivShiftA=arglist[1];
     display_infoy[arglist[0]].iDivShiftB=arglist[2];
     screen_fix=T_TRUE;
    }
    else
    {
     fFatal("Bad/Missing command type for SCREEN (%s) line %d of %s",pcCommandName,line,filename);
    }
   }
   else if(strcmp(pcCommandType,"DEBUG")==0)
   {
    debug=T_TRUE;
   }
   else if(pcCommandType[0]=='#')
   {
    // Text comment or empty line
   }
   else
   {
    fFatal("Unrecognized token in %s line %d (%s)",filename,line,pcCommandType);
   }
   line++;
  }
  fclose(pfINIfile);
  if (current_path!=NULL)
  {
   free(current_path);
   current_path=NULL;
  }
 }
 fIOsetpalette(); /* in case new colors have been set... */
 if (screen_fix==T_TRUE)
 {
  if (bGblDisplayExactScaling==T_FALSE)
  {
   iDivShiftAx=display_infox[wGblDisplayMode].iDivShiftA;
   iDivShiftBx=display_infox[wGblDisplayMode].iDivShiftB;
   iDivShiftAy=display_infoy[wGblDisplayMode].iDivShiftA;
   iDivShiftBy=display_infoy[wGblDisplayMode].iDivShiftB;

   iX1clip=(lwGblClipX>>iDivShiftAx) + (lwGblClipX>>iDivShiftBx);
   iY1clip=(lwGblClipY>>iDivShiftAy) + (lwGblClipY>>iDivShiftBy);
   iX2clip=(-lwGblClipX>>iDivShiftAx) + (-lwGblClipX>>iDivShiftBx);
   iY2clip=(-lwGblClipY>>iDivShiftAy) + (-lwGblClipY>>iDivShiftBy);

   mausxmin=iXOffset-((20000>>iDivShiftAx)+(20000>>iDivShiftBx));
   mausxmax=iXOffset+((20000>>iDivShiftAx)+(20000>>iDivShiftBx));
   mausymin=iYOffset-((20000>>iDivShiftAy)+(20000>>iDivShiftBy));
   mausymax=iYOffset+((20000>>iDivShiftAy)+(20000>>iDivShiftBy));
  }
  else
  {
   dividerx=divider_x[wGblDisplayMode];
   dividery=divider_y[wGblDisplayMode];

   iX1clip=lwGblClipX/dividerx;
   iY1clip=lwGblClipY/dividery;
   iX2clip=-lwGblClipX/dividerx;
   iY2clip=-lwGblClipY/dividery;

   mausxmin=iXOffset-20000/dividerx; // just in case a lightpen
   mausxmax=iXOffset+20000/dividerx; // will be enabled
   mausymin=iYOffset-20000/dividery;
   mausymax=iYOffset+20000/dividery;
  }
  iX1clip+=iXOffset;
  iY1clip+=iYOffset;
  iX2clip+=iXOffset;
  iY2clip+=iYOffset;
 }
 return T_TRUE;
}

T_VOID fBorderTriangleDraw(T_SLONG xl0, T_SLONG yl0, T_SLONG xl1, T_SLONG yl1, T_SLONG xl2, T_SLONG yl2,T_UWORD ink)
{
 T_SWORD x0,x1,x2,y0,y1,y2;

 T_SWORD bottom_x,top_x,mid_v_x;
 T_SWORD bottom_y,top_y,mid_v_y;
 int i;

 /**************************/
 /* Scale to screen coords */
 /**************************/
// yl0=-yl0;
// yl1=-yl1;
// yl2=-yl2;

 scale(&x0,&y0,&x1,&y1,xl0,yl0,xl1,yl1);
 scale(&x0,&y0,&x2,&y2,xl0,yl0,xl2,yl2);

 x0+=iXOffset;
 y0+=iYOffset;
 x1+=iXOffset;
 y1+=iYOffset;
 x2+=iXOffset;
 y2+=iYOffset;


 if ((y0>=y1)&&(y0>=y2))
 {
  bottom_y=y0;
  bottom_x=x0;
  if ((y1<=y0)&&(y1<=y2))
  {
   top_y=y1;
   top_x=x1;
   mid_v_y=y2;
   mid_v_x=x2;
  }
  else if ((y2<=y0)&&(y2<=y1))
  {
   top_y=y2;
   top_x=x2;
   mid_v_y=y1;
   mid_v_x=x1;
  }
 }
 else if ((y1>=y0)&&(y1>=y2))
 {
  bottom_y=y1;
  bottom_x=x1;
  if ((y0<=y1)&&(y0<=y2))
  {
   top_y=y0;
   top_x=x0;
   mid_v_y=y2;
   mid_v_x=x2;
  }
  else if ((y2<=y0)&&(y2<=y1))
  {
   top_y=y2;
   top_x=x2;
   mid_v_y=y0;
   mid_v_x=x0;
  }
 }
 else if ((y2>=y0)&&(y2>=y1))
 {
  bottom_y=y2;
  bottom_x=x2;
  if ((y0<=y1)&&(y0<=y2))
  {
   top_y=y0;
   top_x=x0;
   mid_v_y=y1;
   mid_v_x=x1;
  }
   else if ((y1<=y0)&&(y1<=y2))
  {
   top_y=y1;
   top_x=x1;
   mid_v_y=y0;
   mid_v_x=x0;
  }
 }
 for (i=top_y;i<=bottom_y;i++)
 {
  int first_x,second_x;
  first_x=get_x_line(top_x,top_y,bottom_x,bottom_y,i);
  if (i<mid_v_y)
   second_x=get_x_line(top_x,top_y,mid_v_x,mid_v_y,i);
  else
   second_x=get_x_line(mid_v_x,mid_v_y,bottom_x,bottom_y,i);
 if (first_x<second_x)
  fIODrawLine(first_x,i,second_x,i,ink);
 else
  fIODrawLine(second_x,i,first_x,i,ink);
 }
}

T_SWORD get_x_line(T_SWORD iX1,T_SWORD iY1,T_SWORD iX2,T_SWORD iY2, T_SWORD y_searched)
{
 T_SWORD   dx=0,dy=0,err=0,inc=0;

/**************************/
/* Do straight line cases */
/**************************/
 if (iX1==iX2)
 {
  return iX1;
 }
 else if(iY1==iY2)
 {
  return (iX1+iX2)/2;
 }
 else
 {
  /*************/
  /* X Variant */
  /*************/
  dx=iX2-iX1;
  dy=iY2-iY1;
  if(abs(dx)>=abs(dy))
  {
   if(iX1>iX2)
   {
    fSwap(&iX1,&iX2);
    fSwap(&iY1,&iY2);
   }
   dx=iX2-iX1;
   dy=iY2-iY1;
   err=-(dx>>1);
   if(dy>0)
   {
    inc=1;
   }
   else
   {
    inc=-1;
    dy=-dy;
   }
   do
   {
    /**************************/
    /* Calulate byte position */
    /**************************/
    if (y_searched==iY1)
     return iX1;
    /**********************/
    /* Check error status */
    /**********************/
    err+=dy;
    if(err>0)
    {
     err-=dx;
     iY1+=inc;
    }
   }
   while(iX1++!=iX2);
  }
  else
  {
   if(iY1>iY2)
   {
    fSwap(&iX1,&iX2);
    fSwap(&iY1,&iY2);
   }
   dx=iX2-iX1;
   dy=iY2-iY1;
   err=-(dy>>1);
   if(dx>0)
   {
    inc=1;
   }
   else
   {
    inc=-1;
    dx=-dx;
   }
   do
   {
    /**************************/
    /* Calulate byte position */
    /**************************/
    if (y_searched==iY1)
     return iX1;
    /**********************/
    /* Check error status */
    /**********************/
    err+=dx;
    if(err>=0)
    {
     err-=dy;
     iX1+=inc;
    }
   }
   while(iY1++!=iY2);
  }
 }
 return iX2;
}

T_VOID fOverlayTriangleDraw(T_SLONG xl0, T_SLONG yl0, T_SLONG xl1, T_SLONG yl1, T_SLONG xl2, T_SLONG yl2,T_UWORD ink)
{
 T_SWORD x0,x1,x2,y0,y1,y2;

 T_UWORD bottom_x,top_x,mid_v_x;
 T_UWORD bottom_y,top_y,mid_v_y;
 int i;

 /**************************/
 /* Scale to screen coords */
 /**************************/
// yl0=-yl0;
// yl1=-yl1;
// yl2=-yl2;

 scale(&x0,&y0,&x1,&y1,xl0,yl0,xl1,yl1);
 scale(&x0,&y0,&x2,&y2,xl0,yl0,xl2,yl2);

 x0+=iXOffset;
 y0+=iYOffset;
 x1+=iXOffset;
 y1+=iYOffset;
 x2+=iXOffset;
 y2+=iYOffset;

 if ((y0>=y1)&&(y0>=y2))
 {
  bottom_y=y0;
  bottom_x=x0;
  if ((y1<=y0)&&(y1<=y2))
  {
   top_y=y1;
   top_x=x1;
   mid_v_y=y2;
   mid_v_x=x2;
  }
  else if ((y2<=y0)&&(y2<=y1))
  {
   top_y=y2;
   top_x=x2;
   mid_v_y=y1;
   mid_v_x=x1;
  }
 }
 else if ((y1>=y0)&&(y1>=y2))
 {
  bottom_y=y1;
  bottom_x=x1;
  if ((y0<=y1)&&(y0<=y2))
  {
   top_y=y0;
   top_x=x0;
   mid_v_y=y2;
   mid_v_x=x2;
  }
  else if ((y2<=y0)&&(y2<=y1))
  {
   top_y=y2;
   top_x=x2;
   mid_v_y=y0;
   mid_v_x=x0;
  }
 }
 else if ((y2>=y0)&&(y2>=y1))
 {
  bottom_y=y2;
  bottom_x=x2;
  if ((y0<=y1)&&(y0<=y2))
  {
   top_y=y0;
   top_x=x0;
   mid_v_y=y1;
   mid_v_x=x1;
  }
   else if ((y1<=y0)&&(y1<=y2))
  {
   top_y=y1;
   top_x=x1;
   mid_v_y=y0;
   mid_v_x=x0;
  }
 }
 for (i=top_y;i<=bottom_y;i++)
 {
  int first_x,second_x;
  first_x=get_x_line(top_x,top_y,bottom_x,bottom_y,i);
  if (i<mid_v_y)
   second_x=get_x_line(top_x,top_y,mid_v_x,mid_v_y,i);
  else
   second_x=get_x_line(mid_v_x,mid_v_y,bottom_x,bottom_y,i);
  if (first_x<second_x)
   fOverlayDrawLine(first_x,i,second_x,i,ink);
  else
   fOverlayDrawLine(second_x,i,first_x,i,ink);
 }
}

T_VOID fOverlayDrawLine(T_SWORD iX1,T_SWORD iY1,T_SWORD iX2,T_SWORD iY2,T_SWORD iColour)
{
 T_PUCHAR dest=(T_PUCHAR )overlay_memory;
 T_SWORD   dx=0,dy=0,err=0,inc=0;

/**************************/
/* Do straight line cases */
/**************************/
 if (iX1==iX2)
 {
  if(iY1>iY2)
  {
   fSwap(&iY1,&iY2);
  }
  do
  {
   /******************************************************************************************/
   /* not to be put out of loop, offset can get to high... (high iY1 are pointing to maxline)*/
   /******************************************************************************************/
   offset=vlinestartpos[(T_UWORD)iY1]+(T_ULONG)iX1;
   *(dest+offset)=(T_UCHAR)iColour;
  }
  while(iY1++!=iY2);
 }
 else if(iY1==iY2)
 {
  if(iX1>iX2)
  {
   fSwap(&iX1,&iX2);
  }
  offset=vlinestartpos[(T_UWORD)iY1]+(T_ULONG)iX1;
  do
  {
   *(dest+offset)=(T_UCHAR)iColour;
   offset++;
  }
  while(iX1++!=iX2);
 }
 else
 {
  /*************/
  /* X Variant */
  /*************/
  dx=iX2-iX1;
  dy=iY2-iY1;
  if(abs(dx)>=abs(dy))
  {
   if(iX1>iX2)
   {
    fSwap(&iX1,&iX2);
    fSwap(&iY1,&iY2);
   }
   dx=iX2-iX1;
   dy=iY2-iY1;
   err=-(dx>>1);
   if(dy>0)
   {
    inc=1;
   }
   else
   {
    inc=-1;
    dy=-dy;
   }
   do
   {
    /**************************/
    /* Calulate byte position */
    /**************************/
    offset=vlinestartpos[(T_UWORD)iY1]+(T_ULONG)iX1;
    *(dest+offset)=(T_UCHAR)iColour;
    /**********************/
    /* Check error status */
    /**********************/
    err+=dy;
    if(err>0)
    {
     err-=dx;
     iY1+=inc;
    }
   }
   while(iX1++!=iX2);
  }
  else
  {
   if(iY1>iY2)
   {
    fSwap(&iX1,&iX2);
    fSwap(&iY1,&iY2);
   }
   dx=iX2-iX1;
   dy=iY2-iY1;
   err=-(dy>>1);
   if(dx>0)
   {
    inc=1;
   }
   else
   {
    inc=-1;
    dx=-dx;
   }
   do
   {
    /**************************/
    /* Calulate byte position */
    /**************************/
    offset=vlinestartpos[(T_UWORD)iY1]+(T_ULONG)iX1;
    *(dest+offset)=(T_UCHAR)iColour;
    /**********************/
    /* Check error status */
    /**********************/
    err+=dx;
    if(err>=0)
    {
     err-=dy;
     iX1+=inc;
    }
   }
   while(iY1++!=iY2);
  }
 }
}

T_VOID vector_undraw(T_VOID) /* not remove from hashtable */
{
 T_SWORD iTmp;
 iTmp=line_rootnode;
 while(iTmp!=-1)
 {
  static T_SWORD iX1;
  static T_SWORD iY1;
  static T_SWORD iX2;
  static T_SWORD iY2;
  static T_SWORD iColour;
  static T_SWORD is_dot;

  iX1=line_store[iTmp].iX1;
  iY1=line_store[iTmp].iY1;
  iX2=line_store[iTmp].iX2;
  iY2=line_store[iTmp].iY2;
  iColour=line_store[iTmp].brightness;
  is_dot=line_store[iTmp].is_dot;
#define DEBUG_MSG
  if (blinetype==T_NORMAL)
  {
   if (bGblGoggleGame==T_TRUE)
   {
    #define DISPLAY_TICK_IMAGER
    T_INT imager_color_save=ImagerColorNow;
    ImagerColorNow=line_store[iTmp].imager_color;
    if (framebuffer==FB_LINEAR)
    {
     #define DISPLAY_TICK_LINEAR
     #include "line.cc"
     #undef DISPLAY_TICK_LINEAR
    }
    if (framebuffer==FB_BANKED)
    {
     #define DISPLAY_TICK_BANKED
     #define BANKED
     #include "line.cc"
     #undef BANKED
     #undef DISPLAY_TICK_BANKED
    }
    #undef DISPLAY_TICK_IMAGER
    ImagerColorNow=imager_color_save;
   } //if (bGblGoggleGame=T_TRUE)
   else
   {
    if (framebuffer==FB_LINEAR)
    {
     #define DISPLAY_TICK_LINEAR
     #include "line.cc"
     #undef DISPLAY_TICK_LINEAR
    }
    if (framebuffer==FB_BANKED)
    {
     #define DISPLAY_TICK_BANKED
     #define BANKED
     #include "line.cc"
     #undef BANKED
     #undef DISPLAY_TICK_BANKED
    }
    #undef DISPLAY_TICK_IMAGER
   } //else if (bGblGoggleGame=T_TRUE)
  } //if (blinetype==T_NORMAL)
  else
  {
   if (bGblGoggleGame==T_TRUE)
   {
    #define DISPLAY_TICK_IMAGER
    T_INT imager_color_save=ImagerColorNow;
    ImagerColorNow=line_store[iTmp].imager_color;
    if (framebuffer==FB_LINEAR)
    {
     #define DISPLAY_TICK_LINEAR
     #include "line_aa.cc"
     #undef DISPLAY_TICK_LINEAR
    }
    if (framebuffer==FB_BANKED)
    {
     #define DISPLAY_TICK_BANKED
     #define BANKED
     #include "line_aa.cc"
     #undef BANKED
     #undef DISPLAY_TICK_BANKED
    }
    #undef DISPLAY_TICK_IMAGER
    ImagerColorNow=imager_color_save;
   } //if (bGblGoggleGame=T_TRUE)
   else
   {
    if (framebuffer==FB_LINEAR)
    {
     #define DISPLAY_TICK_LINEAR
     #include "line_aa.cc"
     #undef DISPLAY_TICK_LINEAR
    }
    if (framebuffer==FB_BANKED)
    {
     #define DISPLAY_TICK_BANKED
     #define BANKED
     #include "line_aa.cc"
     #undef BANKED
     #undef DISPLAY_TICK_BANKED
    }
    #undef DISPLAY_TICK_IMAGER
   } //else if (bGblGoggleGame=T_TRUE)
  } // else if (blinetype==T_NORMAL)
  iTmp=line_store[iTmp].next_vector;
 }
}
