home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / Atari800 / antic.c < prev    next >
C/C++ Source or Header  |  1998-03-09  |  39KB  |  1,670 lines

  1. /*
  2.     *****************************************************************
  3.     *                                *
  4.     *    Section            :    Antic Display Modes    *
  5.     *    Original Author        :    David Firth        *
  6.     *                               :       Thomas Richter (thor)   *
  7.     *    Date Written        :    28th May 1995        *
  8.     *                               :       17th February 1988      *
  9.     *    Version            :    1.3            *
  10.     *                                *
  11.     *                                *
  12.     *   Description                            *
  13.     *   -----------                            *
  14.     *                                *
  15.     *   Section that handles Antic display modes. Not required    *
  16.     *   for BASIC version.                        *
  17.     *                                *
  18.     *****************************************************************
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23.  
  24. #ifndef AMIGA
  25. #include "config.h"
  26. #endif
  27.  
  28. #include "atari.h"
  29. #include "rt-config.h"
  30. #include "mem.h"
  31. #include "cpu.h"
  32. #include "gtia.h"
  33. #include "antic.h"
  34.  
  35. #define FALSE 0
  36. #define TRUE 1
  37.  
  38. int xmin;
  39. int xmax;
  40.  
  41. int dmactl_xmin_noscroll;
  42. int dmactl_xmax_noscroll;
  43. static int dmactl_xmin_scroll;
  44. static int dmactl_xmax_scroll;
  45. static int memory_basis;          /* refresh cycles needed for memory */
  46. static int pm_dma;                /* DMA cycles needed by P/M graphics */
  47. static int char_delta;
  48. static int char_offset;
  49. static int invert_mask;
  50. static int blank_mask;
  51. static int screenaddr;
  52. #ifdef DEBUG
  53. static int hpos;                  /* identifier for horizontal position.
  54.                      used for debugging only. */
  55. #define H_BEFORE_DMA 1
  56. #define H_FIRST_HALF 2
  57. #define H_SECOND_HALF 3
  58. #define H_AFTER_WSYNC 4
  59. static int dlipos;
  60. static int dline;
  61. #endif
  62.  
  63.  
  64. /* colour lookup tables */
  65.  
  66. static int lookup_f[256];
  67. static int lookup_4[256];
  68. static int lookup24[256];
  69. static int lookup_6[256];
  70. static int lookup_9[256];
  71.  
  72. /* the scan line buffer of antic */
  73. static int scanbuf[64];
  74.  
  75. /* A function that is used to build the graphics for a given line of 
  76.    the mode line.
  77.    fillin is the pointer where to put the screen data in. Due to CPU
  78.    limitations, THIS BUFFER MUST BE LONGWORD ALIGNED. To allow HSCROLLING,
  79.    all this magic is done in the GTIA module, not here.
  80.    width is the width of the scan line, in half color clocks.
  81.    scanline is the scanline to be displayed, counts from zero up. */
  82.  
  83. typedef void ModeFunc(UBYTE *fillin,int width,int scanline);
  84.  
  85. static char *rcsid = "$Id: antic.c,v 1.30 1998/02/17 thor,david Exp $";
  86.  
  87. UBYTE CHACTL;
  88. UBYTE CHBASE;
  89. UWORD DLIST,DLISTINIT;
  90. UBYTE DMACTL;
  91. UBYTE HSCROL;
  92. UBYTE NMIEN;
  93. UBYTE NMIST;
  94. UBYTE PMBASE;
  95. UBYTE VSCROL;
  96.  
  97. int DMAwidth;
  98.  
  99. extern UWORD regPC;
  100.  
  101. /*
  102.  * These are defined for Word (2 Byte) memory accesses. I have not
  103.  * defined Longword (4 Byte) values since the Sparc architecture
  104.  * requires that Longword are on a longword boundry.
  105.  *
  106.  * Words accesses don't appear to be a problem because the first
  107.  * pixel plotted on a line will always be at an even offset, and
  108.  * hence on a word boundry.
  109.  *
  110.  * Note: HSCROL is in colour clocks whereas the pixels are emulated
  111.  *       down to a half colour clock - the first pixel plotted is
  112.  *       moved across by 2*HSCROL
  113.  */
  114.  
  115. #define PF2_COLPF0 0x0404
  116. #define PF2_COLPF1 0x0505
  117. #define PF2_COLPF2 0x0606
  118. #define PF2_COLPF3 0x0707
  119. #define PF2_COLBK 0x0808
  120. #define PF2_COLPF1_FID 0x1515
  121.  
  122. #define PF4_COLPF0 0x04040404
  123. #define PF4_COLPF1 0x05050505
  124. #define PF4_COLPF2 0x06060606
  125. #define PF4_COLPF3 0x07070707
  126. #define PF4_COLBK 0x08080808
  127. #define PF4_COLPF1_FID 0x15151515
  128.  
  129. /* The middle of the display. All color/display/whatever changes BEFORE that
  130.    cycle are seen on the same row.
  131.    All changes after this color clock are visible ON THE NEXT row */
  132. #define CC_MIDDLE 50
  133. /* The propagation delay needed by the 6502 to react on the NMI interrupt */
  134. #define DLI_DELAY 8
  135. /* The number of cycles available on the same row to proceed after WSYNC and
  136.    before the horizontal blank */
  137. #define AFTER_WSYNC 20
  138. /* The number of cycles available after the horizontal blank but before the
  139.    DMA of antic actually starts */
  140. #define BEFORE_DMA 0
  141. /* The line where the VSYNC is generated. */
  142. #define VSYNC_POS 250
  143.  
  144. int cc_middle=CC_MIDDLE;
  145. int dli_delay=DLI_DELAY;
  146. int after_wsync=AFTER_WSYNC;
  147. int before_dma=BEFORE_DMA;
  148. int vsync_pos=VSYNC_POS;
  149.  
  150.  
  151. int ypos;
  152.  
  153. /*
  154.  * Pre-computed values for improved performance
  155.  */
  156.  
  157. static int chbase_40; /* CHBASE for 40 character mode */
  158. static int chbase_20; /* CHBASE for 20 character mode */
  159. static int maddr_s; /* Address of Missiles - Single Line Resolution */
  160. static int p0addr_s; /* Address of Player0 - Single Line Resolution */
  161. static int p1addr_s; /* Address of Player1 - Single Line Resolution */
  162. static int p2addr_s; /* Address of Player2 - Single Line Resolution */
  163. static int p3addr_s; /* Address of Player3 - Single Line Resolution */
  164. static int maddr_d; /* Address of Missiles - Double Line Resolution */
  165. static int p0addr_d; /* Address of Player0 - Double Line Resolution */
  166. static int p1addr_d; /* Address of Player1 - Double Line Resolution */
  167. static int p2addr_d; /* Address of Player2 - Double Line Resolution */
  168. static int p3addr_d; /* Address of Player3 - Double Line Resolution */
  169.  
  170. int wsync_halt = 0;
  171. static int carry=0;   /* carry over of CPU cycles */
  172.  
  173. /*
  174.    =============================================================
  175.    Define screen as ULONG to ensure that it is Longword aligned.
  176.    This allows special optimisations under certain conditions.
  177.    -------------------------------------------------------------
  178.    The extra 16 scanlines is used as an overflow buffer and has
  179.    enough room for any extra mode line. It is needed on the
  180.    occasions that a valid JVB instruction is not found in the
  181.    display list - An automatic break out will occur when ypos
  182.    is greater than the ATARI_HEIGHT, if its one less than this
  183.    there must be enough space for another mode line.
  184.    =============================================================
  185. */
  186.  
  187. ULONG *atari_screen = NULL;
  188. UBYTE *scrn_ptr;
  189.  
  190. /* I/O register read */
  191.  
  192. mtype ANTIC_CHBASE_GET(void)
  193. {
  194.   return CHBASE;
  195. }
  196.  
  197. mtype ANTIC_CHACTL_GET(void)
  198. {
  199.   return CHACTL;
  200. }
  201.  
  202. mtype ANTIC_DLISTL_GET(void)
  203. {
  204.   return DLIST & 0xff;
  205. }
  206.  
  207. mtype ANTIC_DLISTH_GET(void)
  208. {
  209.   return DLIST >> 8;
  210. }
  211.  
  212. mtype ANTIC_DMACTL_GET(void)
  213. {
  214.   return DMACTL;
  215. }
  216.  
  217. mtype ANTIC_VCOUNT_GET(void)
  218. {
  219.   return ypos >> 1;
  220. }
  221.  
  222. mtype ANTIC_NMIEN_GET(void)
  223. {
  224.   return NMIEN | 0x1f;
  225. }
  226.  
  227. mtype ANTIC_NMIST_GET(void)
  228. {
  229.   return NMIST;
  230. }
  231.  
  232. mtype ANTIC_WSYNC_GET(void)
  233. {
  234.   if (wsync_halt)
  235.     printf("Double wsync!\n");
  236.   wsync_halt++;
  237.   return 0xff;
  238. }
  239.  
  240. /* I/O put routines */
  241.  
  242. int ANTIC_CHBASE_PUT(mtype byte)
  243. {
  244.   CHBASE = byte;
  245.   chbase_40 = (byte << 8) & 0xfc00;
  246.   chbase_20 = (byte << 8) & 0xfe00;
  247. #ifdef DEBUG
  248.   printf("CHBASE = %x, ypos %d, hpos state %d, dlipos %d dline %d\n",byte,ypos,hpos,dlipos,dline);
  249. #endif
  250.   return FALSE;
  251. }
  252.  
  253. int ANTIC_CHACTL_PUT(mtype byte)
  254. {
  255.   CHACTL = byte;
  256. /*
  257.    =================================================================
  258.    Check for vertical reflect, video invert and character blank bits
  259.    =================================================================
  260. */
  261.   switch (CHACTL & 0x07)
  262.     {
  263.     case 0x00 :
  264.       char_offset = 0;
  265.       char_delta = 1;
  266.       invert_mask = 0x00;
  267.       blank_mask = 0x00;
  268.       break;
  269.     case 0x01 :
  270.       char_offset = 0;
  271.       char_delta = 1;
  272.       invert_mask = 0x00;
  273.       blank_mask = 0x80;
  274.       break;
  275.     case 0x02 :
  276.       char_offset = 0;
  277.       char_delta = 1;
  278.       invert_mask = 0x80;
  279.       blank_mask = 0x00;
  280.       break;
  281.     case 0x03 :
  282.       char_offset = 0;
  283.       char_delta = 1;
  284.       invert_mask = 0x80;
  285.       blank_mask = 0x80;
  286.       break;
  287.     case 0x04 :
  288.       char_offset = 7;
  289.       char_delta = -1;
  290.       invert_mask = 0x00;
  291.       blank_mask = 0x00;
  292.       break;
  293.     case 0x05 :
  294.       char_offset = 7;
  295.       char_delta = -1;
  296.       invert_mask = 0x00;
  297.       blank_mask = 0x80;
  298.       break;
  299.     case 0x06 :
  300.       char_offset = 7;
  301.       char_delta = -1;
  302.       invert_mask = 0x80;
  303.       blank_mask = 0x00;
  304.       break;
  305.     case 0x07 :
  306.       char_offset = 7;
  307.       char_delta = -1;
  308.       invert_mask = 0x80;
  309.       blank_mask = 0x80;
  310.       break;
  311.     }
  312.  
  313.   return FALSE;
  314. }
  315.  
  316. int ANTIC_DLISTL_PUT(mtype byte)
  317. {
  318.   DLIST = (DLIST & 0xff00) | byte;
  319.   DLISTINIT = DLIST;
  320.   return FALSE;
  321. }
  322.  
  323. int ANTIC_DLISTH_PUT(mtype byte)
  324. {
  325.   DLIST = (DLIST & 0x00ff) | (byte<<8);  
  326.   DLISTINIT = DLIST;
  327.   return FALSE;
  328. }
  329.  
  330. int ANTIC_DMACTL_PUT(mtype byte)
  331. {
  332.   /* printf("DMACTL set to %2x at %4x\n",byte,regPC); */
  333.   DMACTL = byte;
  334.   switch (DMACTL & 0x03)
  335.     {
  336.     case 0x00 :
  337.       dmactl_xmin_noscroll = dmactl_xmax_noscroll = 0;
  338.       dmactl_xmin_scroll = dmactl_xmax_scroll = 0;
  339.       DMAwidth = 0;
  340.       memory_basis = 9;   /* nine cycles for refresh */
  341.       break;
  342.     case 0x01 :
  343.       dmactl_xmin_noscroll = 64;
  344.       dmactl_xmax_noscroll = ATARI_WIDTH - 64;
  345.       dmactl_xmin_scroll = 32;
  346.       dmactl_xmax_scroll = ATARI_WIDTH - 32;
  347.       DMAwidth = 4;
  348.       memory_basis = 2;   /* nine cycles for refresh */
  349.       break;
  350.     case 0x02 :
  351.       dmactl_xmin_noscroll = 32;
  352.       dmactl_xmax_noscroll = ATARI_WIDTH - 32;
  353.       dmactl_xmin_scroll = 0;
  354.       dmactl_xmax_scroll = ATARI_WIDTH;
  355.       memory_basis = 1;
  356.       DMAwidth = 5;
  357.       break;
  358.     case 0x03 :
  359.       dmactl_xmin_noscroll = dmactl_xmin_scroll = 0;
  360.       dmactl_xmax_noscroll = dmactl_xmax_scroll = ATARI_WIDTH;
  361.       memory_basis = 0;
  362.       DMAwidth = 6;
  363.       break;
  364.     }
  365.  
  366.   pm_dma = 0;   /* cycles needed for PM graphics */
  367.  
  368.   if (DMACTL & 0x0C)   /* Player DMA enables missile DMA */
  369.     pm_dma += 1;
  370.   if (DMACTL & 0x08)   /* Player DMA ? */
  371.     pm_dma += 4;
  372.  
  373. /* SingleLine DMACTL & 0x10 not covered here */
  374.  
  375.   return FALSE;
  376. }
  377.  
  378. int ANTIC_HSCROL_PUT(mtype byte)
  379. {
  380.   HSCROL = byte & 0x0f;
  381.   return FALSE;
  382. }
  383.  
  384. int ANTIC_NMIEN_PUT(mtype byte)
  385. {
  386.   NMIEN = byte | 0x1f;
  387.   /* printf("Wrote %d into NMIEN.\n",byte); */
  388.   return FALSE;
  389. }
  390.  
  391. int ANTIC_NMIRES_PUT(mtype byte)
  392. {
  393.   NMIST = 0x1f;
  394.   return FALSE;
  395. }
  396.  
  397. int ANTIC_PMBASE_PUT(mtype byte)
  398. {
  399. UWORD pmbase_s;
  400. UWORD pmbase_d;
  401.  
  402.   PMBASE = byte;
  403.  
  404.   pmbase_s = (PMBASE & 0xf8) << 8;
  405.   pmbase_d = (PMBASE & 0xfc) << 8;
  406.   
  407.   maddr_s = pmbase_s + 768;
  408.   p0addr_s = pmbase_s + 1024;
  409.   p1addr_s = pmbase_s + 1280;
  410.   p2addr_s = pmbase_s + 1536;
  411.   p3addr_s = pmbase_s + 1792;
  412.   
  413.   maddr_d = pmbase_d + 384;
  414.   p0addr_d = pmbase_d + 512;
  415.   p1addr_d = pmbase_d + 640;
  416.   p2addr_d = pmbase_d + 768;
  417.   p3addr_d = pmbase_d + 896;
  418.   
  419.   return FALSE;
  420. }
  421.  
  422. int ANTIC_VSCROL_PUT(mtype byte)
  423. {
  424.   VSCROL = byte & 0x0f;
  425.   return FALSE;
  426. }
  427.  
  428. int ANTIC_WSYNC_PUT(mtype byte)
  429. {
  430.   wsync_halt ++;
  431.   return TRUE;
  432. }
  433.  
  434. void Init_Antic (int *argc, char *argv[],int base)
  435. {
  436. int i;
  437. int j;
  438.  
  439.   if (argc) {
  440.     for (i=j=1;i<*argc;i++)
  441.       {
  442.     if (strcmp(argv[i],"-xcolpf1") == 0)
  443.       enable_xcolpf1 = TRUE;
  444.     else
  445.       argv[j++] = argv[i];
  446.       }
  447.     
  448.     *argc = j;
  449.   }  
  450.  
  451.   NMIEN = 0x1f;
  452.   NMIST = 0x00;
  453.   DMACTL = 0x00;
  454.   VSCROL = 0x00;
  455.   HSCROL = 0x00;
  456.  
  457. /* setup lookup tables */
  458.  
  459.   memset(lookup_f,0,256*sizeof(int));
  460.   memset(lookup_4,0,256*sizeof(int));
  461.   memset(lookup24,0,256*sizeof(int));
  462.   memset(lookup_9,0,256*sizeof(int));
  463.  
  464.   lookup_f[0x00]=PF_COLPF2;
  465.   lookup_f[0x80]=lookup_f[0x40]=lookup_f[0x20]=
  466.   lookup_f[0x10]=lookup_f[0x08]=lookup_f[0x04]=
  467.   lookup_f[0x02]=lookup_f[0x01]=PF_COLPF1_FID;
  468.  
  469.   lookup_4[0x00]=PF4_COLBK;
  470.   lookup_4[0x40]=lookup_4[0x10]=lookup_4[0x04]=lookup_4[0x01]=PF4_COLPF0;
  471.   lookup_4[0x80]=lookup_4[0x20]=lookup_4[0x08]=lookup_4[0x02]=PF4_COLPF1;
  472.   lookup_4[0xc0]=lookup_4[0x30]=lookup_4[0x0c]=lookup_4[0x03]=PF4_COLPF2;
  473.  
  474.   lookup24[0x00]=PF2_COLBK;
  475.   lookup24[0x40]=lookup24[0x10]=lookup24[0x04]=lookup24[0x01]=PF2_COLPF0;
  476.   lookup24[0x80]=lookup24[0x20]=lookup24[0x08]=lookup24[0x02]=PF2_COLPF1;
  477.   lookup24[0xc0]=lookup24[0x30]=lookup24[0x0c]=lookup24[0x03]=PF2_COLPF3;
  478.  
  479.   lookup_9[0x00]=PF4_COLBK;
  480.   lookup_9[0x80]=lookup_9[0x40]=lookup_9[0x20]=lookup_9[0x10]=
  481.   lookup_9[0x08]=lookup_9[0x04]=lookup_9[0x02]=lookup_9[0x01]=PF4_COLPF0;
  482.  
  483.   memset(lookup_6+0x00,PF2_COLPF0,0x40*sizeof(int));
  484.   memset(lookup_6+0x40,PF2_COLPF1,0x40*sizeof(int));
  485.   memset(lookup_6+0x80,PF2_COLPF2,0x40*sizeof(int));
  486.   memset(lookup_6+0xc0,PF2_COLPF3,0x40*sizeof(int));
  487.  
  488.   SetHW(base+_DMACTL,0xff0f,&ANTIC_DMACTL_GET,&ANTIC_DMACTL_PUT);
  489.   SetHW(base+_CHACTL,0xff0f,&ANTIC_CHACTL_GET,&ANTIC_CHACTL_PUT);
  490.   SetHW(base+_DLISTL,0xff0f,&ANTIC_DLISTL_GET,&ANTIC_DLISTL_PUT);
  491.   SetHW(base+_DLISTH,0xff0f,&ANTIC_DLISTH_GET,&ANTIC_DLISTH_PUT);
  492.   SetHW(base+_HSCROL,0xff0f,NULL,&ANTIC_HSCROL_PUT);
  493.   SetHW(base+_VSCROL,0xff0f,NULL,&ANTIC_VSCROL_PUT);
  494.   SetHW(base+_PMBASE,0xff0f,NULL,&ANTIC_PMBASE_PUT);
  495.   SetHW(base+_CHBASE,0xff0f,&ANTIC_CHBASE_GET,&ANTIC_CHBASE_PUT);
  496.   SetHW(base+_VCOUNT,0xff0f,&ANTIC_VCOUNT_GET,NULL);
  497.   SetHW(base+_NMIEN,0xff0f,&ANTIC_NMIEN_GET,&ANTIC_NMIEN_PUT);
  498.   SetHW(base+_NMIRES,0xff0f,&ANTIC_NMIST_GET,&ANTIC_NMIRES_PUT);
  499.   SetHW(base+_WSYNC,0xff0f,&ANTIC_WSYNC_GET,&ANTIC_WSYNC_PUT);
  500. }
  501.  
  502. /********************************************************************
  503.  ** Antic Mode line generators                                     **
  504.  **                                                                **
  505.  ** These functions come in pairs. One is used to fill the antic   **
  506.  ** scan line buffer scanbuf[] and is called once for each mode    **
  507.  ** line. It returns a function pointer for the second function    **
  508.  ** of the pair, used to build the actual scan lines. They take an **
  509.  ** integer as argument that defines which scan line of the mode   **
  510.  ** line should be build - as needed by vertical scrolling.        **
  511.  ** Horizontal scrolling, however, is done elsewhere, in the GTIA  **
  512.  ** buffer. That looks rather wierd, but allows optimized          **
  513.  ** long accesses here.                                            **
  514.  ********************************************************************/
  515.  
  516. /*
  517.  * Builder pair for blank lines 
  518.  */
  519.  
  520. void Build_Blank(UBYTE *fillin,int width,int scanline)
  521. {
  522.   memset(fillin,PF_COLBK,width);
  523. }
  524.  
  525. ModeFunc *Antic_Blank(void)
  526. {
  527.   return &Build_Blank;
  528. }
  529.  
  530. /*
  531.  * Builder pair for Antic_2 
  532.  */
  533.  
  534. void Build_Antic_2(UBYTE *ptr,int width,int scanline)
  535. {
  536.   int chaddr;
  537.   int i;
  538.   int nchars = width >> 3;
  539.   int *scan=scanbuf;
  540.   int screendata;
  541.   int chbase;
  542.   int chdata;
  543.  
  544.   chbase = chbase_40 + char_offset + scanline*char_delta;
  545.  
  546.   for (i=0;i<nchars;i++,scan++) {  
  547.  
  548.     /* get character data */
  549.     screendata = *scan;  
  550.  
  551.     /* get character base address */
  552.     chaddr = chbase + ((screendata & 0x7f) << 3);  
  553.  
  554.     /* get character data */
  555.     chdata = APeek(chaddr);
  556.  
  557.     if (screendata & invert_mask)
  558.       chdata ^= 0xff;
  559.  
  560.     if (screendata & blank_mask)
  561.       chdata = 0;
  562.  
  563.     if (chdata) {
  564.       *ptr++ = lookup_f[chdata & 0x80];
  565.       *ptr++ = lookup_f[chdata & 0x40];
  566.       *ptr++ = lookup_f[chdata & 0x20];
  567.       *ptr++ = lookup_f[chdata & 0x10];
  568.       *ptr++ = lookup_f[chdata & 0x08];
  569.       *ptr++ = lookup_f[chdata & 0x04];
  570.       *ptr++ = lookup_f[chdata & 0x02];
  571.       *ptr++ = lookup_f[chdata & 0x01];
  572.     } else {
  573.       /* Since HSCROLL is always done in the GTIA module, this is aligned ! */
  574.       ULONG *l_ptr = (ULONG*)ptr;
  575.       
  576.       *l_ptr++ = PF4_COLPF2;
  577.       *l_ptr++ = PF4_COLPF2;
  578.       
  579.       ptr = (UBYTE*)l_ptr;
  580.     }
  581.   }
  582. }
  583.  
  584. ModeFunc *Antic_2(int width)
  585. {
  586. int i;
  587. int *scan=scanbuf;
  588. int nchars = width >> 3;
  589.  
  590.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  591.      *scan=APeek(screenaddr);
  592.  
  593.    return &Build_Antic_2;
  594. }
  595.  
  596. /*
  597.  * Builder pair for Antic 3
  598.  */
  599.  
  600. void Build_Antic_3(UBYTE *ptr,int width,int scanline)
  601. {
  602.   int chaddr;
  603.   int i;
  604.   int nchars = width >> 3;
  605.   int *scan=scanbuf;
  606.   int screendata;
  607.   int chdata=0;
  608.  
  609.   for (i=0;i<nchars;i++,scan++) {  
  610.  
  611.     /* get character data */
  612.     screendata = *scan;  
  613.     
  614.     if ((screendata & 0x60) == 0x60) {
  615.       /* This is a lowercase character. This means that the first two
  616.      scan lines are blank and get mirrored as the last two scan lines */
  617.       switch(scanline) {
  618.       case 0:
  619.       case 1:
  620.     chdata = 0;
  621.     break;
  622.       case 2:
  623.       case 3:
  624.       case 4:
  625.       case 5:
  626.       case 6:
  627.       case 7:
  628.     chaddr = chbase_40 + char_offset + scanline*char_delta;
  629.     chdata = APeek(chaddr);
  630.     break;
  631.       case 8:
  632.     chaddr = chbase_40 + char_offset;
  633.     chdata = APeek(chaddr);
  634.     break;
  635.       case 9:
  636.     chaddr = chbase_40 + char_offset + char_delta;
  637.     chdata = APeek(chaddr);
  638.     break;
  639.       }
  640.     } else {
  641.       /* Uppercase character. We use the standard orientation and keep the
  642.      last two scan lines blank */
  643.       if (scanline<8) {
  644.     chaddr = chbase_40 + char_offset + char_delta * scanline;
  645.     chdata = APeek(chaddr);
  646.       } else {
  647.     chdata = 0;
  648.       }
  649.     }
  650.  
  651.     if (screendata & invert_mask)
  652.       chdata ^= 0xff;
  653.  
  654.     if (screendata & blank_mask)
  655.       chdata = 0;
  656.  
  657.     if (chdata) {
  658.       *ptr++ = lookup_f[chdata & 0x80];
  659.       *ptr++ = lookup_f[chdata & 0x40];
  660.       *ptr++ = lookup_f[chdata & 0x20];
  661.       *ptr++ = lookup_f[chdata & 0x10];
  662.       *ptr++ = lookup_f[chdata & 0x08];
  663.       *ptr++ = lookup_f[chdata & 0x04];
  664.       *ptr++ = lookup_f[chdata & 0x02];
  665.       *ptr++ = lookup_f[chdata & 0x01];
  666.     } else {
  667.       /* Since HSCROLL is always done in the GTIA module, this is aligned ! */
  668.       ULONG *l_ptr = (ULONG*)ptr;
  669.       
  670.       *l_ptr++ = PF4_COLPF2;
  671.       *l_ptr++ = PF4_COLPF2;
  672.       
  673.       ptr = (UBYTE*)l_ptr;
  674.     }
  675.   }
  676. }
  677.  
  678. ModeFunc *Antic_3(int width)
  679. {
  680. int i;
  681. int *scan=scanbuf;
  682. int nchars = width >> 3;
  683.  
  684.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  685.      *scan=APeek(screenaddr);
  686.  
  687.    return &Build_Antic_3;
  688. }
  689.  
  690.  
  691. /*
  692.  * Display Builders for Antic Mode 4
  693.  */
  694.  
  695. void Build_Antic_4(UBYTE *b_ptr,int width,int scanline)
  696. {
  697.   int chaddr;
  698.   int i;
  699.   int nchars = width >> 3;
  700.   int *scan=scanbuf;
  701.   int screendata;
  702.   int chbase;
  703.   int chdata;
  704.   int *lookup;
  705.   UWORD *ptr=(UWORD *)b_ptr;
  706.  
  707.   chbase = chbase_40 + char_offset + scanline*char_delta;
  708.  
  709.   for (i=0;i<nchars;i++,scan++) {  
  710.  
  711.     /* get character data */
  712.     screendata = *scan;  
  713.  
  714.     /* get character base address */
  715.     chaddr = chbase + ((screendata & 0x7f) << 3);  
  716.  
  717.     /* get character data */
  718.     chdata = APeek(chaddr);
  719.     
  720.     if (screendata & 0x80)
  721.       lookup = lookup24;
  722.     else
  723.       lookup = lookup_4;
  724.  
  725.     if (chdata) {
  726.       *ptr++ = lookup[chdata & 0xc0];
  727.       *ptr++ = lookup[chdata & 0x30];
  728.       *ptr++ = lookup[chdata & 0x0c];
  729.       *ptr++ = lookup[chdata & 0x03];
  730.     } else {
  731.       *ptr++ = PF2_COLBK;
  732.       *ptr++ = PF2_COLBK;
  733.       *ptr++ = PF2_COLBK;
  734.       *ptr++ = PF2_COLBK;
  735.     }  
  736.   }
  737. }
  738.  
  739. ModeFunc *Antic_4(int width)
  740. {
  741. int i;
  742. int *scan=scanbuf;
  743. int nchars = width >> 3;
  744.  
  745.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  746.      *scan=APeek(screenaddr);
  747.  
  748.    return &Build_Antic_4;
  749. }
  750.  
  751. /*
  752.  * Builder Pair for Antic Mode 5
  753.  */
  754.  
  755. void Build_Antic_5(UBYTE *b_ptr,int width,int scanline)
  756. {
  757.   int chaddr;
  758.   int i;
  759.   int nchars = width >> 3;
  760.   int *scan=scanbuf;
  761.   int screendata;
  762.   int chbase;
  763.   int chdata;
  764.   int *lookup;
  765.   UWORD *ptr=(UWORD *)b_ptr;
  766.  
  767.   chbase = chbase_40 + char_offset + (scanline>>1)*char_delta;
  768.  
  769.   for (i=0;i<nchars;i++,scan++) {  
  770.  
  771.     /* get character data */
  772.     screendata = *scan;  
  773.  
  774.     /* get character base address */
  775.     chaddr = chbase + ((screendata & 0x7f) << 3);  
  776.  
  777.     /* get character data */
  778.     chdata = APeek(chaddr);
  779.     
  780.     if (screendata & 0x80)
  781.       lookup = lookup24;
  782.     else
  783.       lookup = lookup_4;
  784.  
  785.     if (chdata) {
  786.       *ptr++ = lookup[chdata & 0xc0];
  787.       *ptr++ = lookup[chdata & 0x30];
  788.       *ptr++ = lookup[chdata & 0x0c];
  789.       *ptr++ = lookup[chdata & 0x03];
  790.     } else {
  791.       *ptr++ = PF2_COLBK;
  792.       *ptr++ = PF2_COLBK;
  793.       *ptr++ = PF2_COLBK;
  794.       *ptr++ = PF2_COLBK;
  795.     }  
  796.   }
  797. }
  798.  
  799. ModeFunc *Antic_5(int width)
  800. {
  801. int i;
  802. int *scan=scanbuf;
  803. int nchars = width >> 3;
  804.  
  805.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  806.      *scan=APeek(screenaddr);
  807.  
  808.    return &Build_Antic_5;
  809. }
  810.  
  811.  
  812. /*
  813.  * Display Pair for Antic Mode 6
  814.  */
  815.  
  816. void Build_Antic_6(UBYTE *b_ptr,int width,int scanline)
  817. {
  818.   int chaddr;
  819.   int i;
  820.   int nchars = width >> 4;
  821.   int *scan=scanbuf;
  822.   int screendata;
  823.   int chbase;
  824.   int chdata;
  825.   int color;
  826.   UWORD *ptr=(UWORD *)b_ptr;
  827.  
  828.   chbase = chbase_20 + char_offset + scanline*char_delta;
  829.  
  830.   for (i=0;i<nchars;i++,scan++) {  
  831.  
  832.     /* get character data */
  833.     screendata = *scan;  
  834.  
  835.     /* get character base address */
  836.     chaddr = chbase + ((screendata & 0x3f) << 3);
  837.  
  838.     /* get character cell color */
  839.     color = lookup_6[screendata];
  840.    
  841.     /* get character data */
  842.     chdata = APeek(chaddr);
  843.     
  844.     if (chdata) {
  845.       *ptr++ = (chdata & 0x80)?(color):(PF2_COLBK);
  846.       *ptr++ = (chdata & 0x40)?(color):(PF2_COLBK);
  847.       *ptr++ = (chdata & 0x20)?(color):(PF2_COLBK);
  848.       *ptr++ = (chdata & 0x10)?(color):(PF2_COLBK);
  849.       *ptr++ = (chdata & 0x08)?(color):(PF2_COLBK);
  850.       *ptr++ = (chdata & 0x04)?(color):(PF2_COLBK);
  851.       *ptr++ = (chdata & 0x02)?(color):(PF2_COLBK);
  852.       *ptr++ = (chdata & 0x01)?(color):(PF2_COLBK);
  853.     } else {
  854.       /* Since HSCROLL is always done in the GTIA module, this is aligned ! */
  855.       ULONG *l_ptr = (ULONG*)ptr;
  856.       
  857.       *l_ptr++ = PF4_COLBK;
  858.       *l_ptr++ = PF4_COLBK;
  859.       *l_ptr++ = PF4_COLBK;
  860.       *l_ptr++ = PF4_COLBK;
  861.       
  862.       ptr = (UWORD*)l_ptr;      
  863.     }
  864.   }
  865. }
  866.  
  867. ModeFunc *Antic_6(int width)
  868. {
  869. int i;
  870. int *scan=scanbuf;
  871. int nchars = width >> 4;
  872.  
  873.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  874.      *scan=APeek(screenaddr);
  875.  
  876.    return &Build_Antic_6;
  877. }
  878.  
  879. /*
  880.  * Display Pair for Antic Mode 7
  881.  */
  882. void Build_Antic_7(UBYTE *b_ptr,int width,int scanline)
  883. {
  884.   int chaddr;
  885.   int i;
  886.   int nchars = width >> 4;
  887.   int *scan=scanbuf;
  888.   int screendata;
  889.   int chbase;
  890.   int chdata;
  891.   int color;
  892.   UWORD *ptr=(UWORD *)b_ptr;
  893.  
  894.   chbase = chbase_20 + char_offset + (scanline>>1)*char_delta;
  895.  
  896.   for (i=0;i<nchars;i++,scan++) {  
  897.  
  898.     /* get character data */
  899.     screendata = *scan;  
  900.  
  901.     /* get character base address */
  902.     chaddr = chbase + ((screendata & 0x3f) << 3);
  903.  
  904.     /* get character cell color */
  905.     color = lookup_6[screendata];
  906.    
  907.     /* get character data */
  908.     chdata = APeek(chaddr);
  909.     
  910.     if (chdata) {
  911.       *ptr++ = (chdata & 0x80)?(color):(PF2_COLBK);
  912.       *ptr++ = (chdata & 0x40)?(color):(PF2_COLBK);
  913.       *ptr++ = (chdata & 0x20)?(color):(PF2_COLBK);
  914.       *ptr++ = (chdata & 0x10)?(color):(PF2_COLBK);
  915.       *ptr++ = (chdata & 0x08)?(color):(PF2_COLBK);
  916.       *ptr++ = (chdata & 0x04)?(color):(PF2_COLBK);
  917.       *ptr++ = (chdata & 0x02)?(color):(PF2_COLBK);
  918.       *ptr++ = (chdata & 0x01)?(color):(PF2_COLBK);
  919.     } else {
  920.       /* Since HSCROLL is always done in the GTIA module, this is aligned ! */
  921.       ULONG *l_ptr = (ULONG*)ptr;
  922.       
  923.       *l_ptr++ = PF4_COLBK;
  924.       *l_ptr++ = PF4_COLBK;
  925.       *l_ptr++ = PF4_COLBK;
  926.       *l_ptr++ = PF4_COLBK;
  927.       
  928.       ptr = (UWORD*)l_ptr;      
  929.     }
  930.   }
  931. }
  932.  
  933. ModeFunc *Antic_7(int width)
  934. {
  935. int i;
  936. int *scan=scanbuf;
  937. int nchars = width >> 4;
  938.  
  939.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  940.      *scan=APeek(screenaddr);
  941.  
  942.    return &Build_Antic_7;
  943. }
  944.  
  945. /*
  946.  * Function to Display Antic Mode 8
  947.  */
  948.  
  949. void Build_Antic_8(UBYTE *ptr,int width,int scanline)
  950. {
  951.   int i;
  952.   int nchars = width >> 5;
  953.   int *scan = scanbuf;
  954.   int screendata;
  955.  
  956.   for(i=0;i<nchars;i++,scan++) {
  957.  
  958.     screendata = *scan;
  959.   
  960.     memset(ptr,lookup_4[screendata & 0xc0],8);
  961.     ptr += 8;
  962.     memset(ptr,lookup_4[screendata & 0x30],8);
  963.     ptr += 8;
  964.     memset(ptr,lookup_4[screendata & 0x0c],8);
  965.     ptr += 8;
  966.     memset(ptr,lookup_4[screendata & 0x03],8);
  967.     ptr += 8;
  968.   }
  969. }
  970.  
  971. ModeFunc *Antic_8(int width)
  972. {
  973. int i;
  974. int *scan=scanbuf;
  975. int nchars = width >> 5;
  976.  
  977.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  978.      *scan=APeek(screenaddr);
  979.  
  980.    return &Build_Antic_8;
  981. }
  982.  
  983. /*
  984.  * Display pair for Antic Mode 9
  985.  */
  986.  
  987. void Build_Antic_9(UBYTE *b_ptr,int width,int scanline)
  988. {
  989.   int i;
  990.   int nchars = width >> 5;
  991.   int *scan = scanbuf;
  992.   int screendata;
  993.   ULONG *ptr = (ULONG *)(b_ptr);
  994.  
  995.   for(i=0;i<nchars;i++,scan++) {
  996.  
  997.     screendata = *scan;
  998.  
  999.     *ptr++=lookup_9[screendata & 0x80];
  1000.     *ptr++=lookup_9[screendata & 0x40];
  1001.     *ptr++=lookup_9[screendata & 0x20];
  1002.     *ptr++=lookup_9[screendata & 0x10];
  1003.     *ptr++=lookup_9[screendata & 0x08];
  1004.     *ptr++=lookup_9[screendata & 0x04];
  1005.     *ptr++=lookup_9[screendata & 0x02];
  1006.     *ptr++=lookup_9[screendata & 0x01];
  1007.   }
  1008. }
  1009.  
  1010. ModeFunc *Antic_9(int width)
  1011. {
  1012. int i;
  1013. int *scan=scanbuf;
  1014. int nchars = width >> 5;
  1015.  
  1016.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1017.      *scan=APeek(screenaddr);
  1018.  
  1019.    return &Build_Antic_9;
  1020. }
  1021.  
  1022. /*
  1023.  * Function to Display Antic Mode a
  1024.  */
  1025.  
  1026. void Build_Antic_A(UBYTE *b_ptr,int width,int scanline)
  1027. {
  1028.   int i;
  1029.   int nchars = width >> 4;
  1030.   int *scan = scanbuf;
  1031.   int screendata;
  1032.   ULONG *ptr=(ULONG *)b_ptr;
  1033.  
  1034.   for(i=0;i<nchars;i++,scan++) {
  1035.  
  1036.     screendata = *scan;
  1037.     
  1038.     *ptr++=lookup_4[screendata & 0xc0];
  1039.     *ptr++=lookup_4[screendata & 0x30];
  1040.     *ptr++=lookup_4[screendata & 0x0c];
  1041.     *ptr++=lookup_4[screendata & 0x03];
  1042.   }
  1043. }
  1044.  
  1045. ModeFunc *Antic_A(int width)
  1046. {
  1047. int i;
  1048. int *scan=scanbuf;
  1049. int nchars = width >> 4;
  1050.  
  1051.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1052.      *scan=APeek(screenaddr);
  1053.  
  1054.    return &Build_Antic_A;
  1055. }
  1056.  
  1057.  
  1058. /*
  1059.  * Function to Display Antic Mode b
  1060.  */
  1061.  
  1062. void Build_Antic_B(UBYTE *b_ptr,int width,int scanline)
  1063. {
  1064.   int i;
  1065.   int nchars = width >> 4;
  1066.   int *scan = scanbuf;
  1067.   int screendata;
  1068.   UWORD *ptr = (UWORD *)(b_ptr);
  1069.  
  1070.   for(i=0;i<nchars;i++,scan++) {
  1071.  
  1072.     screendata = *scan;
  1073.  
  1074.     *ptr++=lookup_9[screendata & 0x80];
  1075.     *ptr++=lookup_9[screendata & 0x40];
  1076.     *ptr++=lookup_9[screendata & 0x20];
  1077.     *ptr++=lookup_9[screendata & 0x10];
  1078.     *ptr++=lookup_9[screendata & 0x08];
  1079.     *ptr++=lookup_9[screendata & 0x04];
  1080.     *ptr++=lookup_9[screendata & 0x02];
  1081.     *ptr++=lookup_9[screendata & 0x01];
  1082.   }
  1083. }
  1084.  
  1085. ModeFunc *Antic_B(int width)
  1086. {
  1087. int i;
  1088. int *scan=scanbuf;
  1089. int nchars = width >> 4;
  1090.  
  1091.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1092.      *scan=APeek(screenaddr);
  1093.  
  1094.    return &Build_Antic_B;
  1095. }
  1096.  
  1097. /*
  1098.  * Function to Display Antic Mode c
  1099.  */
  1100.  
  1101. ModeFunc *Antic_C(int width)
  1102. {
  1103. int i;
  1104. int *scan=scanbuf;
  1105. int nchars = width >> 4;
  1106.  
  1107.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1108.      *scan=APeek(screenaddr);
  1109.  
  1110.    return &Build_Antic_B;   
  1111.    /* The scan lines of modes C & B look identically */
  1112. }
  1113.  
  1114.  
  1115. /*
  1116.  * Function to Display Antic Mode d
  1117.  */
  1118.  
  1119. void Build_Antic_D(UBYTE *b_ptr,int width,int scanline)
  1120. {
  1121.   int i;
  1122.   int nchars = width >> 3;
  1123.   int *scan = scanbuf;
  1124.   int screendata;
  1125.   UWORD *ptr=(UWORD *)b_ptr;
  1126.  
  1127.   for(i=0;i<nchars;i++,scan++) {
  1128.  
  1129.     screendata = *scan;
  1130.     
  1131.     *ptr++=lookup_4[screendata & 0xc0];
  1132.     *ptr++=lookup_4[screendata & 0x30];
  1133.     *ptr++=lookup_4[screendata & 0x0c];
  1134.     *ptr++=lookup_4[screendata & 0x03];
  1135.  
  1136.   }
  1137. }
  1138.  
  1139. ModeFunc *Antic_D(int width)
  1140. {
  1141. int i;
  1142. int *scan=scanbuf;
  1143. int nchars = width >> 3;
  1144.  
  1145.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1146.      *scan=APeek(screenaddr);
  1147.  
  1148.    return &Build_Antic_D;
  1149. }
  1150.  
  1151. /*
  1152.  * Function to display Antic Mode e
  1153.  */
  1154.  
  1155. ModeFunc *Antic_E(int width)
  1156. {
  1157. int i;
  1158. int *scan=scanbuf;
  1159. int nchars = width >> 3;
  1160.  
  1161.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1162.      *scan=APeek(screenaddr);
  1163.  
  1164.    return &Build_Antic_D;
  1165.   /* The mode lines of modes E & D look alike */
  1166. }
  1167.  
  1168. /*
  1169.  * Function to display Antic Mode f
  1170.  */
  1171.  
  1172. void Build_Antic_F(UBYTE *ptr,int width,int scanline)
  1173. {
  1174.   int i;
  1175.   int nchars = width >> 3;
  1176.   int *scan = scanbuf;
  1177.   int screendata;
  1178.  
  1179.   for(i=0;i<nchars;i++,scan++) {
  1180.  
  1181.     screendata = *scan;
  1182.  
  1183.     *ptr++=lookup_f[screendata & 0x80];
  1184.     *ptr++=lookup_f[screendata & 0x40];
  1185.     *ptr++=lookup_f[screendata & 0x20];
  1186.     *ptr++=lookup_f[screendata & 0x10];
  1187.     *ptr++=lookup_f[screendata & 0x08];
  1188.     *ptr++=lookup_f[screendata & 0x04];
  1189.     *ptr++=lookup_f[screendata & 0x02];
  1190.     *ptr++=lookup_f[screendata & 0x01];
  1191.   }
  1192. }
  1193.  
  1194. ModeFunc *Antic_F(int width)
  1195. {
  1196. int i;
  1197. int *scan=scanbuf;
  1198. int nchars = width >> 3;
  1199.  
  1200.    for(i=0;i<nchars;i++,scan++,screenaddr++)
  1201.      *scan=APeek(screenaddr);
  1202.  
  1203.    return &Build_Antic_F;
  1204. }
  1205.  
  1206.  
  1207. /*
  1208.     *****************************************************************
  1209.     *                                *
  1210.     *    Section            :    Display List        *
  1211.     *    Original Author        :    David Firth        *
  1212.     *    Date Written        :    28th May 1995        *
  1213.     *    Version            :    1.0            *
  1214.     *                                *
  1215.     *   Description                            *
  1216.     *   -----------                            *
  1217.     *                                *
  1218.     *   Section that handles Antic Display List. Not required for    *
  1219.     *   BASIC version.                        *
  1220.     *                                                               *
  1221.     *****************************************************************
  1222. */
  1223.  
  1224. void pmg_dma (void)
  1225. {
  1226. int yhalf = ypos >> 1;
  1227. /* single line shift not yet implemented.... */
  1228.  
  1229.   if (DMACTL & 0x08)
  1230.     {
  1231.       if (DMACTL & 0x10)
  1232.     {
  1233.       GRAFP0 = memory[p0addr_s + ypos];
  1234.       GRAFP1 = memory[p1addr_s + ypos];
  1235.       GRAFP2 = memory[p2addr_s + ypos];
  1236.       GRAFP3 = memory[p3addr_s + ypos];
  1237.     }
  1238.       else
  1239.     {
  1240.       GRAFP0 = memory[p0addr_d + yhalf - delayp0];
  1241.       GRAFP1 = memory[p1addr_d + yhalf - delayp1];
  1242.       GRAFP2 = memory[p2addr_d + yhalf - delayp2];
  1243.       GRAFP3 = memory[p3addr_d + yhalf - delayp3];
  1244.     }
  1245.     }
  1246.  
  1247.   if (DMACTL & 0x0C)   /* Player DMA enables missile DMA as well */
  1248.     {
  1249.       if (DMACTL & 0x10)
  1250.     GRAFM = memory[maddr_s + ypos];
  1251.       else {
  1252.     int mis0,mis1,mis2,mis3;
  1253.     
  1254.     mis0 =  memory[maddr_d + yhalf - delaym0];
  1255.     mis1 =  memory[maddr_d + yhalf - delaym1];
  1256.     mis2 =  memory[maddr_d + yhalf - delaym2];
  1257.     mis3 =  memory[maddr_d + yhalf - delaym3];
  1258.  
  1259.     GRAFM = (mis0 & 0x03) | (mis1 & 0x0c) | (mis2 & 0x30) | (mis3 & 0xc0);
  1260.       }
  1261.     }
  1262. }
  1263.  
  1264. static void Clear_Border(int hscrol)
  1265. {
  1266. int scrol=HSCROL+HSCROL;
  1267. int shift=FILLIN_OFFSET;
  1268. int left=FILLIN_OFFSET+dmactl_xmin_noscroll;
  1269.   
  1270.   if (hscrol) {
  1271.     shift -= scrol;
  1272.     if ((DMACTL & 0x03)!=0x03)
  1273.       left -= scrol;
  1274.   }
  1275.  
  1276.   memset(scrn_ptr,PF_COLBK,left);
  1277.   memset(scrn_ptr+dmactl_xmax_noscroll+shift,PF_COLBK,
  1278.        ATARI_MODULO-dmactl_xmax_noscroll-shift);
  1279. }
  1280.  
  1281. static void ANTIC_Scanline(int dmacycles,int nmi,int hscrol,ModeFunc *gen,UBYTE *fillin,int width,int displayline)
  1282. {
  1283. int before;
  1284. int after;
  1285. int add;
  1286.  
  1287. #ifdef DEBUG
  1288.   hpos=H_BEFORE_DMA;
  1289. #endif
  1290.   before=cc_middle-before_dma-dmacycles;
  1291.   after=114-cc_middle-after_wsync;
  1292.   if (before<0) {
  1293.     after += before;
  1294.     before = 0;
  1295.   }
  1296.   add = carry;
  1297.   Clear_Border(hscrol);
  1298.   if (!wsync_halt) {
  1299.     if (before_dma>0)
  1300.       add = GO(before_dma+add);
  1301. #ifdef DEBUG
  1302.     hpos=H_FIRST_HALF;
  1303. #endif
  1304.     if (nmi) {
  1305.       before += add;
  1306.       before -= dli_delay;
  1307.       if (before>0) {
  1308.     NMI();
  1309.     nmi = FALSE;
  1310.     add = GO(before);
  1311.       }
  1312.     } else {
  1313.       before += add;
  1314.       if (before>0)
  1315.     add = GO(before);
  1316.     }
  1317.   }
  1318.   /* generate the display */
  1319.   (*gen)(fillin,width,displayline);
  1320.   pmg_dma ();
  1321.   Atari_ScanLine (hscrol); 
  1322. #ifdef DEBUG
  1323.   hpos=H_SECOND_HALF;
  1324.   if (nmi) {
  1325.     dlipos=ypos;
  1326.     dline=displayline;
  1327.   }
  1328. #endif
  1329.   if (!wsync_halt) {
  1330.     if (nmi) {
  1331.       after += add;
  1332.       after -= dli_delay;
  1333.       if (after>0) {
  1334.     NMI();
  1335.     nmi = FALSE;
  1336.     add = GO(after);
  1337.       }
  1338.     } else {
  1339.       after += add;
  1340.       if (after>0)
  1341.     add = GO(after);
  1342.     }
  1343.   }
  1344. #ifdef DEBUG
  1345.   hpos=H_AFTER_WSYNC;
  1346. #endif
  1347.   wsync_halt=0;
  1348.   if (nmi) {
  1349.     NMI();
  1350.     add = GO(after_wsync-dli_delay+add);
  1351.   } else add = GO(after_wsync+add);
  1352.   carry = add;
  1353.  
  1354.   scrn_ptr += ATARI_MODULO;
  1355.   ypos++;
  1356.  
  1357. }
  1358.  
  1359.  
  1360. /* Generate one mode line of the ANTIC display.
  1361.    IR is the instruction code and only needed for horizontal/vertical scrolling
  1362.    and NMI generation. No jump codes are generated here. 
  1363.    first is the first scan line of the mode line to be generated. It may be
  1364.    negative for artefacts. The first scan line is then generated over again
  1365.    until the counter gets zero. 
  1366.    nlines is the number of scan lines in this mode line.
  1367.    last is the number of the last scan line to be generated. It may be larger
  1368.    than nlines. In this case, the last scan line is repeated over again to
  1369.    generate VSCROLL artefacts.
  1370.    acnt is the # of stealed DMA cycles for each scan line of the mode line
  1371.    acntn is the # of additional DMA cycles for the first scan line.
  1372.    ModeFunc * is the scan line generator function. It's called with the
  1373.    *fillin pointer, so to know where to place the graphics, the width
  1374.    of the scan line in half color clocks and the scan line of the mode line
  1375.    to be generated. */
  1376.    
  1377. static void Antic_Modeline(int IR,int first,int last,int nlines,int dmashift,int dmaadd,ModeFunc *gen)
  1378. {
  1379. int width;
  1380. int scanline;
  1381. int displayline;
  1382. int dmawidth;
  1383. UBYTE *fillin;
  1384. int dma;
  1385. int nmi=FALSE;
  1386.  
  1387.     nlines--;   /* for simpler calculations */
  1388.     for (scanline=first;scanline<=last;scanline++) {
  1389.       /* get the line to be displayed. */
  1390.       displayline=scanline;
  1391.       if (displayline<0)
  1392.     displayline = 0;
  1393.       if (displayline>nlines)
  1394.     displayline=nlines;
  1395.  
  1396. /* Get the width of the line. Must be taken from DMACTL right now because
  1397.    the CPU may change it within the mode line */
  1398.  
  1399.       dmawidth = DMAwidth;   /* DMA base cycle counter */
  1400.       width = dmawidth<<6;   /* # of color clocks */
  1401.       fillin = scrn_ptr+dmactl_xmin_noscroll+FILLIN_OFFSET;  /* graphics fill-in position */
  1402.  
  1403. /* All that changes a lot if HSCROL is turned on. Get the next wider display */
  1404.  
  1405.       if (IR & 0x10) {
  1406.     fillin = scrn_ptr+dmactl_xmin_scroll+FILLIN_OFFSET;
  1407.     if (dmawidth<6) {
  1408.       dmawidth++;
  1409.       width += 64;
  1410.       dmaadd--;   /* one memory refresh cycle is dropped */
  1411.     }
  1412.       }
  1413.  
  1414. /* get the number of DMA cycles needed to display that mode */
  1415.  
  1416.       /* base cycles for DISPLAY DMA, used for character based DMA */
  1417.       if (dmashift)
  1418.     dma = dmawidth << dmashift;
  1419.       else dma = 0;
  1420.     
  1421.       /* add the memory refresh cycles */
  1422.       dma += 9;
  1423.  
  1424.       if ((DMACTL & 0x10) || (ypos & 0x01)==0)
  1425.     dma += pm_dma;   /* turn on player DMA? */
  1426.       
  1427.       if (scanline==first)
  1428.     dma += dmaadd;   /* add the DMA cycles to get this mode line IR */
  1429.     
  1430.       /* keep track of the DLI if turned on */
  1431.       if ((scanline == last) && (IR & 0x80)) {
  1432.     if (NMIEN & 0x80) {
  1433.       NMIST = 0x80;
  1434.       nmi = TRUE;
  1435.     }
  1436.       }
  1437.  
  1438.       /* run the scancode */
  1439.       ANTIC_Scanline(dma,nmi,IR & 0x10,gen,fillin,width,displayline);
  1440.     }
  1441. }
  1442.  
  1443. void ANTIC_RunDisplayList (void)
  1444. {
  1445.   int JVB=FALSE;
  1446.   int nlines=0;
  1447.   int width;
  1448.   int IR;
  1449.   int dmabase;
  1450.   int dmawidth;
  1451.   int dmashift;
  1452.   int vertthis,vertlast;
  1453.   ModeFunc *gen;  /* scanline generator. Requires fill-in position,
  1454.              width in half color clocks and scan line within
  1455.              the mode line to be build */
  1456.  
  1457.   wsync_halt = 0;
  1458.   vertthis=FALSE;
  1459.   vertlast=FALSE;
  1460.   gen = NULL;
  1461.  
  1462.   /*
  1463.    * VCOUNT must equal zero for some games but the first line starts
  1464.    * when VCOUNT=4. This portion processes when VCOUNT=0, 1, 2 and 3
  1465.    */
  1466.  
  1467.   scrn_ptr = (UBYTE*)atari_screen;
  1468.  
  1469.   DLIST=DLISTINIT;
  1470.   for (ypos = 0; ypos <8 ;ypos++) {
  1471.     carry=GO (carry+105);    /* 114 minus 9 memory cycles */
  1472.   }
  1473.   
  1474.   NMIST = 0x00;
  1475.  
  1476.   for (ypos = 8, JVB=FALSE ; ypos < (ATARI_HEIGHT + 8);) {
  1477.  
  1478.     /* Counter needed for the DMA cycles to fetch display instructions */
  1479.     dmabase = 0;
  1480.  
  1481.     /* vertical scroll flags. */
  1482.     vertlast=vertthis;
  1483.     vertthis=FALSE;
  1484.  
  1485.     /* setup base DMA width. Changed for HSCROL */
  1486.     dmawidth = DMAwidth;
  1487.  
  1488.    /* display width */
  1489.     width = dmawidth<<6;
  1490.  
  1491.     gen = NULL;
  1492.     /* scan line generator. Needs to be called for each scan line
  1493.        to be generated. */
  1494.  
  1495.     /* dmawidth must be shifted by this to get the DMA display cycles */
  1496.     dmashift = 0;
  1497.     
  1498.     if (JVB || (DMACTL & 0x20)==0) {
  1499.       ANTIC_Scanline(9,FALSE,FALSE,&Build_Blank,scrn_ptr,ATARI_MODULO,0);
  1500.     } else {
  1501.       IR = APeek(DLIST);
  1502.       DLIST++;
  1503.       dmabase++;
  1504.  
  1505.       switch (IR & 0x0f)
  1506.     {
  1507.     case 0x00 :
  1508.       nlines = ((IR >> 4)  & 0x07) + 1;
  1509.       gen = &Build_Blank;
  1510.       IR &= 0x80;           /* avoid confusion with scrolling flags */
  1511.       break;
  1512.     case 0x01 :
  1513.       if (IR & 0x40)
  1514.         JVB = TRUE;
  1515.       DLIST = DAPeek(DLIST);
  1516.       dmabase += 2;
  1517.       nlines = 1;
  1518.       gen = &Build_Blank;    /* Jump aparently uses 1 scan line */
  1519.       IR &= 0x80;
  1520.       break;
  1521.     default :
  1522.       if (IR & 0x40) {
  1523.           screenaddr = DAPeek(DLIST);
  1524.           DLIST += 2;
  1525.           dmabase += 2;
  1526.         }
  1527.     
  1528.       /* Keep track of vertical scrolling */
  1529.       if (IR & 0x20) {
  1530.         vertthis = TRUE;
  1531.       }
  1532.  
  1533.       if (IR & 0x10) {
  1534.         if (dmawidth<6) {
  1535.           dmawidth++;
  1536.           width += 64;
  1537.         }
  1538.       }
  1539.       
  1540.       switch (IR & 0x0f) {
  1541.         case 0x02 :
  1542.           nlines = 8;
  1543.           dmashift = 3;               /* dmawith * 8 */
  1544.           dmabase += (dmawidth<<3)+memory_basis-9;  /* reduce memory DMA */
  1545.           gen = Antic_2(width);
  1546.           break;
  1547.         case 0x03 :
  1548.           nlines = 10;
  1549.           dmashift = 3;
  1550.           dmabase += (dmawidth<<3)+memory_basis-9;
  1551.           gen = Antic_3(width);
  1552.           break;
  1553.         case 0x04 :
  1554.           nlines = 8;
  1555.           dmashift = 3;
  1556.           dmabase += (dmawidth<<3)+memory_basis-9;
  1557.           gen = Antic_4(width);
  1558.           break;
  1559.         case 0x05 :
  1560.           nlines = 16;
  1561.           dmashift = 3;
  1562.           dmabase += (dmawidth<<3)+memory_basis-9;
  1563.           gen = Antic_5(width);
  1564.           break;
  1565.         case 0x06 :
  1566.           nlines = 8;
  1567.           dmashift = 2;
  1568.           dmabase += (dmawidth<<2);
  1569.           gen = Antic_6(width);
  1570.           break;
  1571.         case 0x07 :
  1572.           nlines = 16;
  1573.           dmashift = 2;
  1574.           dmabase += (dmawidth<<2);
  1575.           gen = Antic_7(width);
  1576.           break;
  1577.         case 0x08 :
  1578.           nlines = 8;
  1579.           dmabase += (dmawidth<<1);
  1580.           gen = Antic_8(width);
  1581.           break;
  1582.         case 0x09 :
  1583.           nlines = 4;
  1584.           dmabase += (dmawidth<<1);
  1585.           gen = Antic_9(width);
  1586.           break;
  1587.         case 0x0a :
  1588.           nlines = 4;
  1589.           dmabase += (dmawidth<<2);
  1590.           gen = Antic_A(width);
  1591.           break;
  1592.         case 0x0b :
  1593.           nlines = 2;
  1594.           dmabase += (dmawidth<<2);
  1595.           gen = Antic_B(width);
  1596.           break;
  1597.         case 0x0c :
  1598.           nlines = 1;
  1599.           dmabase += (dmawidth<<2);
  1600.           gen = Antic_C(width);
  1601.           break;
  1602.         case 0x0d :
  1603.           nlines = 2;
  1604.           dmabase += (dmawidth<<3);
  1605.           gen = Antic_D(width);
  1606.           break;
  1607.         case 0x0e :
  1608.           nlines = 1;
  1609.           dmabase += (dmawidth<<3);
  1610.           gen = Antic_E(width);
  1611.           break;
  1612.         case 0x0f :
  1613.           nlines = 1;
  1614.           dmabase += (dmawidth<<3);
  1615.           gen = Antic_F(width);
  1616.           break;
  1617.         default :
  1618.           printf("Antic.c: IR %x caused problems.\n",IR);
  1619.           nlines = 0;
  1620.           break;
  1621.         }
  1622.       break;
  1623.     }
  1624.       
  1625.       if (nlines > 0) {
  1626.     int first,last;
  1627.     
  1628.     if (gen) {
  1629.       /* Calculate the first & last line to display */
  1630.       first = 0;
  1631.       last  = nlines-1;
  1632.       
  1633.       /* If this is a VScrol-Line, delay the first line. */
  1634.       if (vertthis && !vertlast) {
  1635.         first = VSCROL;
  1636.         if (first>last)
  1637.           first -= 16;
  1638.       }
  1639.       if (!vertthis && vertlast) {
  1640.         last = VSCROL+1;
  1641.       }
  1642.       
  1643.       Antic_Modeline(IR,first,last,nlines,dmashift,dmabase,gen);
  1644.     } else {
  1645.       printf("Antic.c: Found unknown mode generator.\n");
  1646.     }
  1647.       }
  1648.     }
  1649.   }
  1650.  
  1651.   for(ypos=248; ypos<vsync_pos;ypos++)
  1652.     carry = GO(carry+105);
  1653.   
  1654.   NMIST = 0x40; /* Set VBLANK */
  1655.   if (NMIEN & 0x40) {
  1656.     carry=GO (carry+7); 
  1657.     /* Needed for programs that monitor NMIST (Spy's Demise, GORF) */
  1658.     NMI ();
  1659.     carry -= dli_delay+7;   /* Needed by 6502 to react */
  1660.   }
  1661.   
  1662.   if (tv_mode == PAL)
  1663.     for (ypos=vsync_pos;ypos<312;ypos++)
  1664.       carry=GO (carry+105);
  1665.   else
  1666.     for (ypos=vsync_pos;ypos<262;ypos++)
  1667.       carry=GO (carry+105);
  1668. }
  1669.  
  1670.