#pragma message ( "including dline.cc" );
/*****************************************************************************/
/*                                                                           */
/*   Function    : fDisplayLineDraw()                                        */
/*                                                                           */
/*   Author      : K.W / C.S.                                                */
/*                                                                           */
/*   Description : This is the function that is called by the emulation code */
/*                 to register and draw a line with the display functions    */
/*                 that emulate the persistance of the monitor               */
/*                                                                           */
/*   Accepts     : Coordinates of the line to be plotted                     */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/
//void fDisplayLineDraw_shift_lin(SLONG lX1,SLONG lY1,SLONG lX2,SLONG lY2,UBYTE tBright)
fDebug(LOW,("fDisplayLineDraw() - <%08ld>,<%08ld> to <%08ld>,<%08ld> in pen <%03d>",lX1,lY1,lX2,lY2,tBright));

/********************************/
/* Scale and correct brightness */
/********************************/
// tBright&=0x7f;

if (tBright<0x80)
if ((tBright>>=3))
{
 /*
 chris:Feb '97
 This adds the upper 4 bits to the display color,
 I assume overlay colors have been set to wGblDisplayBaseColour so this is
 really not neccessary, inspite it collides with
 the brightness '&' in linedraw
 tBright+=wGblDisplayBaseColour<<4;
 instead:
 tBright+=128+64+32+16;
 */
 // tBright|=128+64+32+16;
 // printf("tBright:%i\n",tBright);
 /**************************/
 /* Scale to screen coords */
 /**************************/
 lY1=-lY1;
 lY2=-lY2;

#if defined DISPLAY_LINE_LINEAR_SHIFT || defined DISPLAY_LINE_BANKED_SHIFT
 diX1=(lX1>>iDivShiftAx) + (lX1>>iDivShiftBx) + iXOffset;
 diX2=(lX2>>iDivShiftAx) + (lX2>>iDivShiftBx) + iXOffset;
 diY1=(lY1>>iDivShiftAy) + (lY1>>iDivShiftBy) + iYOffset;
 diY2=(lY2>>iDivShiftAy) + (lY2>>iDivShiftBy) + iYOffset;
#endif
#if defined DISPLAY_LINE_LINEAR_DIV || defined DISPLAY_LINE_BANKED_DIV
 diX1=lX1/dividerx+iXOffset;
 diX2=lX2/dividerx+iXOffset;
 diY1=lY1/dividery+iYOffset;
 diY2=lY2/dividery+iYOffset;
#endif

 if (bGblOverlayEnable)
 {
  if (bGblDisplayEnable)
  {
   /********************************************/
   /*  Work out the hashing code for this line */
   /********************************************/
   // hash_code=((UWORD)(diX1*diY1+diX2*diY2))%HASH_TABLE_SIZE; /* better distribution, but MUL -> slower */
   // ((diX1+diY1+HASH_TABLE_SIZE/2)^(diX2+diY2))&HASH_MASK; /* Keiths function */
   hash_code=((T_ULONG)(lX1+lX2+lY1+lY2))%HASH_TABLE_SIZE; /* works ok... */

   /*************************************************************/
   /* Scan the Active list for this line & refresh if necessary */
   /*************************************************************/
   hash=hash_rootnodes[hash_code];
   while (hash!=-1)
   {
    /**************************************/
    /* Convert hash entry to a line entry */
    /**************************************/
    line=hash_store[hash].line_index;

    /*******************************************/
    /* If the line exists then refresh the AGE */
    /*******************************************/

// should add brightness to the line check, since lines with different
// brightness SHOULD be updated with the new value...
// this is not done yet! DONE !!!
// (dunno if this is really important!)
//
// it is VERY important for anti aliased lines, since they are differently
// drawn for different intervall sizes, which relates directly to brightness!!!
//
    if (line_store[line].iX1==diX1 && line_store[line].iY1==diY1 && line_store[line].iX2==diX2 && line_store[line].iY2==diY2 && line_store[line].brightness==tBright)
    {
     /**********************************************************/
     /* The refresh period may be too long if age!=0           */
     /* We pick a line that has been refreshed and hold        */
     /* that line number, after being refreshed X times        */
     /* we calculate what the new refresh period should be     */
     /*                                                        */
     /* Check if this is the reference line used for display   */
     /* refresh timing, if so then increase the lost reference */
     /* count and clear the line reference, after we've lost   */
     /* iAdjustCount references we will change the line period */
     /**********************************************************/
     if (bGblDisplayAutoRefresh && iLineSelected==-1)
     {
      iLineSelected=line;
      iLineSelector=LINE_REFRESH_LIMIT;
      lwRefreshMarker=lwGblSystemTickTotal;
      fDebug(MED,("fDisplayLineDraw() - Selected candidate refresh line %d ",iLineSelected));
     }
     else if (bGblDisplayAutoRefresh && line==iLineSelected && !--iLineSelector)
     {
      iLineSelected=-1;
      lwGblDisplayTickReload=((lwGblSystemTickTotal-lwRefreshMarker)/(LINE_REFRESH_LIMIT));

      if(lwGblDisplayTickReload>lwGblDisplayTickMax)
       lwGblDisplayTickReload=lwGblDisplayTickMax;
      if(lwGblDisplayTickReload<lwGblDisplayTickMin)
       lwGblDisplayTickReload=lwGblDisplayTickMin;
      fDebug(MED,("fDisplayLineDraw() - Tracking: Age(%d) Reload(%ld)",wGblDisplayLinePeriod,lwGblDisplayTickReload));
     }
     /************************/
     /* Refresh the line age */
     /************************/
     line_store[line].age=wGblDisplayLinePeriod;
//     line_store[line].brightness=tBright;
     break;
    }
    hash=hash_store[hash].next_hash;
   } // while (hash!=-1)
   /*******************************************************************************/
   /* If line didn't exist then add to the Active list, steal node from free list */
   /*******************************************************************************/
   if (hash==-1)
   {
    /************************************************/
    /* Create line store entry, insert at root node */
    /************************************************/
    if (line_freelist!=-1)
    {
     /************************************************/
     /* Create line store entry, insert at root node */
     /************************************************/
     line=line_freelist;
     line_freelist=line_store[line_freelist].next_vector;
     line_store[line].next_vector=line_rootnode;
     line_rootnode=line;

     line_store[line].iX1=diX1;
     line_store[line].iY1=diY1;
     line_store[line].iX2=diX2;
     line_store[line].iY2=diY2;
     line_store[line].brightness=tBright;
     line_store[line].imager_color=ImagerColorNow;
     line_store[line].age=wGblDisplayLinePeriod;
    #ifdef ANTI_ALIASING
     if (tSIGDEF_RAMPB)
//     if (lYSampleHold/*+lXSampleHold*/==0)
      line_store[line].is_dot=T_TRUE;
     else
      line_store[line].is_dot=T_FALSE;
    #endif
    }
    else
    {
     fDebug(VERROR,("fDisplayLineDraw() - Line bufffer overflow, %d vectors exceeded",LINESTORE_DEPTH));
     fFatal("fDisplayLineDraw() - Line buffer overflow");
    }

    /***************************************************************************/
    /* Create hash store entry, shouldn't ever need to check as both freelists */
    /* should ALWAYS have the same free space.                                 */
    /***************************************************************************/

    /************************************************/
    /* Create line store entry, insert at root node */
    /************************************************/
    hash=hash_freelist;
    hash_freelist=hash_store[hash_freelist].next_hash;

    hash_store[hash].next_hash=hash_rootnodes[hash_code];
    hash_store[hash].prev_hash=-1;
    if (hash_rootnodes[hash_code]!=-1)
     hash_store[hash_rootnodes[hash_code]].prev_hash=hash;
    hash_rootnodes[hash_code]=hash;

    hash_store[hash].line_index=line;
    hash_store[hash].hash_code=hash_code;

    /******************************/
    /* Cross link the two entries */
    /******************************/
    line_store[line].hash_index=hash;
    #define iColour tBright
    #define iX1 diX1
    #define iX2 diX2
    #define iY1 diY1
    #define iY2 diY2
    #define is_dot line_store[line].is_dot
    /***************************/
    /* inlining, bad isn't it? */
    /***************************/
// neu


    #ifdef ANTI_ALIASING
    #if defined DISPLAY_LINE_LINEAR_SHIFT || defined DISPLAY_LINE_LINEAR_DIV
    #include "mline_aa.cc"
    #endif
    #if defined DISPLAY_LINE_BANKED_SHIFT || defined DISPLAY_LINE_BANKED_DIV
    #define BANKED
    #include "mline_aa.cc"
    #undef BANKED
    #endif
    #else
    #if defined DISPLAY_LINE_LINEAR_SHIFT || defined DISPLAY_LINE_LINEAR_DIV
    #include "mline.cc"
    #endif
    #if defined DISPLAY_LINE_BANKED_SHIFT || defined DISPLAY_LINE_BANKED_DIV
    #define BANKED
    #include "mline.cc"
    #undef BANKED
    #endif
    #endif

    #undef is_dot
    #undef iColour
    #undef iX1
    #undef iX2
    #undef iY1
    #undef iY2
   } // if (hash==-1)
  } // if (bGblDisplayEnable)
 } // if (bGblOverlayEnable)
 else
 {
  tBright|=wGblDisplayBaseColour<<4;
  if (bGblDisplayEnable)
  {
   /********************************************/
   /*  Work out the hashing code for this line */
   /********************************************/
   // hash_code=((UWORD)(diX1*diY1+diX2*diY2))%HASH_TABLE_SIZE; /* better distribution, but MUL -> slower */
   // ((diX1+diY1+HASH_TABLE_SIZE/2)^(diX2+diY2))&HASH_MASK; /* Keiths function */
   hash_code=((T_ULONG)(lX1+lX2+lY1+lY2))%HASH_TABLE_SIZE; /* works ok... */

   /*************************************************************/
   /* Scan the Active list for this line & refresh if necessary */
   /*************************************************************/
   hash=hash_rootnodes[hash_code];
   while (hash!=-1)
   {
    /**************************************/
    /* Convert hash entry to a line entry */
    /**************************************/
    line=hash_store[hash].line_index;

    /*******************************************/
    /* If the line exists then refresh the AGE */
    /*******************************************/
    if (line_store[line].iX1==diX1 && line_store[line].iY1==diY1 && line_store[line].iX2==diX2 && line_store[line].iY2==diY2 && line_store[line].brightness==tBright)
    {
     /**********************************************************/
     /* The refresh period may be too long if age!=0           */
     /* We pick a line that has been refreshed and hold        */
     /* that line number, after being refreshed X times        */
     /* we calculate what the new refresh period should be     */
     /*                                                        */
     /* Check if this is the reference line used for display   */
     /* refresh timing, if so then increase the lost reference */
     /* count and clear the line reference, after we've lost   */
     /* iAdjustCount references we will change the line period */
     /**********************************************************/
     if (bGblDisplayAutoRefresh && iLineSelected==-1)
     {
      iLineSelected=line;
      iLineSelector=LINE_REFRESH_LIMIT;
      lwRefreshMarker=lwGblSystemTickTotal;
      fDebug(MED,("fDisplayLineDraw() - Selected candidate refresh line %d ",iLineSelected));
     }
     else if (bGblDisplayAutoRefresh && line==iLineSelected && !--iLineSelector)
     {
      iLineSelected=-1;
      lwGblDisplayTickReload=((lwGblSystemTickTotal-lwRefreshMarker)/(LINE_REFRESH_LIMIT));

      if(lwGblDisplayTickReload>lwGblDisplayTickMax)
       lwGblDisplayTickReload=lwGblDisplayTickMax;
      if(lwGblDisplayTickReload<lwGblDisplayTickMin)
       lwGblDisplayTickReload=lwGblDisplayTickMin;
      fDebug(MED,("fDisplayLineDraw() - Tracking: Age(%d) Reload(%ld)",wGblDisplayLinePeriod,lwGblDisplayTickReload));
     }
     /************************/
     /* Refresh the line age */
     /************************/
     line_store[line].age=wGblDisplayLinePeriod;
//     line_store[line].brightness=tBright;
     break;
    }
    hash=hash_store[hash].next_hash;
   } // while (hash!=-1)
   /*******************************************************************************/
   /* If line didn't exist then add to the Active list, steal node from free list */
   /*******************************************************************************/
   if (hash==-1)
   {
    /************************************************/
    /* Create line store entry, insert at root node */
    /************************************************/
    if (line_freelist!=-1)
    {
     /************************************************/
     /* Create line store entry, insert at root node */
     /************************************************/
     line=line_freelist;
     line_freelist=line_store[line_freelist].next_vector;
     line_store[line].next_vector=line_rootnode;
     line_rootnode=line;

     line_store[line].iX1=diX1;
     line_store[line].iY1=diY1;
     line_store[line].iX2=diX2;
     line_store[line].iY2=diY2;
     line_store[line].brightness=tBright;
     line_store[line].imager_color=ImagerColorNow;
     line_store[line].age=wGblDisplayLinePeriod;
    #ifdef ANTI_ALIASING
     if (lYSampleHold+lXSampleHold==0)
      line_store[line].is_dot=T_TRUE;
     else
      line_store[line].is_dot=T_FALSE;
    #endif
    }
    else
    {
     fDebug(VERROR,("fDisplayLineDraw() - Line bufffer overflow, %d vectors exceeded",LINESTORE_DEPTH));
     fFatal("fDisplayLineDraw() - Line buffer overflow");
    }

    /***************************************************************************/
    /* Create hash store entry, shouldn't ever need to check as both freelists */
    /* should ALWAYS have the same free space.                                 */
    /***************************************************************************/

    /************************************************/
    /* Create line store entry, insert at root node */
    /************************************************/
    hash=hash_freelist;
    hash_freelist=hash_store[hash_freelist].next_hash;

    hash_store[hash].next_hash=hash_rootnodes[hash_code];
    hash_store[hash].prev_hash=-1;
    if (hash_rootnodes[hash_code]!=-1)
     hash_store[hash_rootnodes[hash_code]].prev_hash=hash;
    hash_rootnodes[hash_code]=hash;

    hash_store[hash].line_index=line;
    hash_store[hash].hash_code=hash_code;

    /******************************/
    /* Cross link the two entries */
    /******************************/
    line_store[line].hash_index=hash;
    #define iColour tBright
    #define iX1 diX1
    #define iX2 diX2
    #define iY1 diY1
    #define iY2 diY2
    #define is_dot line_store[line].is_dot
    /***************************/
    /* inlining, bad isn't it? */
    /***************************/



    #ifdef ANTI_ALIASING
    #if defined DISPLAY_LINE_LINEAR_SHIFT || defined DISPLAY_LINE_LINEAR_DIV
    #include "line_aa.cc"
    #endif
    #if defined DISPLAY_LINE_BANKED_SHIFT || defined DISPLAY_LINE_BANKED_DIV
    #define BANKED
    #include "line_aa.cc"
    #undef BANKED
    #endif
    #else
    #if defined DISPLAY_LINE_LINEAR_SHIFT || defined DISPLAY_LINE_LINEAR_DIV
    #include "line.cc"
    #endif
    #if defined DISPLAY_LINE_BANKED_SHIFT || defined DISPLAY_LINE_BANKED_DIV
    #define BANKED
    #include "line.cc"
    #undef BANKED
    #endif
    #endif

    #undef is_dot
    #undef iColour
    #undef iX1
    #undef iX2
    #undef iY1
    #undef iY2
   } // if (hash==-1)
  } // if (bGblDisplayEnable)
 } // if (bGblOverlayEnable)
} // if ((tBright>>=3))



