home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / utilitys / 105 / source / _xatari.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-11-09  |  78.1 KB  |  3,141 lines

  1.  
  2. /***************************************************************************
  3.  
  4.    XATARI.C  by Darek Mihocka (CIS: 73657,2714   GEnie: DAREKM)
  5.  
  6.    This file contains the hardware emulation routines of an Atari 800.
  7.  
  8.    June 14, 1987     19:50
  9.  
  10.  ***************************************************************************/
  11.  
  12. #include <stdio.h>
  13. #include <osbind.h>
  14. #include "_xformer.h"
  15.  
  16. #define QNIL (DL *)0L
  17.  
  18. typedef struct
  19.     {
  20.     int mode;       /* antic mode */
  21.     int height;     /* height in scan lines */
  22.     int width;      /* width in bytes per line */
  23.     int block_size; /* number of consecutive bytes displayed */
  24.     int scan;       /* starting scan line */
  25.     unsigned start; /* location of first byte being displayed */
  26.     } DL;
  27.  
  28. #define Rnewfont A1
  29. #define Rhorbyte D2
  30. #define Rscansiz D3
  31.  
  32. #define SETREAD   ADDQ.W #1,isread(A4)
  33. #define SETWRITE  CLR.W  isread(A4)
  34. #define TESTWRITE TST.W  isread(A4)
  35.  
  36. /* The following are variables required for the service routines */
  37.  
  38. unsigned int dl=0;   /* value of start of display list */
  39. int fRedraw=FALSE;   /* flag to redraw the screen during VBI */
  40.     gtia=0,          /* set if in GTIA display mode */
  41.     mdPMG=0,         /* 0= off, 1= byte mode, 2=single line, 3=double line */
  42.     mdWidth,         /* 1 = 32 columns,  2 = 40 columns, 0,3 undefined */
  43.     dma=0,           /* state of video chip access */
  44.      /* bit 1,0 select playfield width, stored in mdWidth */
  45.      /* bit 2 unknown, ignored here */
  46.      /* bit 3, unknown, ignored here */
  47.      /* bit 4, 1= double line PMG, 0= single line PMG */
  48.      /* bit 5, PMG DMA enabled */
  49.      /* bit 6, unknown, ignored here */
  50.      /* bit 7  unknown, ignored here */
  51.     fSTART, fSELECT, fOPTION,  /* console key flags */
  52.     fBREAK,      /* BREAK key flag */
  53.     IKBD,        /* value of keyboard interrupt */
  54.     cBeep=0,     /* counter for speaker access */
  55.     pmg,     /* $D01D contains flags for PMG */
  56.     pmbase,      /* $D407 */
  57.     hposP[4],    /* $D000 horizontal position of players */
  58.     hposM[4],    /* $D004 horizontal position of missles */
  59.     grafP[4],    /* $D00D data for players if DMA is not on */
  60.     grafM=0;     /* $D011 data for missles */
  61.  
  62. char *qP[4], *qM;    /* pointers to player missle data */
  63.  
  64. char shadows[16];    /* 8 bit values stored in shadow registers */
  65. char keyboard=255;   /* value of keyboard register */
  66. int DOS_hand[8];     /* atari 2.0 DOS file handles for GEMDOS */
  67. int DOS_mode[8];     /* open modes for each file */
  68. char filename[15];
  69.  
  70. DL dlBlocks[200];
  71.  
  72. long *IntrptPtr;
  73. int IRet;
  74.  
  75. char norm_font[2048] ;
  76. int wide_font[2048] ;    /* conversion from 8 bit pattern to wide 16 bits */
  77. int wide_byte[256] ;
  78.  
  79. int mul40[200],mul80[200],mul160[200];
  80.  
  81. extern
  82.   nul() ,    /* should never execute */
  83.   w_ROM(),       /* attempt to write to ROM */
  84.   w_0230(),      /* DL pointer */
  85.   w_022F(),      /* DMA control */
  86.   w_dl(),    /* changing the display list */
  87.   w_GTIA(),      /* GTIA display mode register */
  88.   screen(),      /* attempt to plot to ANTIC mode 0-15 */
  89.   w_710(),       /* shadow color register */
  90.   w_D012(),      /* hardware color register */
  91.   w_02F4(),      /* chset base page */
  92.   s_brk(),       /* break key flag */
  93.   s_con(),       /* console keys */
  94.   s_rnd(),       /* random number location */
  95.   s_vcount(),    /* scan line counter register */
  96.   w_D200(),      /* sound registers */
  97.   w_xP(),    /* horizontal player positions write */
  98.   w_xM(),    /* horizontal missle positions write */
  99.   w_gM(),    /* graphics data for missle */
  100.   w_gP(),    /* graphics data for player */
  101.   w_sP(),    /* size of player */
  102.   w_sM(),    /* size of missle */
  103.   w_P0(),    /* writing to player 0 data array */
  104.   w_P1(),    /* writing to player 1 data array */
  105.   w_P2(),    /* writing to player 2 data array */
  106.   w_P3(),    /* writing to player 3 data array */
  107.   w_M(),     /* writing to missle data array */
  108.   w_PMB(),   /* writing to PMBASE */
  109.   w_PMG()    /* writing to DMACTL */
  110.  ;
  111.  
  112. /* This array is used to map one of 128 8 bit colours to ST colours */
  113.  
  114. int rainbow[128] = {
  115.   0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777,
  116.   0x200, 0x320, 0x430, 0x541, 0x650, 0x653, 0x764, 0x775,
  117.   0x200, 0x420, 0x530, 0x742, 0x753, 0x754, 0x754, 0x765,
  118.   0x200, 0x400, 0x500, 0x630, 0x643, 0x754, 0x754, 0x765,
  119.   0x400, 0x500, 0x511, 0x600, 0x744, 0x755, 0x755, 0x766,
  120.   0x301, 0x402, 0x513, 0x613, 0x634, 0x645, 0x756, 0x766,
  121.   0x202, 0x303, 0x404, 0x526, 0x636, 0x646, 0x757, 0x767,
  122.   0x203, 0x204, 0x325, 0x426, 0x446, 0x557, 0x667, 0x667,
  123.   0x003, 0x004, 0x115, 0x226, 0x346, 0x457, 0x567, 0x667,
  124.   0x003, 0x004, 0x115, 0x236, 0x346, 0x457, 0x567, 0x667,
  125.   0x012, 0x023, 0x234, 0x345, 0x366, 0x466, 0x577, 0x677,
  126.   0x022, 0x032, 0x043, 0x243, 0x354, 0x465, 0x576, 0x676,
  127.   0x020, 0x030, 0x040, 0x242, 0x353, 0x464, 0x575, 0x676,
  128.   0x220, 0x230, 0x342, 0x352, 0x463, 0x473, 0x674, 0x775,
  129.   0x220, 0x330, 0x332, 0x442, 0x553, 0x663, 0x664, 0x775,
  130.   0x210, 0x320, 0x432, 0x540, 0x543, 0x654, 0x764, 0x775 } ;
  131.  
  132. int scan_table[16] = {    /* height in pixels of each ANTIC mode */
  133.   0,1,8,10,8,16,8,16,8,4,4,2,1,2,1,1 } ;
  134.  
  135. /* bytes per scan line */
  136. int rghor_bytes[4][16] =
  137.   {
  138.   {0,0,20,20,20,20,10,10,05,05,10,10,10,20,20,20},
  139.   {0,0,32,32,32,32,16,16,8,8,16,16,16,32,32,32},
  140.   {0,0,40,40,40,40,20,20,10,10,20,20,20,40,40,40},
  141.   {0,0,40,40,40,40,20,20,10,10,20,20,20,40,40,40}
  142.   } ;
  143.  
  144. int *phor_bytes;
  145.  
  146. int (*serv_hrdw[256])() = {    /* array of pointers to 256 service routines */
  147.  
  148.   nul  ,w_022F,w_ROM,  nul  ,w_0230,w_D200, w_710,w_D012, /* 128 write */
  149.   w_GTIA,nul  , nul  , nul  , nul  , nul  ,w_02F4, nul  ,
  150.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  151.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  152.   w_xP , w_xM , w_gP , w_gM , w_sP , w_sM , w_M  , w_PMG, /* player missle */
  153.   w_P0 , w_P1 , w_P2 , w_P3 , nul  , nul  , nul  , w_PMB, /* locations */
  154.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  155.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  156.   w_dl , screen,nul  , nul  , nul  , nul  , nul  , nul  ,
  157.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  158.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  159.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  160.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  161.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  162.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  163.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,
  164.   nul  , s_con, s_rnd, s_vcount,nul, nul  , nul  , nul  ,  /* 128 read */
  165.   nul  , nul  , nul  , nul  , nul  , nul  , nul  , nul  ,  /* and write */
  166.   nul  /* don't need the rest */
  167.  } ;
  168.  
  169.  
  170. /* given a vector, insert the given opcode at the address pointed to */
  171.  
  172. patch(vec,opc)
  173. register unsigned vec;
  174. register char opc;
  175.     {
  176.     register char *pch;
  177.  
  178.     pch = mem + (unsigned)(*(mem+vec)) + (unsigned)(*(mem+vec+1))*256;
  179.     *pch = opc;
  180.     }
  181.  
  182.  
  183. /* given a handler vector, insert the given opcode at the address pointed to */
  184.  
  185. patchind(vec,opc)
  186. register unsigned vec;
  187. register char opc;
  188.     {
  189.     register char *pch;
  190.  
  191.     pch = mem + (unsigned)(*(mem+vec)) + (unsigned)(*(mem+vec+1))*256 + 1 ;
  192.     *pch = opc;
  193.     }
  194.  
  195.  
  196. /* initialize the stat[] array and set defaults for power on */
  197.  
  198. InitMachine()
  199.   {
  200.  
  201.   register int old, num8, num16 ;
  202.  
  203.   /* Patch the operating system */
  204.   {
  205.     char *qch;
  206.     unsigned addr;
  207.  
  208.     /* replace cassette vectors with DOS vectors */
  209.     patchind (0xE440,0x0F);
  210.     patchind (0xE442,0x1F);
  211.     patchind (0xE444,0x2F);
  212.     patchind (0xE446,0x3F);
  213.     patchind (0xE448,0x4F);
  214.     patchind (0xE44A,0x5F);
  215.  
  216.     /* patch new P: vectors */
  217.     patchind (0xE430,0x7F);
  218.     patchind (0xE432,0x7F);
  219.     patchind (0xE434,0x7F);
  220.     patchind (0xE436,0x6F);
  221.     patchind (0xE438,0x7F);
  222.     patchind (0xE43A,0x7F);
  223.  
  224.  
  225.     /* E: put */
  226.    /* patchind (0xE406,0x0C); */
  227.  
  228.     /* blackboard vector */
  229.     patch (0xE472,0x00);
  230.  
  231.     /* SIO vectors */
  232.     patch (0xE454,0x60);
  233.     patch (0xE45A,0x60);
  234.  
  235.     /* replace C: with D: */
  236.     addr = 0xE400;
  237.     while (addr<0xFFF0)
  238.         {
  239.         qch = mem+addr++;
  240.         if (*qch=='C' && *(qch+3)=='E' && *(qch+6)=='S')
  241.             *qch = 'D';
  242.         }
  243.  
  244.     /* create a RTS vector */
  245.     qch=mem+(unsigned)0xE44CL;
  246.     *qch++ = 76;   /* JMP */
  247.     *qch++ = 0x4F;
  248.     *qch++ = 0xE4;
  249.     *qch   = 96;   /* RTS */
  250.  
  251.     /* take out JSR disk boot - this is a ROM B specific address!!!!*/
  252.     qch=mem+55296L+6652L;
  253.     *qch++ = 234;    *qch++ = 234;    *qch++ = 234;
  254.  
  255.     /* check if we have Fastchip loaded, if so, patch in special opcode */
  256.     qch=mem+55296L+507L;  /* $D9FB */
  257.     if (*qch==(char)0xD8)
  258.         {
  259.         *qch = 0x02;   /* patch in our special opcode for normalization */
  260.         qch=mem+55296L+614L;  /* $DA66 */
  261.     /*    *qch = 0x12;   opcode for floating point add, not debugged */
  262.         }
  263.     }
  264.  
  265.  /* quick routine to create 16 bit wide bytes */
  266.   for (num8=0 ; num8<256; num8++)
  267.       {
  268.       num16 = 0 ;
  269.       old=num8 ;
  270.       if (old&1)
  271.           num16 |= 3 ;
  272.       if (old&2)
  273.          num16 |= 12 ;
  274.       if (old&4)
  275.          num16 |= 48 ;
  276.       if (old&8)
  277.          num16 |= 192 ;
  278.       if (old&16)
  279.          num16 |= 768 ;
  280.       if (old&32)
  281.          num16 |= 3072 ;
  282.       if (old&64)
  283.          num16 |= 12288 ;
  284.       if (old&128)
  285.          num16 |= 0xC000 ;
  286.       wide_byte[num8] = num16 ;
  287.    }
  288.  
  289.   for (num8=0; num8<200; num8++)
  290.      {
  291.      mul40[num8]=num8*40;
  292.      mul80[num8]=num8*80;
  293.      mul160[num8]=num8*160;
  294.      }
  295.  
  296.   for (ea=0; ea<8; DOS_hand[ea++]=-1); /* clear out DOS handles */
  297.  
  298.   for (ea=0; ea; stat[ea++]=0) ;   /* clear out stat array */
  299.  
  300.   stat[0x022F] = 1 ;  /* DMA control */
  301.  
  302.   if (fCartA)
  303.       for (ea=40960; ea<49152; ea++)           /* BASIC and OS are ROM */
  304.           stat[ea]=2 ;
  305.  
  306.   if (fCartB)
  307.       for (ea=32768; ea<40960; ea++)
  308.           stat[ea]=2 ;
  309.  
  310.   for (ea=49152; ea<53248; ea++)
  311.       stat[ea]=2 ;
  312.  
  313.   for (ea=53248; ea<55296; ea++)
  314.       stat[ea]=2 ;
  315.  
  316.   for (ea=55296; ea<65535; ea++)
  317.       stat[ea]=2 ;
  318.  
  319.  /* For some functions, support the shadow, not the hardware location. */
  320.  /* This is because it's unlikely anyone will do them on the fly. */
  321.  /* Possibly in a DLI routine, but those aren't supported anyway. */
  322.  
  323.   stat[0x0230] = 4 ;  /* start of display RAM */
  324.   stat[0x0231] = 4 ;  /* not supporting hardware location */
  325.  
  326.   for (ea=0xD200; ea<=0xD209; ea++)
  327.      stat[ea]=5 ;     /* sound registers */
  328.  
  329.   for (ea=704; ea<=712; ea++)
  330.      stat[ea]=6;      /* shadow color registers */
  331.  
  332.   for (ea=53270; ea<=53274; ea++)
  333.      stat[ea]=7 ;     /* hardware color registers */
  334.  
  335.   stat[623] = 8 ;     /* GTIA mode, not supporing hardware location */
  336.   stat[756] = 14 ;    /* chset base page, not supporting hardware loc. */
  337.  
  338.   stat[53248] = 32;   /* player horizontal */
  339.   stat[53252] = 33;   /* missle horizontal */
  340.  
  341.   stat[53261] = 34;   /* player data */
  342.   stat[53265] = 35;   /* missle data */
  343.  
  344.   stat[53277] = 39;   /* enables DMA PMG */
  345.  
  346.   stat[54279] = 47;   /* positions PMG data pages */
  347.  
  348.  /* These are memory locations that return special values on a read. */
  349.  /* They also cause writes to be trapped and ignored (usually). */
  350.  
  351.   stat[53279] = 129 ; /* console */
  352.   stat[53770] = 130 ; /* random */
  353.   stat[54283] = 131 ; /* vcount */
  354.  
  355.   dlBlocks[0].mode=-1;
  356.  
  357.   } /* END OF INIT */
  358.  
  359. IntOn()
  360.     {
  361.   asm
  362.     {                           ; save A4 where we can find it later */
  363.     lea     RegA4(PC),A0
  364.     move.l  A4,(A0)
  365.     }
  366.  
  367.     JoyOn();       /* initialize joystick vector */
  368.     Supexec(VBIon);  /* init VBI routine */
  369.     Install_Key();
  370.     fSTART = fSELECT = fOPTION = FALSE;
  371.     }
  372.  
  373. IntOff()
  374.     {
  375.     JoyOff();                 /* disconnect joystick handler */
  376.     Remove_Key();              /* disconnect keyboard handler patch */
  377.     Supexec(VBIoff);
  378.     }
  379.  
  380.  
  381. foo() {    /* This function is never called.
  382.               It's purpose is to allow the 68000 routines to pop into
  383.               C once in a while.
  384.               Therefore they must be inside a C function.   */
  385.  
  386.  
  387.  /* emul_serv is called whenever a read/write access is attempted
  388.     to non-RAM memory locations, such as ROM or hardware registers.
  389.  
  390.     when status bytes are > $80  (read and write)
  391.     REGEA points to memory to read with D0
  392.     this routine ends with DISPATCH when writing
  393.     and RTS when reading
  394.  
  395.     when status bytes are <>=0 (write-only)
  396.     REGEA points to memory to write with D0
  397.     byte to poke is in high byte of DBUS
  398.     this routine ends with DISPATCH
  399.   */
  400.  asm {
  401.  
  402.   emul_serv:
  403.     ANDI.W  #0x00FF,IR              ; clear out bits 8..15
  404.     ADD.W   IR,IR
  405.     ADD.W   IR,IR                   ; calculate offset
  406.     LEA     serv_hrdw(GLOBAL),REGMEA ; get start of vector table
  407.     MOVE.L  0(REGMEA,IR.W),REGMEA   ; calculate correct vector
  408.     JMP     (REGMEA)                ; jump through it
  409.  
  410.  
  411.  /* The following routine is most of the system vertical blank re-written */
  412.  /* in 68000 so that it can be executed much faster. */
  413.  
  414.  sysvbl:
  415.     SAVEREGS
  416.     lea     emul(PC),A0
  417.     tst.b   fTrace(GLOBAL)
  418.     beq.s   nt
  419.     lea     exit_emul(PC),A0
  420.   nt:
  421.     lea     pemul(PC),A1
  422.     move.l  A0,(A1)         ; change dispatch vector to normal
  423.  
  424.     move.l  mem(GLOBAL),REGMEA          ; get pointer to byte 0
  425.  
  426.   ; the incrementing of the clocks is not done here. see VBI
  427.  
  428.   sysvb1:
  429.     move.b  #0xFE,REGA
  430.     clr.b   REGX
  431.     move.b  77(REGMEA),REGY
  432.     bpl.s   vbatra
  433.     move.b  REGA,77(REGMEA)
  434.     move.b  19(REGMEA),REGX
  435.     move.b  #0xF6,REGA
  436.   vbatra:
  437.     move.b  REGA,78(REGMEA)         ; drkmsk
  438.     move.b  REGX,79(REGMEA)         ; colrsh
  439.  
  440.     lea     rainbow(GLOBAL),A0      ; pointer to rainbow[128]
  441.     lea     rgPalette(GLOBAL),A1
  442.     lea     32(A1),A1               ; pointer to ST colors
  443.     lea     0x8240,A2               ; pointer to ST colors regs
  444.     lea     shadows(GLOBAL),A3      ; pointer to 8 bit colors
  445.     move.w  #15,REGY
  446.   sysvb2:
  447.     clr.l   D0
  448.     move.b  (A3)+,D0
  449.     eor.b   REGX,D0
  450.     and.b   REGA,D0
  451.     andi.w  #~1,D0
  452.     move.w  0(A0,D0.L),D0
  453.     move.w  D0,(A1)+
  454.     move.w  D0,(A2)+
  455.     dbf     REGY,sysvb2
  456.     }
  457.     {
  458.     long scan_code ;
  459.     int scan, shift ;
  460.     int fSHIFT,fCTRL;
  461.     static int fBreakEnable=TRUE;
  462.  
  463.     if (Kbshift(-1)&8)         /* ALT key is used as the BREAK key */
  464.         {
  465.         if (fBreakEnable)
  466.             {
  467.             *(mem+17)=0;
  468.             fBreakEnable=FALSE;
  469.             }
  470.         }
  471.     else
  472.         {
  473.         fBreakEnable=TRUE;
  474.         *(mem+17)=1;
  475.         }
  476.  
  477.     if (Bconstat(2) != 0)
  478.         {
  479.         *(mem+77)=0;     /* clear attract mode */
  480.         keyboard = scan_code = Bconin(2) ;    /* get ASCII */
  481.         shift=Kbshift(-1);
  482.         fSHIFT=(shift&3)?64:0;
  483.         fCTRL =(shift&4)?128:0;
  484.  
  485.         switch(scan_code>>16)
  486.             {
  487.         case  1:
  488.             *(mem+764)=28+fSHIFT+fCTRL ; /* ESCape */
  489.             break ;
  490.  
  491.         case  3:
  492.             *(mem+764) =30+(fSHIFT?87:0)+fCTRL ;  /* 2 */
  493.             break ;
  494.  
  495.         case  4:
  496.             *(mem+764) =26+fSHIFT+fCTRL ;       /* 3 */
  497.             break ;
  498.  
  499.         case 14:
  500.             *(mem+764)=52+fSHIFT+fCTRL ;       /* BS */
  501.             break ;
  502.  
  503.         case 83:
  504.             *(mem+764)=180-fSHIFT;       /* delete BS */
  505.             break ;
  506.  
  507.         case 15:
  508.             *(mem+764) =44+fSHIFT+fCTRL ;       /* TAB */
  509.             break ;
  510.  
  511.         case 114:
  512.         case 28:
  513.             *(mem+764) =12+fSHIFT+fCTRL ;       /* CR */
  514.             break ;
  515.  
  516.         case 72:
  517.             *(mem+764) = 142 ;       /* CTRL up arrow */
  518.             break ;
  519.  
  520.         case 80:
  521.             *(mem+764) = 143 ;       /* CTRL dn arrow */
  522.             break ;
  523.  
  524.         case 75:
  525.             *(mem+764) = 134 ;       /* CTRL lt arrow */
  526.            break ;
  527.  
  528.         case 77:
  529.             *(mem+764) = 135 ;       /* CTRL rt arrow */
  530.             break ;
  531.  
  532.         case 119:
  533.         case 71:
  534.             *(mem+764) = 118+(fCTRL?64:0);     /* shift CLR */
  535.             break ;
  536.  
  537.         case 82:
  538.             *(mem+764) = 55+128-fSHIFT;    /* CTRL insert */
  539.             break ;
  540.  
  541.         case 88:
  542.         case 63:
  543.             *(mem+764) = 39 ;        /* F5 = /|\ */
  544.             break ;
  545.  
  546.         case 62:
  547.             *(mem+764)=fCTRL+60; /* F4 = caps */
  548.             break ;
  549.  
  550.         case 87:
  551.             *(mem+764) = 60+64 ;     /* F4 = shift caps */
  552.             break ;
  553.  
  554.         case 68:
  555.   asm
  556.     {                    /* F10 = RESET */
  557.     LOADREGS
  558.     clr.w    dma(GLOBAL)     ; shut screen off
  559.     move.b  #0x224,REGEA
  560.     move.l  REGEA,REGMEA
  561.     clr.w   (REGMEA)         ; clear VVBLKD
  562.     MOVE.W   #0xE474,REGPC   ; stuff warmstart vector
  563.     MOVE.L   REGPC,REGMPC    ; into PC
  564.     DISPATCH
  565.     }
  566.             break ;
  567.  
  568.         case 59:
  569.   asm
  570.     {                    /* F1 = force break */
  571.     LOADREGS
  572.     bra     op00
  573.     }
  574.         case 60:        /* F2 = redraw */
  575.             clear_disp();
  576.             do_display();
  577.             break;
  578.  
  579.         default:
  580.             if (keyboard)                    /* if regular character */
  581.                 for (scan=0 ; scan<192 ; scan ++)  /* to internal */
  582.                     if (*(mem+0xFEFE+scan) == keyboard)
  583.                           *(mem+764)=scan;
  584.  
  585.               } /* switch */
  586.  
  587.         *(mem + 0x0000D209L) = mem[764];
  588.         if (mem[764]==255)
  589.                *(mem+0x0D20F) = 255;
  590.         else
  591.                *(mem+0x0D20F) = 251;
  592.         *(mem+0x0D21F) = *(mem+0x0D20F) ;   /* this pleases AtariWriter */
  593.         } /* while */
  594.  
  595.     if (fRedraw)
  596.         {
  597.         clear_disp();
  598.         do_display();
  599.         }
  600.     }
  601.  asm
  602.     {
  603.     LOADREGS
  604.  
  605.   ; Now we want to call the deferred vertical blank routine at VVBLKD ($224).
  606.   ; It ends in an RTI so we not only push the PC to the stack, but also the
  607.   ; status register. Don't bother encoding it to 6502 format.
  608.  
  609.     btst    #5,REGST                ; get out if interrupts disabled
  610.     bne.s   noVVBLKD
  611.  
  612.     move.w  #0x225,REGEA            ; just for grins, make sure it is non-0
  613.     move.l  REGEA,REGMEA
  614.     tst.b   (REGMEA)
  615.     beq.s   noVVBLKD                ; it is, must be in a warmstart
  616.  
  617.   ; push the PC and status register, then push A,X and Y to the stack
  618.     subq.B  #6,REGSP
  619.     move.W  REGSP,REGEA
  620.     move.L  REGEA,REGMEA
  621.     move.B  REGST,6(REGMEA)         ; push status register
  622.     move.W  REGMPC,REGPC
  623.     move.B  REGPC,4(REGMEA)         ; push PClo
  624.     move.W  REGPC,-(SP)
  625.     move.B  (SP)+,5(REGMEA)         ; push PChi
  626.     move.B  REGA,3(REGMEA)          ; PHA
  627.     move.B  REGX,2(REGMEA)          ; PHX
  628.     move.B  REGY,1(REGMEA)          ; PHY
  629.  
  630.   ; do a JMP ($224)
  631.     move.w  #0x224,REGEA
  632.     move.L  REGEA,REGMEA
  633.     move.B  1(REGMEA),-(SP)
  634.     move.W  (SP)+,REGPC
  635.     move.B  (REGMEA),REGPC
  636.     move.L  REGPC,REGMPC
  637.  
  638.   noVVBLKD:
  639.     DISPATCH
  640.  
  641.  
  642.   nul:       /* should never execute! but just in case... */
  643.     SWAP    DBUS
  644.   do_write:
  645.     MOVE.L  REGEA,REGMEA
  646.     MOVE.B  DBUS,(REGMEA)    /* do the actual write to memory */
  647.     DISPATCH
  648.  
  649.   w_dl:
  650.     SWAP    DBUS
  651.     MOVE.L  REGEA,REGMEA
  652.     move.b  (REGMEA),x(GLOBAL)  ; get old value
  653.     MOVE.B  DBUS,(REGMEA)       ; do the actual write to memory */
  654.     move.b  DBUS,a(GLOBAL)
  655.     SAVEREGS
  656.     }
  657.     if (dma && a!=x)
  658.         fRedraw=TRUE;
  659.    asm
  660.     {
  661.     LOADREGS
  662.     DISPATCH
  663.  
  664.   w_0230:
  665.     move.w  dl(GLOBAL),ea(GLOBAL)   ; save old display list pointer
  666.     move.l  REGEA,REGMEA
  667.     btst    #0,REGEA                ; check address to poke to
  668.     BNE     w_0231
  669.     SWAP    DBUS
  670.     MOVE.B  DBUS,dl+1(GLOBAL)       ; if 230, then low byte of dl
  671.     move.b  (REGMEA),REGEA
  672.     cmp.b   REGEA,DBUS              ; are we changing value?
  673.     beq.s   w_0230_exit
  674.     move.b  DBUS,(REGMEA)
  675.     BRA     w_0230_2
  676.   w_0231:
  677.     SWAP    DBUS        ; if 231, then high byte of dl
  678.     MOVE.B  DBUS,dl(GLOBAL)
  679.     move.b  (REGMEA),REGEA
  680.     cmp.b   REGEA,DBUS              ; are we changing value?
  681.     beq.s   w_0230_exit
  682.     move.b  DBUS,(REGMEA)           ; write new value
  683.   w_0230_2:
  684.     SAVEREGS
  685.     }
  686.     if (dma)
  687.         {
  688.         fRedraw=TRUE;     /* screen must be redrawn, so release display list */
  689.         while (*(mem+ea)!=65 && (ea!=0xD000))
  690.             {
  691.             if (stat[ea]&64) stat[ea]=0;
  692.             ea++;
  693.             }
  694.         }
  695.   asm {
  696.     LOADREGS
  697.   w_0230_exit:
  698.     DISPATCH
  699.  
  700.   w_022F:
  701.     SWAP    DBUS
  702.     move.l  REGEA,REGMEA
  703.     move.b  DBUS,(REGMEA)
  704.     MOVE.W  DBUS,-(SP)                  ; save value
  705.     andi.w  #3,DBUS                     ; get playfield width
  706.     move.w  DBUS,mdWidth(GLOBAL)        ; store it
  707.     lsl.w   #5,DBUS
  708.     lea     rghor_bytes(GLOBAL),REGMEA
  709.     adda.w  DBUS,REGMEA
  710.     move.l  REGMEA,phor_bytes(GLOBAL)   ; phor_bytes = rghorbytes[mdWidth]
  711.  
  712.     MOVE.W  (SP)+,DBUS
  713.     andi.w  #0x20,DBUS
  714.     BNE     DMA_on
  715.   DMA_off:                              ; if DMA is off, blank screen
  716.     SAVEREGS
  717.        }
  718.        plot_0 (0,200) ;
  719.        ea=dl;
  720.        while (*(mem+ea)!=65 && (ea!=0xD000))
  721.            {
  722.            if (stat[ea]&64) stat[ea]=0;
  723.            ea++;
  724.            }
  725.        clear_disp();
  726.        dma=0;
  727.    asm {
  728.     LOADREGS
  729.     BRA     w_022Fexit
  730.   DMA_on:
  731.     SAVEREGS
  732.        }
  733.        if (dma)
  734.            {
  735.            if (mdWidth!=2)
  736.                plot_0 (0,200) ;
  737.            clear_disp();
  738.            }
  739.        dma=1;
  740.        do_display() ;
  741.  
  742.    asm {
  743.     LOADREGS
  744.   w_022Fexit:
  745.     DISPATCH
  746.  
  747.   w_710:                   /* color register */
  748.     SWAP    DBUS
  749.     MOVE.L  REGEA,REGMEA
  750.     MOVE.B  DBUS,(REGMEA)    /* do the actual write to memory */
  751.     MOVE.B  DBUS,a(GLOBAL)
  752.     MOVE.W  REGEA,ea(GLOBAL)
  753.     SAVEREGS
  754.     }
  755.         do_colors (ea,a) ;
  756.  asm
  757.     {
  758.     LOADREGS
  759.     DISPATCH
  760.  
  761.   w_D012:                   /* color register */
  762.     SWAP    DBUS
  763.     MOVE.L  REGEA,REGMEA
  764.     MOVE.B  DBUS,(REGMEA)    /* do the actual write to memory */
  765.     MOVE.B  DBUS,a(GLOBAL)
  766.     MOVE.W  REGEA,ea(GLOBAL)
  767.     SAVEREGS
  768.     }
  769.         do_color (ea,a) ;
  770.  asm
  771.     {
  772.     LOADREGS
  773.     DISPATCH
  774.  
  775.   w_GTIA:                   /* GTIA register */
  776.     SWAP    DBUS
  777.     MOVE.L  REGEA,REGMEA
  778.     MOVE.B  DBUS,(REGMEA)      /* do the actual write to memory */
  779.     ANDI.w  #0xC0,DBUS     /* bits 6 and 7 control GTIA mode */
  780.     move.w  DBUS,gtia(GLOBAL)  /* store in gtia */
  781.     SAVEREGS
  782.     }
  783.        {
  784.         int i;
  785.         for (i=704; i<=712; i++)
  786.             do_colors(i,mem[i]);
  787.         if (dma)
  788.             fRedraw=TRUE;
  789.        }
  790.    asm {
  791.         LOADREGS
  792.         DISPATCH
  793.  
  794.   w_D200:                  /* sound registers */
  795.     SWAP    DBUS
  796.     MOVE.L  REGEA,REGMEA
  797.     MOVE.B  DBUS,(REGMEA)    /* do the actual write to memory */
  798.     MOVE.B  DBUS,a(GLOBAL)
  799.     MOVE.W  REGEA,ea(GLOBAL)
  800.     SAVEREGS
  801.     }
  802.         {
  803.         register char tmp;
  804.  
  805.         switch (ea)
  806.             {
  807.         default:
  808.             break;
  809.         case 0xD200:
  810.         case 0xD202:
  811.         case 0xD204:
  812.         case 0xD206:
  813.             tmp = *(mem+ea+1);
  814.             Sound ((ea-0xD200)>>1,a,tmp>>4,tmp&15);
  815.             break;
  816.  
  817.         case 0xD201:
  818.         case 0xD203:
  819.         case 0xD205:
  820.         case 0xD207:
  821.             tmp = *(mem+ea-1);
  822.             Sound ((ea-0xD200)>>1,tmp,a>>4,a&15);
  823.             break;
  824.             }
  825.         }
  826.   asm
  827.     {
  828.     LOADREGS
  829.     DISPATCH
  830.  
  831.   w_02F4:                  /* character set */
  832.     SWAP    DBUS
  833.     MOVE.L  REGEA,REGMEA
  834.     move.b  (REGMEA),REGEA
  835.     cmp.b   DBUS,REGEA
  836.     beq.s   w_02F4_exit
  837.     MOVE.B  DBUS,(REGMEA)
  838.     SAVEREGS
  839.     }
  840.         do_chset() ;
  841.  asm
  842.     {
  843.     LOADREGS
  844.   w_02F4_exit:
  845.     DISPATCH
  846.  
  847.   screen:                      ; handler for screen plots
  848.     swap    DBUS               ; get byte we want to plot
  849.     MOVE.L  REGEA,REGMEA
  850.  
  851.     move.b  (REGMEA),REGEA     ; get old value
  852.     cmp.b   REGEA,DBUS         ; are we writing what's already there?
  853.     beq.s   skipscr            ; Sure are, skip the plot, save time
  854.  
  855.     MOVE.B  DBUS,(REGMEA)      ; do the actual write to memory
  856.     tst.w   dma(GLOBAL)
  857.     beq.s   skipscr            ; if dma is off, get out
  858.  
  859.     SAVEREGS                   ; save 6502 enviornment
  860.     move.w  REGMEA,-(SP)       ; push memory location
  861.     }
  862.     do_byte();                 /* address already on stack */
  863.   asm
  864.     {
  865.     addq.l  #2,SP
  866.     LOADREGS                   ; restore 6502 enviornment
  867.   skipscr:
  868.     DISPATCH
  869.  
  870.   s_brk:
  871.     TESTWRITE
  872.     beq     nul
  873.     SAVEREGS
  874.        }
  875.         {
  876.         *(mem+17)=(char)(1-fBREAK&1);
  877.         }
  878.   asm {
  879.     LOADREGS
  880.     RTS
  881.  
  882.   s_con:
  883.     TESTWRITE
  884.     beq.s   w_con
  885.     SAVEREGS
  886.        }
  887.         {
  888.         *(mem+53279)=(fSTART?0:1) | (fSELECT?0:2) | (fOPTION?0:4);
  889.         }
  890.   asm {
  891.     LOADREGS
  892.     RTS
  893.  
  894.   w_con:
  895.     move.w   cBeep(GLOBAL),DBUS    ; only click every 128th access to
  896.     add.w    #1,DBUS               ; compensate for speed slowdown
  897.     andi.w   #127,DBUS
  898.     move.w   DBUS,cBeep(GLOBAL)
  899.     tst.w    DBUS
  900.     bne.s    w_con_exit
  901.     swap     DBUS
  902.     cmpi.w   #8,DBUS               ; also get out if clearing console keys
  903.     beq.s    w_con_exit
  904.     SAVEREGS
  905.     }
  906.         Sound (2,20,10,15);      /* click a little */
  907.         Sound (2,0,0,0);
  908.   asm
  909.     {
  910.     LOADREGS
  911.   w_con_exit:
  912.     DISPATCH
  913.  
  914.   s_rnd:
  915.     TESTWRITE
  916.     beq     nul
  917.     SAVEREGS
  918.     }
  919.         *(mem+53770L)=(char)((Random()>>3)^x^(a&y));
  920.   asm
  921.     {
  922.     LOADREGS
  923.     RTS
  924.  
  925.   s_vcount:
  926.     TESTWRITE
  927.     beq      nul
  928.     move.b   0x8207,-(SP)
  929.     move.w   (SP)+,D0
  930.     move.b   0x8209,D0
  931.     divu     #20,D0
  932.     andi.w   #254,D0
  933.     MOVE.L  REGEA,REGMEA
  934.     MOVE.B  DBUS,(REGMEA)
  935.     RTS
  936.  
  937.   w_ROM:
  938.         DISPATCH
  939.  
  940.  
  941.  ; handler for P: putchar
  942.  
  943.   op6F:
  944.  
  945.     SAVEREGS
  946.     MOVE.B   REGA,a(GLOBAL)     ; character to print */
  947.   }
  948.     {
  949.     int timeout = 1000;
  950.  
  951.     do
  952.       {
  953.       if (Cprnos())
  954.         {                       /* if printer is ready */
  955.         timeout=0;
  956.         if (a!=155)
  957.             Cprnout (a) ;       /* then check for CR and print */
  958.         else
  959.             {
  960.             Cprnout(13) ;       /* if CR then send CRLF */
  961.             Cprnout(10) ;
  962.             }
  963.         y = 1 ;                 /* set status = good */
  964.         }
  965.       else y = 0x8A ;           /* else status = timeout error */
  966.       } while (timeout--);
  967.     }
  968.  asm {
  969.     LOADREGS
  970.     MOVE.b  y(GLOBAL),REGY     ; return status
  971.     FLAGS
  972.     BRA     op60
  973.  
  974.  ; handler for all other P: calls
  975. op7F:
  976.     MOVE.w  #1,REGY            ; return good status
  977.     FLAGS
  978.     BRA     op60
  979.  
  980.  
  981.   op0F: /* handler for open D: call */
  982.         SAVEREGS
  983.         MOVE.B  REGX,x(GLOBAL)
  984.       }
  985.      do_open();
  986.   asm {
  987.         LOADREGS
  988.         MOVE.B  y(GLOBAL),REGY     /* return status */
  989.         FLAGS
  990.         BRA     op60
  991.  
  992.   op2F: /* handler for get D: call */
  993.         SAVEREGS
  994.         MOVE.B  REGX,x(GLOBAL)
  995.       }
  996.         do_get();
  997.   asm {
  998.         LOADREGS
  999.         MOVE.B  a(GLOBAL),REGA
  1000.         MOVE.B  y(GLOBAL),REGY     /* return status */
  1001.         FLAGS
  1002.         BRA     op60
  1003.  
  1004.   op3F: /* handler for put D: call */
  1005.         SAVEREGS
  1006.         MOVE.B  REGX,x(GLOBAL)
  1007.         MOVE.B  REGA,a(GLOBAL)
  1008.       }
  1009.         do_put();
  1010.     asm {
  1011.         LOADREGS
  1012.         MOVE.B  y(GLOBAL),REGY     /* return status */
  1013.         FLAGS
  1014.         BRA     op60
  1015.  
  1016. op1F:
  1017. op4F:
  1018. op5F:   /* handler for close D: calls */
  1019.         SAVEREGS
  1020.         MOVE.B  REGX,x(GLOBAL)
  1021.       }
  1022.       do_close();
  1023.   asm {
  1024.         LOADREGS
  1025.         MOVE.B  y(GLOBAL),REGY     /* return status */
  1026.         FLAGS
  1027.         BRA     op60
  1028.  
  1029.   op0C: /* handler for E: */
  1030. /*
  1031.         SAVEREGS
  1032.         MOVE.B  REGA,a(GLOBAL)
  1033.         MOVE.B  REGX,x(GLOBAL)
  1034.         MOVE.B  REGY,y(GLOBAL)
  1035.         FLAGS
  1036.       }
  1037.       do_Eput();
  1038.   asm {
  1039.         LOADREGS
  1040.         MOVE.B  a(GLOBAL),REGA
  1041.         MOVE.B  x(GLOBAL),REGX
  1042.         MOVE.B  y(GLOBAL),REGY
  1043.         FLAGS
  1044. */
  1045.         BRA     op60
  1046.  
  1047.  
  1048.  /* Player missle graphics routines. ouch */
  1049.  
  1050.   w_xP:   /* horizontal player positions write */
  1051.   w_xM:   /* horizontal missle positions write */
  1052.   w_gM:   /* graphics data for missle */
  1053.   w_sP:   /* size of player */
  1054.   w_sM:   /* size of missle */
  1055.   w_P0:   /* writing to player 0 data array */
  1056.   w_P1:   /* writing to player 1 data array */
  1057.   w_P2:   /* writing to player 2 data array */
  1058.   w_P3:   /* writing to player 3 data array */
  1059.   w_M:    /* writing to missle data array */
  1060.   w_PMG:  /* writing to DMACTL */
  1061.     DISPATCH
  1062.  
  1063.   /**** opcode $02 is used to simulate the Fastchip normalize ****/
  1064.  
  1065.   /* FNORM - $D9FB normalize FR0 and terminate with an RTS */
  1066.  
  1067.   op02:
  1068.     move.w  #0,REGEA
  1069.     move.l  REGEA,REGMEA    ; REGMEA = mem
  1070.  
  1071.     andi.b  #~BITD,REGST
  1072.     lea     vec_6502(GLOBAL),REGOPS   ; CLD
  1073.  
  1074.     move.w  #5,REGY         ; LDY #5
  1075.  
  1076.   fnml:
  1077.     move.b  0xD5(REGMEA),REGA       ; LDA FR0+1
  1078.     beq.s   fnm2            ; BEQ FNM2
  1079.  
  1080.     andi.b  #~BITX,REGST    ; CLC
  1081.     bra     op60            ; RTS
  1082.  
  1083.   fnm2:
  1084.     clr.b   0xDA(REGMEA)    ; STA FR0+FPREC (A=0)
  1085.     subi.b  #1,0xD4(REGMEA) ; DEC FR0
  1086.  
  1087.   fnm3:
  1088.     move.w  #0x00FB,REGX    ; LDX #1-FPREC
  1089.  
  1090.   fnm4:
  1091.     move.b  0xDB(REGMEA,REGX.w),0xDA(REGMEA,REGX.w) ; LDA FRO+FPREC+1,X
  1092.                                 ; STA FRO+FPREC,X
  1093.  
  1094.     add.b   #1,REGX         ; INX
  1095.     bne.s   fnm4            ; BNE FNM4
  1096.  
  1097.     sub.b   #1,REGY         ; DEY
  1098.     bne.s   fnml            ; BNE FNML
  1099.  
  1100.     move.w  #0xDA43,REGPC
  1101.     move.l  REGPC,REGMPC
  1102.     DISPATCH                ; BEQ RZERO ($DA43) unconditinal
  1103.  
  1104.   /**** opcode $12 is used to simulate the Fastchip add, a bit buggy  ****/
  1105.  
  1106.   /* FAAD - $DA66 - add FR0 and FR1 and exit to FNME ($D9E7) */
  1107.  
  1108.   op12:
  1109.     clr.w   REGA
  1110.     clr.w   REGX
  1111.     clr.w   REGY
  1112.     move.w  #0x100,REGEA
  1113.     move.l  REGEA,REGMEA    ; REGMEA = mem[100]
  1114.  
  1115.     move.w  #5,REGX         ; LDX #5
  1116.     move.b  0xFFE0(REGMEA),DBUS   ; LDA FR1
  1117.     andi.w  #0x7F,DBUS
  1118.  
  1119.     move.b  0xFFD4(REGMEA),REGA   ; LDA FR0
  1120.     andi.w  #0x7F,REGA
  1121.  
  1122.     sub.w   DBUS,REGA
  1123.     bpl     frobig
  1124.  
  1125.     addi.w  #5,REGA
  1126.     move.b  REGA,REGY
  1127.  
  1128.     ori.w   #BITX,REGST
  1129.     move.b  REGST,CCR           ; SEC
  1130.     ori.w   #BITD,REGST         ; SED
  1131.  
  1132.     move.b  0xFFE0(REGMEA),DBUS
  1133.     move.b  0xFFD4(REGMEA),REGA
  1134.     eor.w   DBUS,REGA
  1135.     bmi     fdif0
  1136.  
  1137.     andi.w  #~BITX,REGST
  1138.     move.b  REGST,CCR           ; CLC
  1139.  
  1140.     subi.w  #1,REGY             ; DEY
  1141.     bmi     fadd1
  1142.  
  1143.   fadd0:
  1144.     move.b  0xD5(REGMEA,REGY.w),REGA ; LDA FR0+1,Y
  1145.     move.b  0xE0(REGMEA,REGX.w),DBUS ; ADC FR1,X
  1146.     abcd    DBUS,REGA
  1147.     move.w  SR,REGST
  1148.     move.b  REGA,0xD4(REGMEA,REGX.w) ; STA FR0,X
  1149.  
  1150.     sub.b   #1,REGX             ; DEX
  1151.     sub.b   #1,REGY             ; DEY
  1152.     bpl.s   fadd0
  1153.  
  1154.   fadd1:
  1155.     move.b  0xE0(REGMEA,REGX.w),REGA ; LDA FR1,X
  1156.     clr.w   DBUS
  1157.     abcd    DBUS,REGA
  1158.     move.w  SR,REGST
  1159.     move.b  REGA,0xD4(REGMEA,REGX.w) ; STA FR0,X
  1160.  
  1161.     sub.b   #1,REGX             ; DEX
  1162.     bne.s   fadd1               ; BNE FADD1
  1163.  
  1164.     move.b  0xFFE0(REGMEA),0xFFD4(REGMEA) ; LDA FR1  STA FRO
  1165.  
  1166.   fhtst:
  1167.     move.b  REGST,CCR
  1168.     bcc     faddx            ; BCC FADDX
  1169.  
  1170.   fadd2:
  1171.     move.b  0xFFD8(REGMEA),0xFFD9(REGMEA)
  1172.     move.b  0xFFD7(REGMEA),0xFFD8(REGMEA)
  1173.     move.b  0xFFD6(REGMEA),0xFFD7(REGMEA)
  1174.     move.b  0xFFD5(REGMEA),0xFFD6(REGMEA)
  1175.  
  1176.     move.b  #1,0xFFD5(REGMEA)
  1177.     move.b  0xFFD4(REGMEA),REGA
  1178.  
  1179.     move.b  REGA,DBUS
  1180.     add.b   #1,DBUS
  1181.     move.b  DBUS,0xFFD4(REGMEA)
  1182.     eor.b   DBUS,REGA
  1183.     bmi     faddx            ; C is set
  1184.     andi.w  #~BITX,REGST     ; CLC
  1185.  
  1186.   faddx:
  1187.     andi.w  #~BITD,REGST     ; CLD
  1188.     bra     op60
  1189.  
  1190.   frobig:
  1191.     not.b   REGA        ; EOR #$FF
  1192.     addi.b  #5,REGA
  1193.     bcc     fnml
  1194.  
  1195.     ori.w   #BITX,REGST
  1196.     move.b  REGST,CCR            ; SEC
  1197.  
  1198.     move.b  REGA,REGY   ; TAY
  1199.     ori.w   #BITD,REGST         ; SED
  1200.     move.b  0xFFE0(REGMEA),DBUS
  1201.     move.b  0xFFD4(REGMEA),REGA
  1202.     eor.b   DBUS,REGA
  1203.     bmi     fdif5
  1204.  
  1205.     andi.w  #~BITX,REGST
  1206.     move.b  REGST,CCR            ; CLC
  1207.  
  1208.   fadd5:
  1209.     move.b  0xD4(REGMEA,REGX.w),REGA    ; LDA FRO,X
  1210.     move.b  0xE1(REGMEA,REGY.w),DBUS    ; ADC FR1+1,Y
  1211.     abcd    DBUS,REGA
  1212.     move.w  SR,REGST
  1213.     move.b  REGA,0xD4(REGMEA,REGX.w)    ; STA FR0,X
  1214.     subi.b  #1,REGX         ; DEX
  1215.     subi.b  #1,REGY         ; DEY
  1216.     bpl.s   fadd5
  1217.  
  1218.   fadd6:
  1219.     subi.b  #1,REGX         ; DEX
  1220.     bmi     fhtst
  1221.     move.b  0xD5(REGMEA,REGX.w),REGA    ; LDA FRO+1,X
  1222.     clr.w   DBUS
  1223.     abcd    DBUS,REGA
  1224.     move.w  SR,REGST
  1225.     move.b  REGA,0xD5(REGMEA,REGX.w)    ; STA FR0+1,X
  1226.     move.b  REGST,SR
  1227.     bcs     fadd6
  1228.     bra     faddx
  1229.  
  1230.   fdif0:
  1231.     move.w  #0xDAB5,REGPC
  1232.     move.l  REGPC,REGMPC
  1233.     DISPATCH
  1234.  
  1235.   fdif5:
  1236.     move.w  #0xD9BA,REGPC
  1237.     move.l  REGPC,REGMPC
  1238.     DISPATCH
  1239.  
  1240.  
  1241.   op22:
  1242.   op32:
  1243.   op42:
  1244.  
  1245.   /* unused opcodes which can be put to good use as patches */
  1246.  
  1247.   op80:
  1248.   op52:
  1249.   op62:
  1250.   op72:
  1251.   op82:
  1252.   op92:
  1253.   opB2:
  1254.   opC2:
  1255.   opD2:
  1256.   opE2:
  1257.   opF2:
  1258.   op03:
  1259.   op13:
  1260.   op23:
  1261.   op33:
  1262.   op43:
  1263.   op53:
  1264.   op63:
  1265.   op73:
  1266.   op83:
  1267.   op93:
  1268.   opA3:
  1269.   opB3:
  1270.   opC3:
  1271.   opD3:
  1272.   opE3:
  1273.   opF3:
  1274.   op04:
  1275.   op14:
  1276.   op34:
  1277.   op44:
  1278.   op54:
  1279.   op64:
  1280.   op74:
  1281.   opD4:
  1282.   opF4:
  1283.   op07:
  1284.   op17:
  1285.   op27:
  1286.   op37:
  1287.   op47:
  1288.   op57:
  1289.   op67:
  1290.   op77:
  1291.   op87:
  1292.   op97:
  1293.   opA7:
  1294.   opB7:
  1295.   opC7:
  1296.   opD7:
  1297.   opE7:
  1298.   opF7:
  1299.   op89:
  1300.   op1A:
  1301.   op3A:
  1302.   op5A:
  1303.   op7A:
  1304.   opDA:
  1305.   opEA:
  1306.   opFA:
  1307.   op0B:
  1308.   op1B:
  1309.   op2B:
  1310.   op3B:
  1311.   op4B:
  1312.   op5B:
  1313.   op6B:
  1314.   op7B:
  1315.   op8B:
  1316.   op9B:
  1317.   opAB:
  1318.   opBB:
  1319.   opCB:
  1320.   opDB:
  1321.   opEB:
  1322.   opFB:
  1323.   op1C:
  1324.   op3C:
  1325.   op5C:
  1326.   op7C:
  1327.   op9C:
  1328.   opDC:
  1329.   opFC:
  1330.   op9E:
  1331.   op8F:
  1332.   op9F:
  1333.   opAF:
  1334.   opBF:
  1335.   opCF:
  1336.   opDF:
  1337.   opEF:
  1338.   opFF: DISPATCH
  1339.  
  1340.   }
  1341.  }
  1342.  
  1343.  
  1344. plot_0 (scan, height)          /* clear scan lines */
  1345. register int scan, height ; {  /* height black scan lines */
  1346.  
  1347.   register long *loc;
  1348.   register int clong;
  1349.  
  1350.   loc = (long *)scr_emul + (long)((scan<<5)+(scan<<3));
  1351.   clong=(height<<3)+height+height;   /* height * 10 */
  1352.  
  1353.   for (;clong--; *loc++ = *loc++ = *loc++ = *loc++ = 0L) ;
  1354.  }
  1355.  
  1356.  
  1357. plot_1 (scan, height)          /* clear bit planes 2 & 3  */
  1358. register int scan, height ;    /* height black scan lines */
  1359.   {
  1360.   register long *loc;
  1361.   register int clong;
  1362.  
  1363.   loc = (long *)scr_emul + (long)mul40[scan] ;
  1364.   clong= (height<<4)+(height<<2);     /* multiply * 20 bit planes per line */
  1365.  
  1366.   for (;clong--; loc++, *loc++ = 0L) ;
  1367.  }
  1368.  
  1369.                         /* plot a 40 column character using ROM B font */
  1370. plot_2 (data,scry, scrx,count)
  1371. register char *data;
  1372. register int scry, scrx, count ;
  1373.    {
  1374.   register int text;
  1375.   register char *newscr;
  1376.   char *newfont ;        /* unused - use A1 */
  1377.  
  1378.   if (gtia) return;
  1379.  
  1380.   asm {
  1381. ; scry=mul160[scry];       /* since we won't change y co-ordinate */
  1382.        LEA     mul160(GLOBAL),A0
  1383.        ADD.W   scry,scry
  1384.        ADDA.W  scry,A0
  1385.        MOVE.W  (A0),scry
  1386.  
  1387. ; while (count--)
  1388.   loop_2:
  1389. ;      text = *data++ *8;
  1390.        MOVE.W  #0,text
  1391.        MOVE.B  (data)+,text
  1392.        ADD.W   text,text
  1393.        ADD.W   text,text
  1394.        ADD.W   text,text
  1395. ;      newfont = &norm_font[text^0x400] ;
  1396.        EORI.W  #0x400,text
  1397.        LEA     norm_font(GLOBAL),Rnewfont
  1398.        ADDA.W  text,Rnewfont
  1399. ;      newscr = scr_emul + scry + (scrx&1) + ((scrx&~1)<<2) ;
  1400.        MOVE.W  scrx,D0
  1401.        ANDI.W  #1,D0
  1402.        MOVE.W  scrx,D1
  1403.        ANDI.W  #~1,D1
  1404.        ADD.W   D1,D1
  1405.        ADD.W   D1,D1
  1406.        ADD.W   D1,D0
  1407.        ADD.W   scry,D0
  1408.        MOVE.L  scr_emul(GLOBAL),newscr
  1409.        ADDA.W  D0,newscr
  1410.  
  1411.        MOVE.B  #~0,D0
  1412.        MOVE.B  (Rnewfont)+,(newscr)
  1413.        MOVE.B  D0,2(newscr)
  1414.        MOVE.B  (Rnewfont)+,160(newscr)
  1415.        MOVE.B  D0,162(newscr)
  1416.        MOVE.B  (Rnewfont)+,320(newscr)
  1417.        MOVE.B  D0,322(newscr)
  1418.        MOVE.B  (Rnewfont)+,480(newscr)
  1419.        MOVE.B  D0,482(newscr)
  1420.        MOVE.B  (Rnewfont)+,640(newscr)
  1421.        MOVE.B  D0,642(newscr)
  1422.        MOVE.B  (Rnewfont)+,800(newscr)
  1423.        MOVE.B  D0,802(newscr)
  1424.        MOVE.B  (Rnewfont)+,960(newscr)
  1425.        MOVE.B  D0,962(newscr)
  1426.        MOVE.B  (Rnewfont)+,1120(newscr)
  1427.        MOVE.B  D0,1122(newscr)
  1428.        ADDQ.W  #1,scrx        ; scrx++ ;
  1429.        SUB.W   #1,count
  1430.        BNE     loop_2
  1431.        }
  1432.  }
  1433.  
  1434.  
  1435.                         /* plot a 40 column character in 10 pixels */
  1436.  
  1437. plot_3 (data,scry, scrx,count)
  1438. char *data;
  1439. register int scry, scrx, count ;
  1440.    {
  1441.   register int text;
  1442.   register char *newscr;
  1443.   register char *newfont ;
  1444.  
  1445.   if (gtia) return;
  1446.  
  1447.   while (count--)
  1448.     {
  1449.       text = *data++;
  1450.       text &= 0xFF ;     /* character was signed, so unsign it */
  1451.  
  1452.   asm {
  1453.    ADD.W   text,text
  1454.    ADD.W   text,text
  1455.    ADD.W   text,text   /* text *= 8 */
  1456.    }
  1457.  
  1458.         newscr=scr_emul+mul160[scry]+(scrx&1)+((scrx&~1)<<2) ;
  1459.         newfont = &norm_font[text^0x400] ;
  1460.  
  1461.         newscr[1282]=newscr[1442]=
  1462.         newscr[002]= newscr[162]= newscr[322]= newscr[482]=
  1463.         newscr[642]= newscr[802]= newscr[962]= newscr[1122]=~0;
  1464.         newscr[000]=*newfont++;
  1465.         newscr[160]=*newfont++;
  1466.         newscr[320]=*newfont++;
  1467.         newscr[480]=*newfont++;
  1468.         newscr[640]=*newfont++;
  1469.         newscr[800]=*newfont++;
  1470.         newscr[960]=*newfont++;
  1471.         newscr[1120]=*newfont;
  1472.         newscr[1280]=newscr[1440]=~0;
  1473.         scrx++ ;
  1474.    }
  1475.  }
  1476.  
  1477.   /* 4 color text modes */
  1478.  
  1479. plot_4(data, scry, scrx, count)
  1480. register char *data;
  1481. register int scry, scrx, count ;
  1482.     {
  1483.   register int text;
  1484.   register char *newscr;
  1485.   char *newfont ;        /* unused - use A1 */
  1486.  
  1487.     if (gtia) return;
  1488.     while (count--)
  1489.         {
  1490.         text = *data++;
  1491.         text &= 0x7F ;     /* ignore hi bit */
  1492.  
  1493.     asm {
  1494.         ADD.W   text,text
  1495.         ADD.W   text,text
  1496.         ADD.W   text,text   /* text *= 8 */
  1497.         }
  1498.  
  1499.     newscr=scr_emul+mul160[scry]+(scrx&1)+((scrx&~1)<<2) ;
  1500.     newfont = &norm_font[text] ;
  1501.  
  1502.   asm
  1503.     {
  1504.     move.l   newfont(LOCAL),Rnewfont
  1505.     move.w   #7,D2                  ; 8 scan lines
  1506.   loop_4:
  1507.     move.b   (Rnewfont)+,text
  1508.     move.b   text,D1
  1509.     andi.w   #0x55,D1
  1510.     move.w   D1,D0
  1511.     add.w    D0,D0
  1512.     or.w     D1,D0
  1513.     move.b   D0,(newscr)
  1514.  
  1515.     andi.w   #0xAA,text
  1516.     move.w   text,D0
  1517.     lsr.w    #1,D0
  1518.     or.w     text,D0
  1519.     move.b   D0,2(newscr)
  1520.  
  1521.     lea      160(newscr),newscr
  1522.     dbf      D2,loop_4
  1523.     }
  1524.         scrx++ ;
  1525.         }
  1526.     }
  1527.  
  1528. plot_5(data, scry, scrx, count)
  1529. register char *data;
  1530. register int scry, scrx, count ;
  1531.     {
  1532.   register int text;
  1533.   register char *newscr;
  1534.   char *newfont ;        /* unused - use A1 */
  1535.  
  1536.     if (gtia) return;
  1537.     while (count--)
  1538.         {
  1539.         text = *data++;
  1540.         text &= 0x7F ;     /* ignore hi bit */
  1541.  
  1542.     asm {
  1543.         ADD.W   text,text
  1544.         ADD.W   text,text
  1545.         ADD.W   text,text   /* text *= 8 */
  1546.         }
  1547.  
  1548.         newscr=scr_emul+mul160[scry]+(scrx&1)+((scrx&~1)<<2) ;
  1549.         newfont = &norm_font[text] ;
  1550.  
  1551.   asm
  1552.     {
  1553.     move.l   newfont(LOCAL),Rnewfont
  1554.     move.w   #7,D2                  ; 8 unique scan lines
  1555.   loop_5:
  1556.     move.b   (Rnewfont)+,text
  1557.     move.b   text,D1
  1558.     andi.w   #0x55,D1
  1559.     move.w   D1,D0
  1560.     add.w    D0,D0
  1561.     or.w     D1,D0
  1562.     move.b   D0,(newscr)
  1563.     move.b   D0,160(newscr)
  1564.  
  1565.     andi.w   #0xAA,text
  1566.     move.w   text,D0
  1567.     lsr.w    #1,D0
  1568.     or.w     text,D0
  1569.     move.b   D0,2(newscr)           ; do 2 scan lines at once
  1570.     move.b   D0,162(newscr)
  1571.  
  1572.     lea      320(newscr),newscr     ; skip 2 lines
  1573.     dbf      D2,loop_5
  1574.     }
  1575.         scrx++ ;
  1576.         }
  1577.     }
  1578.  
  1579.  
  1580.   /* plot a 20 column character */
  1581.  
  1582. plot_6(data, scry, scrx, count)
  1583. char *data;
  1584. register int scry, scrx, count ;
  1585.    {
  1586.   register int text;
  1587.   register int *newscr ;
  1588.   register int *newfont ;
  1589.  
  1590.   if (gtia) return;
  1591.  
  1592.   while (count--) {
  1593.   asm
  1594.         {
  1595. ;  text = *data++ + 64; /* add 64 to select colours 1-4, not 0-3 */
  1596.         clr.w   text
  1597.         move.l  data(LOCAL),A0
  1598.         move.b  (A0)+,text
  1599.         move.l  A0,data(LOCAL)
  1600.         add.w   #64,text
  1601.         ADD.W   text,text
  1602.         ADD.W   text,text
  1603.         ADD.W   text,text   /* text *= 8 */
  1604.         }
  1605.  
  1606.   newscr = (int *) scr_emul + mul80[scry] + (scrx<<2) ;
  1607.   newfont = &wide_font[(text&0x01F8)];  /* ignore color bits */
  1608.  
  1609.   if (text&0x200)
  1610.   asm {
  1611.     move.l  newfont,A0
  1612.     move.w  (A0)+,(newscr)
  1613.     move.w  (A0)+,160(newscr)
  1614.     move.w  (A0)+,320(newscr)
  1615.     move.w  (A0)+,480(newscr)
  1616.     move.w  (A0)+,640(newscr)
  1617.     move.w  (A0)+,800(newscr)
  1618.     move.w  (A0)+,960(newscr)
  1619.     move.w  (A0),1120(newscr)
  1620.     }
  1621.   else
  1622.   asm {
  1623.     clr.w   (newscr)
  1624.     clr.w   160(newscr)
  1625.     clr.w   320(newscr)
  1626.     clr.w   480(newscr)
  1627.     clr.w   640(newscr)
  1628.     clr.w   800(newscr)
  1629.     clr.w   960(newscr)
  1630.     clr.w   1120(newscr)
  1631.     }
  1632.  
  1633.   if (text&0x400)
  1634.    asm {
  1635.     move.l  newfont,A0
  1636.     move.w  (A0)+,2(newscr)
  1637.     move.w  (A0)+,162(newscr)
  1638.     move.w  (A0)+,322(newscr)
  1639.     move.w  (A0)+,482(newscr)
  1640.     move.w  (A0)+,642(newscr)
  1641.     move.w  (A0)+,802(newscr)
  1642.     move.w  (A0)+,962(newscr)
  1643.     move.w  (A0),1122(newscr)
  1644.     }
  1645.   else
  1646.    asm {
  1647.     clr.w   2(newscr)
  1648.     clr.w   162(newscr)
  1649.     clr.w   322(newscr)
  1650.     clr.w   482(newscr)
  1651.     clr.w   642(newscr)
  1652.     clr.w   802(newscr)
  1653.     clr.w   962(newscr)
  1654.     clr.w   1122(newscr)
  1655.     }
  1656.  
  1657.   if (text&0x800)
  1658.    asm {
  1659.     move.l  newfont,A0
  1660.     move.w  (A0)+,4(newscr)
  1661.     move.w  (A0)+,164(newscr)
  1662.     move.w  (A0)+,324(newscr)
  1663.     move.w  (A0)+,484(newscr)
  1664.     move.w  (A0)+,644(newscr)
  1665.     move.w  (A0)+,804(newscr)
  1666.     move.w  (A0)+,964(newscr)
  1667.     move.w  (A0),1124(newscr)
  1668.     }
  1669.   else
  1670.    asm {
  1671.     clr.w   4(newscr)
  1672.     clr.w   164(newscr)
  1673.     clr.w   324(newscr)
  1674.     clr.w   484(newscr)
  1675.     clr.w   644(newscr)
  1676.     clr.w   804(newscr)
  1677.     clr.w   964(newscr)
  1678.     clr.w   1124(newscr)
  1679.     }
  1680.  
  1681.             /* clear out bit plane 3 */
  1682.   asm {
  1683.     clr.w   6(newscr)
  1684.     clr.w   166(newscr)
  1685.     clr.w   326(newscr)
  1686.     clr.w   486(newscr)
  1687.     clr.w   646(newscr)
  1688.     clr.w   806(newscr)
  1689.     clr.w   966(newscr)
  1690.     clr.w   1126(newscr)
  1691.     }
  1692.    scrx++ ;
  1693.    }
  1694.  }
  1695.  
  1696. plot_7(data, scry, scrx, count)
  1697. char *data;
  1698. register int scry, scrx, count ;
  1699.    {
  1700.   register int text;
  1701.   register int *newscr ;
  1702.   register int *newfont ;
  1703.  
  1704.   if (gtia) return;
  1705.  
  1706.   while (count--)
  1707.       {
  1708.   asm
  1709.     {
  1710. ;  text = *data++ + 64; /* add 64 to select colours 1-4, not 0-3 */
  1711.     clr.w   text
  1712.     move.l  data(LOCAL),A0
  1713.     move.b  (A0)+,text
  1714.     move.l  A0,data(LOCAL)
  1715.     add.w   #64,text
  1716.     ADD.W   text,text
  1717.     ADD.W   text,text
  1718.     ADD.W   text,text   /* text *= 8 */
  1719.     }
  1720.  
  1721.   newscr = (int *) scr_emul + mul80[scry] + (scrx<<2) ;
  1722.   newfont = &wide_font[(text&0x01F8)];  /* ignore color bits */
  1723.  
  1724.   if (text&0x200)
  1725.      {
  1726.      newfont = &wide_font[(text&0x01F8)];     /* ignore color bits */
  1727.      newscr[000]= newscr[80]=*newfont++;
  1728.      newscr[160]= newscr[240]=*newfont++;
  1729.      newscr[320]= newscr[400]=*newfont++;
  1730.      newscr[480]= newscr[560]=*newfont++;
  1731.      newscr[640]= newscr[720]=*newfont++;
  1732.      newscr[800]= newscr[880]=*newfont++;
  1733.      newscr[960]= newscr[1040]=*newfont++;
  1734.      newscr[1120]= newscr[1200]=*newfont;
  1735.      }
  1736.   else
  1737.   asm
  1738.     {
  1739.     clr.w   0(newscr)
  1740.     clr.w   160(newscr)
  1741.     clr.w   320(newscr)
  1742.     clr.w   480(newscr)
  1743.     clr.w   640(newscr)
  1744.     clr.w   800(newscr)
  1745.     clr.w   960(newscr)
  1746.     clr.w   1120(newscr)
  1747.     clr.w   1280(newscr)
  1748.     clr.w   1440(newscr)
  1749.     clr.w   1600(newscr)
  1750.     clr.w   1760(newscr)
  1751.     clr.w   1920(newscr)
  1752.     clr.w   2080(newscr)
  1753.     clr.w   2240(newscr)
  1754.     clr.w   2400(newscr)
  1755.     }
  1756.  
  1757.   if (text&0x400)
  1758.      {
  1759.      newfont = &wide_font[(text&0x01F8)];     /* ignore color bits */
  1760.      newscr[001]= newscr[81]=*newfont++;
  1761.      newscr[161]= newscr[241]=*newfont++;
  1762.      newscr[321]= newscr[401]=*newfont++;
  1763.      newscr[481]= newscr[561]=*newfont++;
  1764.      newscr[641]= newscr[721]=*newfont++;
  1765.      newscr[801]= newscr[881]=*newfont++;
  1766.      newscr[961]= newscr[1041]=*newfont++;
  1767.      newscr[1121]= newscr[1201]=*newfont;
  1768.      }
  1769.   else
  1770.   asm
  1771.     {
  1772.     clr.w   2(newscr)
  1773.     clr.w   162(newscr)
  1774.     clr.w   322(newscr)
  1775.     clr.w   482(newscr)
  1776.     clr.w   642(newscr)
  1777.     clr.w   802(newscr)
  1778.     clr.w   962(newscr)
  1779.     clr.w   1122(newscr)
  1780.     clr.w   1282(newscr)
  1781.     clr.w   1442(newscr)
  1782.     clr.w   1602(newscr)
  1783.     clr.w   1762(newscr)
  1784.     clr.w   1922(newscr)
  1785.     clr.w   2082(newscr)
  1786.     clr.w   2242(newscr)
  1787.     clr.w   2402(newscr)
  1788.     }
  1789.  
  1790.   if (text&0x800)
  1791.      {
  1792.      newfont = &wide_font[(text&0x01F8)];     /* ignore color bits */
  1793.      newscr[002]= newscr[82]=*newfont++;
  1794.      newscr[162]= newscr[242]=*newfont++;
  1795.      newscr[322]= newscr[402]=*newfont++;
  1796.      newscr[482]= newscr[562]=*newfont++;
  1797.      newscr[642]= newscr[722]=*newfont++;
  1798.      newscr[802]= newscr[882]=*newfont++;
  1799.      newscr[962]= newscr[1042]=*newfont++;
  1800.      newscr[1122]= newscr[1202]=*newfont;
  1801.      }
  1802.   else
  1803.   asm
  1804.     {
  1805.     clr.w   4(newscr)
  1806.     clr.w   164(newscr)
  1807.     clr.w   324(newscr)
  1808.     clr.w   484(newscr)
  1809.     clr.w   644(newscr)
  1810.     clr.w   804(newscr)
  1811.     clr.w   964(newscr)
  1812.     clr.w   1124(newscr)
  1813.     clr.w   1284(newscr)
  1814.     clr.w   1444(newscr)
  1815.     clr.w   1604(newscr)
  1816.     clr.w   1764(newscr)
  1817.     clr.w   1924(newscr)
  1818.     clr.w   2084(newscr)
  1819.     clr.w   2244(newscr)
  1820.     clr.w   2404(newscr)
  1821.     }
  1822.             /* clear out bit plane 3 */
  1823.   asm
  1824.     {
  1825.     clr.w   6(newscr)
  1826.     clr.w   166(newscr)
  1827.     clr.w   326(newscr)
  1828.     clr.w   486(newscr)
  1829.     clr.w   646(newscr)
  1830.     clr.w   806(newscr)
  1831.     clr.w   966(newscr)
  1832.     clr.w   1126(newscr)
  1833.     clr.w   1286(newscr)
  1834.     clr.w   1446(newscr)
  1835.     clr.w   1606(newscr)
  1836.     clr.w   1766(newscr)
  1837.     clr.w   1926(newscr)
  1838.     clr.w   2086(newscr)
  1839.     clr.w   2246(newscr)
  1840.     clr.w   2406(newscr)
  1841.     }
  1842.    scrx++ ;
  1843.    }
  1844.  }
  1845.  
  1846. /* for mode 8 (GR.3), each byte is 4 pixels, which appear as 4 8 pixel boxes */
  1847. /* Therefore 2 pixels are stored as 2 long words, with planes 0 and 1 in the */
  1848. /* first, and planes 2 and 3 in the seconds. The following lookup table has */
  1849. /* the masks for the 16 color combinations of 2 pixels */
  1850.  
  1851. long mode8_planes[16] = {
  1852.     0x00000000L, 0x00FF0000L, 0x000000FFL, 0x00FF00FFL,
  1853.     0xFF000000L, 0xFFFF0000L, 0xFF0000FFL, 0xFFFF00FFL,
  1854.     0x0000FF00L, 0x00FFFF00L, 0x0000FFFFL, 0x00FFFFFFL,
  1855.     0xFF00FF00L, 0xFFFFFF00L, 0xFF00FFFFL, 0xFFFFFFFFL } ;
  1856.  
  1857. plot_8(data, scry, scrx, count)
  1858. register char *data;
  1859. register int scry, scrx, count ;
  1860.  {
  1861.   register int text;
  1862.   register long *newscr;
  1863.  
  1864.   if (gtia) return;
  1865.  
  1866.   while (count--) {
  1867.         text = *data++;
  1868.         newscr = (long *)scr_emul + mul40[scry] + (scrx<<2) ;
  1869.                                            /* do left 2 pixels */
  1870.         newscr[0] = newscr[40] = newscr[80] = newscr[120] =
  1871.         newscr[160] = newscr[200] = newscr[240] = newscr[280] =
  1872.         mode8_planes[(text>>4)&0x0F] ;
  1873.                                           /* do right two pixels */
  1874.         newscr[2] = newscr[42] = newscr[82] = newscr[122] =
  1875.         newscr[162] = newscr[202] = newscr[242] = newscr[282] =
  1876.         mode8_planes[text&0x0F] ;
  1877.  
  1878.         scrx++ ;
  1879.    }
  1880.  }
  1881.  
  1882. plot_9(data, scry, scrx, count)
  1883. register char *data;
  1884. register int scry, scrx, count ;
  1885.    {
  1886.    register long *newscr;
  1887.  
  1888.    if (gtia) return;
  1889.    while (count--)
  1890.        {
  1891.        newscr = (long *)scr_emul + mul40[scry] + (scrx<<2) ;
  1892.   asm
  1893.     {
  1894. ; since GR.4 and GR.5 have the same horizontal resolution as GTIA, use the same
  1895. ; brute force routine to plot the pixels
  1896.  
  1897.     clr.l    4(newscr)          ; clear bit planes 2 & 3
  1898.     clr.l    12(newscr)
  1899.     clr.l    164(newscr)
  1900.     clr.l    172(newscr)
  1901.     clr.l    324(newscr)
  1902.     clr.l    332(newscr)
  1903.     clr.l    484(newscr)
  1904.     clr.l    492(newscr)
  1905.     move.b   (data)+,D0
  1906.  
  1907.     clr.l    D1
  1908.     btst     #0,D0
  1909.     beq.s    p91
  1910.     move.l   #0x000F0000,D1
  1911.   p91:
  1912.     btst     #1,D0
  1913.     beq.s    p92
  1914.     ori.l    #0x00F00000,D1
  1915.   p92:
  1916.     btst     #2,D0
  1917.     beq.s    p94
  1918.     ori.l    #0x0F000000,D1
  1919.   p94:
  1920.     btst     #3,D0
  1921.     beq.s    p98
  1922.     ori.l    #0xF0000000,D1
  1923.   p98:
  1924.     move.l   D1,8(newscr)
  1925.     move.l   D1,168(newscr)
  1926.     move.l   D1,328(newscr)
  1927.     move.l   D1,488(newscr)
  1928.     clr.l    D1
  1929.     btst     #4,D0
  1930.     beq.s    p910
  1931.     move.l   #0x000F0000,D1
  1932.   p910:
  1933.     btst     #5,D0
  1934.     beq.s    p920
  1935.     ori.l    #0x00F00000,D1
  1936.   p920:
  1937.     btst     #6,D0
  1938.     beq.s    p940
  1939.     ori.l    #0x0F000000,D1
  1940.   p940:
  1941.     btst     #7,D0
  1942.     beq.s    p9
  1943.     ori.l    #0xF0000000,D1
  1944.   p9:
  1945.     move.l   D1,(newscr)
  1946.     move.l   D1,160(newscr)
  1947.     move.l   D1,320(newscr)
  1948.     move.l   D1,480(newscr)
  1949.     add.w    #1,scrx
  1950.     }
  1951.         }
  1952.     }
  1953.  
  1954. plot_A(data, scry, scrx, count)
  1955. register char *data;
  1956. register int scry, scrx, count ;
  1957.    {
  1958.    register long *newscr;
  1959.  
  1960.    if (gtia) return;
  1961.    while (count--)
  1962.        {
  1963.        newscr = (long *)scr_emul + mul40[scry] + (scrx<<1) ;
  1964.   asm
  1965.     {
  1966.     clr.l    4(newscr)          ; clear bit planes 2 & 3
  1967.     clr.l    12(newscr)
  1968.     clr.l    164(newscr)
  1969.     clr.l    172(newscr)
  1970.     clr.l    324(newscr)
  1971.     clr.l    332(newscr)
  1972.     clr.l    484(newscr)
  1973.     clr.l    492(newscr)
  1974.     move.b   (data)+,D0
  1975.  
  1976.     clr.l    D1
  1977.     btst     #0,D0
  1978.     beq.s    pA1
  1979.     move.l   #0x000F0000,D1
  1980.   pA1:
  1981.     btst     #1,D0
  1982.     beq.s    pA2
  1983.     ori.l    #0x0000000F,D1
  1984.   pA2:
  1985.     btst     #2,D0
  1986.     beq.s    pA4
  1987.     ori.l    #0x00F00000,D1
  1988.   pA4:
  1989.     btst     #3,D0
  1990.     beq.s    pA8
  1991.     ori.l    #0x000000F0,D1
  1992.   pA8:
  1993.     btst     #4,D0
  1994.     beq.s    pA10
  1995.     ori.l    #0x0F000000,D1
  1996.   pA10:
  1997.     btst     #5,D0
  1998.     beq.s    pA20
  1999.     ori.l    #0x00000F00,D1
  2000.   pA20:
  2001.     btst     #6,D0
  2002.     beq.s    pA40
  2003.     ori.l    #0xF0000000,D1
  2004.   pA40:
  2005.     btst     #7,D0
  2006.     beq.s    pA
  2007.     ori.l    #0x0000F000,D1
  2008.   pA:
  2009.     move.l   D1,(newscr)
  2010.     move.l   D1,160(newscr)
  2011.     move.l   D1,320(newscr)
  2012.     move.l   D1,480(newscr)
  2013.     add.w    #1,scrx
  2014.     }
  2015.         }
  2016.     }
  2017.  
  2018.                           /* plot a GR.6 byte - just do two 6+ plots */
  2019. plot_B(data, scry, scrx, count)
  2020. register char *data;
  2021. register int scry, scrx, count ;
  2022.    {
  2023.    if (gtia) return;
  2024.      plot_C (data,scry,scrx,count) ;
  2025.      plot_C (data,++scry,scrx,count) ;
  2026.   }
  2027.                                          /* plot a GR.6+ byte */
  2028. /* for mode C (GR.6), each byte is 8 pixels, which appear as 8 2 pixel boxes */
  2029. /* Therefore 8 pixels are stored as 4 ints, with planes 0 and 1 in the */
  2030. /* first 2, and planes 2 and 3 in last 2. Since it is mono, planes 1 & 2 & 3 */
  2031. /* are clear and plane 0 gets the value of the byte stretched to a wide_byte */
  2032.  
  2033. plot_C(data, scry, scrx, count)
  2034. register char *data;
  2035. register int scry, scrx, count ;
  2036.  {
  2037.   register int text;
  2038.   register int *newscr;
  2039.  
  2040.    if (gtia) return;
  2041.   while (count--) {
  2042.         text = *data++;
  2043.         newscr = (int *) scr_emul +  mul80[scry] + (scrx<<2) ;
  2044.         *newscr++ = wide_byte[text&0xFF] ;
  2045.         *newscr = 0 ;
  2046.         scrx++ ;
  2047.    }
  2048.  
  2049.  }
  2050.  
  2051. plot_D(data, scry, scrx, count)
  2052. register char *data;
  2053. register int scry, scrx, count ;
  2054.  {
  2055.   register int text;
  2056.   register char *newscr;
  2057.  
  2058.    if (gtia) return;
  2059.   while (count--) {
  2060.         newscr = scr_emul + mul160[scry] + (scrx&1) + ((scrx&~1)<<2) ;
  2061.         asm
  2062.                 {
  2063.                 move.b   (data)+,text
  2064.                 move.b   text,D1
  2065.                 andi.w   #0x55,D1
  2066.                 move.w   D1,D0
  2067.                 add.w    D0,D0
  2068.                 or.w     D1,D0
  2069.                 move.b   D0,(newscr)
  2070.                 move.b   D0,160(newscr)
  2071.  
  2072.                 andi.w   #0xAA,text
  2073.                 move.w   text,D0
  2074.                 lsr.w    #1,D0
  2075.                 or.w     text,D0
  2076.                 move.b   D0,2(newscr)
  2077.                 move.b   D0,162(newscr)
  2078.  
  2079.                 add.w    #1,scrx
  2080.                 }
  2081.    }
  2082.  }
  2083.  
  2084. plot_E(data, scry, scrx, count)
  2085. register char *data;
  2086. register int scry, scrx, count ;
  2087.  {
  2088.   register int text;
  2089.   register char *newscr;
  2090.  
  2091.    if (gtia) return;
  2092.   while (count--) {
  2093.         newscr = scr_emul + mul160[scry] + (scrx&1) + ((scrx&~1)<<2) ;
  2094.         asm
  2095.                 {
  2096.                 move.b   (data)+,text
  2097.                 move.b   text,D1
  2098.                 andi.w   #0x55,D1
  2099.                 move.w   D1,D0
  2100.                 add.w    D0,D0
  2101.                 or.w     D1,D0
  2102.                 move.b   D0,(newscr)
  2103.  
  2104.                 andi.w   #0xAA,text
  2105.                 move.w   text,D0
  2106.                 lsr.w    #1,D0
  2107.                 or.w     text,D0
  2108.                 move.b   D0,2(newscr)
  2109.  
  2110.                 add.w    #1,scrx
  2111.                 }
  2112.    }
  2113.  }
  2114.  
  2115.                              /* plot a GR.8 byte */
  2116.  
  2117. plot_F(data, scry, scrx, count)
  2118. register char *data;
  2119. register int scry, scrx, count ;
  2120.   {
  2121.   register char *newscr;
  2122.  
  2123.   if (gtia)
  2124.       {
  2125.       while (count--)
  2126.           {
  2127.           newscr = scr_emul + mul160[scry] + (scrx&1) + ((scrx&~1)<<2) ;
  2128.           asm
  2129.             {
  2130.             clr.b    (newscr)
  2131.             clr.b    2(newscr)
  2132.             clr.b    4(newscr)
  2133.             clr.b    6(newscr)
  2134.             move.b   (data)+,D0
  2135.             beq.s    gtia0
  2136.  
  2137.             btst     #0,D0
  2138.             beq.s    gtia01
  2139.             move.b   #15,(newscr)
  2140.   gtia01:
  2141.             btst     #1,D0
  2142.             beq.s    gtia02
  2143.             move.b   #15,2(newscr)
  2144.   gtia02:
  2145.             btst     #2,D0
  2146.             beq.s    gtia04
  2147.             move.b   #15,4(newscr)
  2148.   gtia04:
  2149.             btst     #3,D0
  2150.             beq.s    gtia08
  2151.             move.b   #15,6(newscr)
  2152.   gtia08:
  2153.             btst     #4,D0
  2154.             beq.s    gtia10
  2155.             ori.b    #0xF0,(newscr)
  2156.   gtia10:
  2157.             btst     #5,D0
  2158.             beq.s    gtia20
  2159.             ori.b    #0xF0,2(newscr)
  2160.   gtia20:
  2161.             btst     #6,D0
  2162.             beq.s    gtia40
  2163.             ori.b    #0xF0,4(newscr)
  2164.   gtia40:
  2165.             btst     #7,D0
  2166.             beq.s    gtia0
  2167.             ori.b    #0xF0,6(newscr)
  2168.   gtia0:
  2169.             add.w    #1,scrx
  2170.             }
  2171.           } /* while */
  2172.       }
  2173.   else
  2174.       {
  2175.       while (count--) {
  2176.           newscr = scr_emul + mul160[scry] + (scrx&1) + ((scrx&~1)<<2) ;
  2177.           asm
  2178.             {
  2179.             move.b   (data)+,D0
  2180.             not.w    D0
  2181.             move.b   D0,(newscr)
  2182.             move.w   #~0,D0
  2183.             move.b   D0,2(newscr)
  2184.             clr.b    4(newscr)
  2185.             clr.b    6(newscr)
  2186.             add.w    #1,scrx
  2187.             }
  2188.           } /* while */
  2189.       } /* if gtia */
  2190.  }
  2191.  
  2192. int (*do_plot[16])() = {
  2193.   plot_0, plot_1, plot_2, plot_3, plot_4, plot_5, plot_6, plot_7,
  2194.   plot_8, plot_9, plot_A, plot_B, plot_C, plot_D, plot_E, plot_F } ;
  2195.  
  2196.  
  2197. do_display()
  2198.   {
  2199.   /* redraw the entire screen - does not clear status bytes - just sets them */
  2200.  
  2201.   register char *mdlptr ;  /* pointer to current byte in dlist */
  2202.   register char *pstat;
  2203.   DL *qdl=dlBlocks;
  2204.   int old_mode=-1;
  2205.   unsigned d_loc = 0 ;     /* address of start of scan line */
  2206.   register  int opc,       /* current byte of dl */
  2207.   h_byt,
  2208.   scan_line = 0,     /* current scan line */
  2209.   antic_mode ;
  2210.  
  2211.   if (!gtia)
  2212.       plot_1 (0,200);   /* clear any garbage out of bit planes 2 and 3 */
  2213.  
  2214.   qdl->mode=-1;
  2215.  
  2216.   mdlptr = mem+dl;
  2217.  
  2218.   do
  2219.     {
  2220.     opc = *mdlptr++ & 0x7F ;     /* skip first 24 lines */
  2221.     } while (opc==112) ;
  2222.  
  2223.   mdlptr-- ;
  2224.  
  2225.   do {
  2226.       stat[(int)(mdlptr-mem)] = 64;    /* set status byte of dl byte */
  2227.  
  2228.       antic_mode = (opc = *mdlptr++ & 0x4F) & 0x0F ;
  2229.  
  2230.       if (antic_mode>1)
  2231.           {
  2232.           if (opc&64)
  2233.               {
  2234.               d_loc=(unsigned)(*mdlptr)+((unsigned)(*(mdlptr+1))<<8) ;
  2235.               stat[(int)(mdlptr++ -mem)] = 64;
  2236.               stat[(int)(mdlptr++ -mem)] = 64;
  2237.               if (antic_mode==old_mode)
  2238.                   old_mode=999;              /* force a new DL */
  2239.               }
  2240.           (*do_plot[antic_mode])(mem+d_loc,scan_line,0,phor_bytes[antic_mode]);
  2241.           h_byt=phor_bytes[antic_mode]-1;
  2242.           pstat=&stat[d_loc];
  2243.             {
  2244.             asm {
  2245.   loop_DD:
  2246.     move.b   (pstat)+,D0
  2247.     bne.s    no_stat
  2248.     move.b   #65,-1(pstat)
  2249. no_stat:
  2250.     dbf      h_byt,loop_DD
  2251.                 }
  2252.              } /* for loop */
  2253.           if (antic_mode!=old_mode)
  2254.              {
  2255.              if (old_mode!=-1)
  2256.                  qdl++;
  2257.              old_mode=antic_mode;
  2258.              qdl->mode = antic_mode;
  2259.              qdl->height = scan_table[antic_mode];
  2260.              qdl->width = phor_bytes[antic_mode];
  2261.              qdl->block_size = 0;
  2262.              qdl->start=d_loc;
  2263.              qdl->scan=scan_line;
  2264.              }
  2265.           qdl->block_size += phor_bytes[antic_mode];
  2266.           d_loc += phor_bytes[antic_mode] ;
  2267.  
  2268.           scan_line += scan_table[antic_mode] ;
  2269.           }
  2270.       else if (antic_mode==1)
  2271.           plot_0 (scan_line++,1) ;
  2272.       else
  2273.           {
  2274.           plot_0(scan_line,(opc>>4)+1) ;
  2275.           if (old_mode!=0)
  2276.              {
  2277.              if (old_mode!=-1)
  2278.                  qdl++;
  2279.              old_mode=0;
  2280.              qdl->mode = 0;
  2281.              }
  2282.           scan_line += (opc>>4)+1 ;
  2283.           }
  2284.    } while (opc != 65 && scan_line<196) ;
  2285.  
  2286.    if (scan_line<199)
  2287.         plot_0(scan_line,200-scan_line);
  2288.  
  2289.    (++qdl)->mode=-1;
  2290.    fRedraw=FALSE;
  2291.  }
  2292.  
  2293.  
  2294. do_byte(loc)       /* redraw one byte on the screen */
  2295. register unsigned loc ;
  2296.     {
  2297.     register int antic_mode ;
  2298.     register unsigned int offset;
  2299.     register int scan_line;     /* current scan line */
  2300.     register DL *qdl=dlBlocks;
  2301.  
  2302.     while ((antic_mode = qdl->mode) != -1)
  2303.         {
  2304.         if (antic_mode!=0)
  2305.         if (((offset=loc-(unsigned)(qdl->start))<qdl->block_size))
  2306.             {
  2307.             scan_line = qdl->scan + ((offset)/qdl->width)*qdl->height;
  2308.             (*do_plot[antic_mode])(mem+loc,scan_line,offset%qdl->width,1);
  2309.             }
  2310.         ++qdl;
  2311.         }
  2312.     }
  2313.  
  2314. /* Clear out all status bytes that refer to the screen. About to redraw */
  2315. /* It works by traversing the DL structures and clearing the status bytes */
  2316. /* of all the blocks. A lot faster than the following code: */
  2317. /*    for (ea=0; ++ea;) if (stat[ea]&64) stat[ea]=0; */
  2318.  
  2319. clear_disp()
  2320.     {
  2321.     register int cb;
  2322.     register DL *qdl=dlBlocks;
  2323.     register char *pstat;
  2324.  
  2325.     while (qdl->mode != -1)
  2326.         {
  2327.         if (qdl->mode==0)
  2328.             {
  2329.             qdl++;
  2330.             continue;
  2331.             }
  2332.         cb = qdl->block_size -1;
  2333.         pstat = &stat[qdl->start];
  2334.   asm
  2335.     {
  2336.   loop_clear:
  2337.     move.b  (pstat)+,D0         ; get a status byte
  2338.     cmpi.b  #65,D0              ; is it a screen status byte
  2339.     bne.s   no_clear            ; no
  2340.     clr.b   -1(pstat)           ; otherwise clear it
  2341.   no_clear:
  2342.     dbf     cb,loop_clear       ; while cb--
  2343.     }
  2344.         qdl++;
  2345.         }
  2346.     dlBlocks[0].mode=-1;
  2347.     }
  2348.  
  2349.  
  2350. do_color (ea, byt) unsigned int ea, byt ;
  2351.   {
  2352.   register int temp=*(rainbow+(byt&~1));
  2353.  
  2354.   if (ea==53274)
  2355.       *(int *)0xFFFF8240L=temp;
  2356.   else
  2357.       *(int *)(0xFFFF8240L + (long)((ea-53269)<<1))=temp;
  2358.   }
  2359.  
  2360. do_colors (ea, byt) register unsigned int ea, byt ;
  2361.   {
  2362.   register char *rgch = shadows;
  2363.   register int i;
  2364.  
  2365.   byt &= 254;
  2366.  
  2367.   switch (gtia)
  2368.       {
  2369.   default:                   /* normal mode */
  2370.       if (ea==712)
  2371.           *rgch=byt;
  2372.       else if (ea>707)
  2373.           rgch[ea-707]=byt;
  2374.       break;
  2375.  
  2376.   case 0x80:                 /* GR.10 mode */
  2377.       rgch[ea-704]= byt;
  2378.       break;
  2379.  
  2380.   case 0x40:                   /* GR.9 (16 shades) */
  2381.       if (ea==712)
  2382.           {
  2383.           byt &= 0xF0;
  2384.           for (i=0; i<16; i++)
  2385.               {
  2386.               *rgch++ = byt++;
  2387.               }
  2388.           }
  2389.       break;
  2390.  
  2391.   case 0xC0:                   /* GR.11 (16 colors) */
  2392.       if (ea==712)
  2393.           {
  2394.           byt &= 0x0F;
  2395.           for (i=0; i<16; i++)
  2396.               {
  2397.               *rgch++ = byt;
  2398.               byt += 16;
  2399.               }
  2400.           }
  2401.       break;
  2402.       }
  2403.   }
  2404.  
  2405. do_chset() {
  2406.  
  2407.   register int num8, old ;
  2408.   register char *pchset ;
  2409.  
  2410.   pchset = mem + (unsigned)(*(mem+756))*256 ;
  2411.  
  2412.   for (num8=0 ; num8<1024; num8++) {
  2413.       old = *pchset++ ;
  2414.  
  2415.       norm_font[num8] = old ;
  2416.       norm_font[num8+1024] = ~old ;
  2417.       wide_font[num8] = wide_byte[old] ;
  2418.       wide_font[num8+1024] = ~wide_byte[old] ;
  2419.    }
  2420.   if (dma) fRedraw=TRUE;
  2421.  }
  2422.  
  2423. /* these two routines nuked when put as inline code. WHY??????? arghhh */
  2424.  
  2425. do_open()
  2426.       {
  2427.         char stat;
  2428.         int cch, iocb, iocb16, hand;
  2429.         char ch, aux1, aux2;
  2430.         unsigned int vector;
  2431.  
  2432.         iocb16 = (unsigned) x ;
  2433.         iocb = iocb16/16;
  2434.         vector = (unsigned)mem[0x344+iocb16] + (unsigned)mem[0x345+iocb16]*256;
  2435.         aux1 = mem[0x34A+iocb16];
  2436.  
  2437.         stat=146 ;
  2438.         cch=0;
  2439.  
  2440. /* Parse over the "Dn:" which leaves just the filename */
  2441.         while (*(mem+vector++)!=':')
  2442.            {
  2443.            if (++cch>2)
  2444.                goto Dopen_exit;
  2445.            }
  2446.  
  2447.         cch=0;
  2448.         do {
  2449.            ch = *(mem+vector++);
  2450.            filename[cch++]=ch;
  2451.          } while (cch<15 && ch>32 && ch<91) ;
  2452.         filename[--cch]=0;
  2453.  
  2454.  /* Now check for the special case where the use wants a disk directory. */
  2455.  /* Open a file _.DIR and stuff a DOS 2.0 type directory listing into it. */
  2456.  
  2457.         if (aux1==6)
  2458.             {
  2459.             hand = Fcreate("_.DIR",0);
  2460.             Directory(filename,hand);
  2461.             Fclose(hand);
  2462.             hand = Fopen("_.DIR",0);
  2463.             }
  2464.         else if (aux1&4)
  2465.             hand = Fopen(filename,0);
  2466.         else
  2467.             hand = Fcreate(filename,0);
  2468.  
  2469.         if (hand<0) {
  2470.             if (hand==-33) stat = 170 ;
  2471.             else stat=165;
  2472.            }
  2473.         else {
  2474.             stat = 1 ;
  2475.             DOS_hand[iocb]=hand;
  2476.             DOS_mode[iocb]=aux1;
  2477.           }
  2478.   Dopen_exit:
  2479.         mem[0x4c]=stat;
  2480.         y=stat;
  2481.       }
  2482.  
  2483. do_put()
  2484.       {
  2485.         char stat;
  2486.         int iocb, iocb16, hand;
  2487.         char ch;
  2488.         unsigned cch, vector;
  2489.  
  2490.         ch=a;
  2491.         iocb16 = (unsigned) x ;
  2492.         iocb = iocb16/16;
  2493.  
  2494.         vector = (unsigned)mem[0x24] + (unsigned)mem[0x25]*256;
  2495.         cch = (unsigned)mem[0x28] + (unsigned)mem[0x29]*256;
  2496.  
  2497.         stat=135 ;
  2498.         if (DOS_mode[iocb]&4) goto Dput_exit;   /* read only */
  2499.         hand=Fwrite (DOS_hand[iocb],(long)cch,mem+vector) ;
  2500.         if (hand<0)
  2501.             stat=163;
  2502.         else
  2503.             {
  2504.             mem[0x24]+=mem[0x28];     /* increment buffer pointer */
  2505.             mem[0x25]+=mem[0x29];
  2506.             mem[0x28]=1;    /* decrement buffer length */
  2507.             mem[0x29]=0;    /* decrement buffer length */
  2508.             stat = 1 ;
  2509.             }
  2510.   Dput_exit:
  2511.         mem[0x4c]=stat;
  2512.         y=stat;
  2513.       }
  2514.  
  2515. do_get()
  2516.       {
  2517.         char stat;
  2518.         int iocb, iocb16, hand;
  2519.         char ch;
  2520.         unsigned cch, vector;
  2521.         int fTEXT;
  2522.  
  2523.         iocb16 = (unsigned) x ;
  2524.         iocb = iocb16/16;
  2525.  
  2526.         vector = (unsigned)mem[0x24] + (unsigned)mem[0x25]*256;
  2527.         cch = (unsigned)mem[0x28] + (unsigned)mem[0x29]*256;
  2528.         if (cch==0) cch=1;
  2529.  
  2530.         stat=131 ;
  2531.         if (DOS_mode[iocb]&8)
  2532.             goto Dget_exit;   /* write only */
  2533.  
  2534.         fTEXT = (mem[0x22]&2)?0:1;
  2535.  
  2536.         if (fTEXT)
  2537.             {
  2538.             while (cch)
  2539.                 {
  2540.                 hand=Fread (DOS_hand[iocb],1L,mem+vector) ;
  2541.                 ch = *(mem+vector++);
  2542.                 if (hand<0)
  2543.                     stat=163;
  2544.                 else if (hand==0)    /* EOF */
  2545.                     stat=136;
  2546.                 else
  2547.                     {
  2548.                     if (mem[0x24]++ ==0)   /* increment buffer pointer */
  2549.                         mem[0x25]++;
  2550.                     if (mem[0x28]-- == (char)255)
  2551.                         mem[0x29]--;       /* decrement buffer length */
  2552.                     stat = 1 ;
  2553.                     }
  2554.                 if (hand<=0 || (ch == (char)155))
  2555.                     goto Dget_exit;
  2556.                 }
  2557.             stat = 137;   /* truncated record error */
  2558.             }
  2559.         else
  2560.             {
  2561.             hand=Fread (DOS_hand[iocb],(long)cch,mem+vector) ;
  2562.             ch = *(mem+vector+cch-1);
  2563.  
  2564.             if (hand<0)
  2565.                 stat=163;
  2566.             else if (hand==0)    /* EOF */
  2567.                 stat=136;
  2568.             else
  2569.                 {
  2570.                 mem[0x24]+=mem[0x28];     /* increment buffer pointer */
  2571.                 mem[0x25]+=mem[0x29];
  2572.                 mem[0x28]=1;    /* decrement buffer length */
  2573.                 mem[0x29]=0;    /* decrement buffer length */
  2574.                 stat = 1 ;
  2575.                 }
  2576.             }
  2577.   Dget_exit:
  2578.         mem[0x4c]=stat;
  2579.         y=stat;
  2580.         a=ch;
  2581.       }
  2582.  
  2583. do_close()
  2584.       {
  2585.         char stat;
  2586.         int iocb16, iocb;
  2587.  
  2588.         iocb16 = (unsigned) x ;
  2589.         iocb = iocb16/16;
  2590.         Fclose(DOS_hand[iocb]);
  2591.         DOS_hand[iocb] = -1 ;
  2592.         stat = 1 ;
  2593.   Dclose_exit:
  2594.         mem[0x4c]=stat;
  2595.         y=stat;
  2596.       }
  2597.  
  2598. #ifdef NEVER
  2599.  
  2600. do_Eput()
  2601.      {
  2602.      register char *rmem = mem;
  2603.      register int crs_r=rmem[84];
  2604.      register int crs_c=rmem[85];
  2605.      register unsigned addr;
  2606.      register unsigned addr1;
  2607.  
  2608.      rmem[763]=a;
  2609.  
  2610.      /* if ESC flag is off, go handle special keys, else handle as text */
  2611.  
  2612.      addr = (addr1 = (unsigned)(rmem[88]) + (((unsigned)(rmem[89]))<<8))
  2613.                + crs_c + (crs_r<<3) + (crs_r<<5);
  2614.  
  2615.      if (a==155)
  2616.         {
  2617.         if (rmem[752]==0)
  2618.             {
  2619.             *(rmem+addr) ^= 128;
  2620.             do_byte(addr);
  2621.             }
  2622.         goto cr;
  2623.         }
  2624.      else     /* normal char */
  2625.         {
  2626.         switch (a&96)
  2627.              {
  2628.         case  0: a |= 64;
  2629.                  break;
  2630.         case 32: a &= ~32;
  2631.                  break;
  2632.         case 64: a ^= 96;
  2633.              }
  2634.  
  2635.         if ((stat[addr] & 79)==66)
  2636.             {
  2637.             *(rmem+addr) = a;
  2638.             do_byte(addr);
  2639.             }
  2640.         if (++crs_c >mem[83])
  2641.             {
  2642.   cr:
  2643.             crs_c = mem[82];
  2644.             if (++crs_r>23)
  2645.                 crs_r = 0;
  2646.             }
  2647.         }
  2648.      rmem[84]=crs_r;
  2649.      rmem[85]=crs_c;
  2650.      rmem[86]=0;
  2651.      if (rmem[752]==0)
  2652.          {
  2653.          addr = addr1 + crs_c + (crs_r<<3) + (crs_r<<5);
  2654.          *(rmem+addr) ^= 128;
  2655.          do_byte(addr);
  2656.          }
  2657.  
  2658.      rmem[0x4C] = y = 1;
  2659.      }
  2660.  
  2661. #endif
  2662.  
  2663. /******** Sound routines  *************************************************/
  2664.  
  2665. int NoiseOn[]={0xF7,0xEF,0xDF};
  2666. int NoiseOff[]={0x8,0x10,0x20};
  2667. int ToneOn[]={0xFE,0xFD,0xFB};
  2668. int ToneOff[]={0x01,0x02,0x04};
  2669.  
  2670. /* This routine emulates the Atari 800 SOUND 0,0,0,0 command */
  2671.  
  2672. Sound(channel,freq,dist,vol)
  2673. register int channel,freq,vol;
  2674. int dist;
  2675.     {
  2676.     register int old7;
  2677.     channel %= 3;           /* mask all values to make them legal */
  2678.     freq &= 0xFF;
  2679.     dist &= 0x0E;
  2680.     vol &= 0xF;
  2681.  
  2682. /*  ST uses 12 bits. The 800's 8 bits maps to bits 10..3 xxxx0ffffffff000 */
  2683.  
  2684.     Giaccess(freq<<2,0x80+channel+channel); /* fine tune */
  2685.     Giaccess(freq>>6,0x81+channel+channel); /* coarse tune */
  2686.  
  2687. /* stuff volume */
  2688.  
  2689.     Giaccess(vol,0x88+channel);
  2690.  
  2691. /* do distortion */
  2692.  
  2693.     old7=Giaccess(0,0x7);
  2694.  
  2695.     if(freq)
  2696.        {
  2697.  
  2698.        if ((dist&10)==10)
  2699.            {         /* pure tones */
  2700.            old7 |= NoiseOff[channel];
  2701.            old7 &= ToneOn[channel];
  2702.            }
  2703.        else
  2704.            {                          /* noise */
  2705.            old7 |= ToneOff[channel];
  2706.            old7 &= NoiseOn[channel];
  2707.            Giaccess(dist<<4,0x86);
  2708.            }
  2709.        }
  2710.     else
  2711.        {  /* if freq==0, shut down channel */
  2712.        old7 |= NoiseOff[channel];
  2713.        old7 |= ToneOff[channel];
  2714.        }
  2715.     Giaccess(old7,0x87);
  2716.     }
  2717.  
  2718.  
  2719. /************ joystick handling routines ************************************/
  2720.  
  2721. anotherdummy()   /* a dummy routine. Should never be called */
  2722.     {
  2723.     asm
  2724.         {
  2725. JoyOn:
  2726.         move.w  #0x12,-(A7)
  2727.         move.w  #4,-(A7)
  2728.         move.w  #3,-(A7)
  2729.         trap    #13
  2730.         addq.l  #6,A7
  2731.  
  2732.         lea     Joy0(PC),A3
  2733.         move.w  #0,(A3)         ; clear both sticks
  2734.         move.w  #34,-(A7)
  2735.         trap    #14             ; Kbdvase call
  2736.         addq.l  #2,A7
  2737.         move.l  D0,A0
  2738.         lea     SaveStick(PC),A3
  2739.         move.l  24(A0),(A3)     ; joystick is the 7th vector
  2740.         lea     Stick(PC),A3
  2741.         move.l  A3,24(A0)       ; install our handler
  2742.  
  2743.         move.w  #0x14,-(A7)
  2744.         move.w  #4,-(A7)
  2745.         move.w  #3,-(A7)
  2746.         trap    #13
  2747.         addq.l  #6,A7
  2748.  
  2749.         rts
  2750.  
  2751. Stick:
  2752.         move.l  A1,-(A7)        ; skip the formalities, just read both sticks
  2753.         lea     Joy0(PC),A1
  2754.         move.b  1(A0),(A1)+
  2755.         move.b  2(A0),(A1)
  2756.         move.l  (A7)+,A1
  2757.         rts
  2758.  
  2759. JoyOff:
  2760.         move.w  #0x1a,-(A7)
  2761.         move.w  #4,-(A7)
  2762.         move.w  #3,-(A7)
  2763.         trap    #13
  2764.         addq.l  #6,A7           ; disable Joysticks
  2765.  
  2766.         move.w  #34,-(A7)
  2767.         trap    #14
  2768.         addq.l  #2,A7
  2769.         move.l  D0,A0
  2770.         move.l  SaveStick(PC),24(A0) ; restore the old vector
  2771.  
  2772.         move.w  #0x8,-(A7)
  2773.         move.w  #4,-(A7)
  2774.         move.w  #3,-(A7)
  2775.         trap    #13
  2776.         addq.l  #6,A7
  2777.         rts
  2778.  
  2779. SaveStick:
  2780.         dc.l    0
  2781. Joy0:   dc.b    0
  2782. Joy1:   dc.b    0
  2783.  
  2784.    /*********spill over into VBI stuff ******************************/
  2785.  
  2786.   VBI:
  2787.     move.l  RegA4(PC),A4    ; now we can access C globals
  2788.     lea     RegA7(PC),A0    ; this saves the stack for sure
  2789.     move.l  A7,(A0)
  2790.                 
  2791.     move.l  mem(GLOBAL),A0  ; get pointer to byte 0
  2792.     move.l  A0,A1
  2793.     adda.l  #65536L,A1      ; A1 points to end of memory
  2794.     addq.b  #1,20(A0)
  2795.     bne     check_critic
  2796.     addq.b  #1,77(A0)       ; attract mode
  2797.     addq.b  #1,19(A0)
  2798.     bne.s   check_critic
  2799.     addq.b  #1,18(A0)
  2800.  
  2801.   check_critic:
  2802.     tst.b   66(A0)          ; did someone set the critical flag?
  2803.     bne     exitVBI
  2804.  
  2805.   do_stick:
  2806.     move.b  Joy1(PC),D0     ; joystick-only port is stick 0
  2807.     move.b  D0,D1
  2808.     not.w   D0
  2809.     andi.w  #15,D0
  2810.     move.b  D0,632(A0)      ; stick(0) shadow
  2811.     move.b  D0,D2
  2812.     lsl.w   #8,D2
  2813.     move.b  D0,634(A0)      ; stick(2) shadow
  2814.     btst    #7,D1
  2815.     seq     D0
  2816.     andi.w  #1,D0
  2817.     move.b  D0,644(A0)      ; strig(0) shadow
  2818.     move.b  D0,646(A0)      ; strig(2)
  2819.     move.b  D0,53264(A1)    ; strig(0) hardware
  2820.     move.b  D0,53266(A1)
  2821.     move.b  Joy0(PC),D0     ; mouse port is really stick 1, not 0
  2822.     move.b  D0,D1
  2823.     not.w   D0
  2824.     andi.w  #15,D0
  2825.     move.b  D0,633(A0)      ; stick(1)
  2826.     move.b  D0,635(A0)      ; stick(3)
  2827.     move.b  D0,D2
  2828.     move.w  D2,54016(A1)    ; stick(0) and stick(1) hardware
  2829.     move.w  D2,54018(A1)    ; stick(2) and stick(3) hardware
  2830.     btst    #7,D1
  2831.     seq     D0
  2832.     andi.w  #1,D0
  2833.     move.b  D0,645(A0)      ; strig(1)
  2834.     move.b  D0,647(A0)      ; strig(3)
  2835.     move.b  D0,53265(A1)    ; strig(1) hardware
  2836.     move.b  D0,53267(A1)
  2837.  
  2838.   ; decrement system timers and set flags
  2839.  
  2840.   do_timers:
  2841.     move.w  #4,D1       ; 5 system timers
  2842.   dt1:
  2843.     move.w  536(A0),D0
  2844.     beq.s   dt3
  2845.     subi.w  #0x0100,D0      ; decrement lo byte
  2846.     cmp.w   #255,D0
  2847.     bgt.s   dt2
  2848.     subi.w  #1,D0           ; decrement hi byte
  2849.   dt2:
  2850.     move.w  D0,(A0)+
  2851.   dt3:
  2852.     dbf     D1,dt1
  2853.  
  2854.   exitVBI:
  2855.     lea     sysvbl(PC),A0
  2856.     lea     pemul(PC),A1
  2857.     move.l  A0,(A1)         ; change dispatch vector to point to VBI
  2858.  
  2859.     move.l  RegA7(PC),A7    ; restore the stack pointer before
  2860.     rts                     ; we leave from the vbi
  2861.  
  2862. RegA4:  dc.l    0
  2863. RegA7:  dc.l    0
  2864.     }
  2865.     }
  2866.  
  2867. VBIon()
  2868.     {
  2869.     int queue,i;
  2870.  
  2871.   asm
  2872.     {
  2873.     lea     RegA4(PC),A0
  2874.     move.l  A4,(A0)
  2875.  
  2876.     move.l  #0x456,A0
  2877.     move.l  (A0),IntrptPtr(A4)
  2878.     }
  2879.     queue=*(int *)0x454L;
  2880.     IRet=0;
  2881.  
  2882.     for(i=0;i<queue;i++)
  2883.         {
  2884.         if(*IntrptPtr==0L)
  2885.             {
  2886.             asm
  2887.                 {
  2888.                 move.l  IntrptPtr(A4),A0
  2889.                 lea     VBI(PC),A1
  2890.                 move.l  A1,(A0)
  2891.                 }
  2892.             i=queue;
  2893.             IRet=1;
  2894.             }
  2895.         else
  2896.             IntrptPtr++;
  2897.         }
  2898.     }
  2899.  
  2900. VBIoff()
  2901.     {
  2902.     *IntrptPtr=0L;
  2903.     }
  2904.  
  2905.  
  2906. /**************** keyboard handler stuff ***********************/
  2907.  
  2908. Install_Key()
  2909.     {
  2910.     register long *oldvec;
  2911.  
  2912.     oldvec = (long *) Kbdvbase();
  2913.  
  2914.     asm {
  2915.         lea     32(oldvec),oldvec      ; system IKBD vector
  2916.         lea     oldKey(PC),A0
  2917.         move.l  (oldvec),(A0)          ; put it away in safe storage
  2918.         lea     KeyPatch(PC),A1        ; and now play with fire and
  2919.         move.l  A1,(oldvec)            ; patch in our routine
  2920.         }
  2921.     return;
  2922.  
  2923.     asm {
  2924.  
  2925. ; this is a patch to the keyboard input routine to allows us to tell if
  2926. ; the keys F7, F8, and F9 are being held down
  2927. ; Note that we do NOT check the keys before the OS does. This is because as
  2928. ; soon as the key is checked, the interrupt is cleared and the OS would not
  2929. ; see the keypress. So jsr to the code in ROM then check the key, since WE know
  2930. ; it's there.
  2931.  
  2932. KeyPatch:
  2933.         movem.l D0/A0/A4,-(SP)
  2934.  
  2935.         move.l  oldKey(PC),A0   ; call the old keyboard routine
  2936.         jsr     (A0)
  2937.  
  2938.         move.l  RegA4(PC),A4
  2939.  
  2940.         lea     0xFFFFC00L,A0   ; address of keyboard ACIA
  2941.  
  2942.         move.b  2(A0),D0        ; get the byte
  2943.  
  2944.         cmpi.b  #0xC1,D0        ; is F7 being released?
  2945.         bne.s   kp2
  2946.         clr.w   fSTART(GLOBAL)
  2947.         bra     kp_exit         ; get out of interrupt
  2948.   kp2:
  2949.         cmpi.b  #0x41,D0        ; is F7 being pressed?
  2950.         bne.s   kp3
  2951.         move.w  #-1,fSTART(GLOBAL)
  2952.         bra     kp_exit         ; get out of interrupt
  2953.   kp3:
  2954.         cmpi.b  #0xC2,D0        ; F8
  2955.         bne.s   kp4
  2956.         clr.w   fSELECT(GLOBAL)
  2957.         bra     kp_exit         ; get out of interrupt
  2958.   kp4:
  2959.         cmpi.b  #0x42,D0
  2960.         bne.s   kp5
  2961.         move.w  #1,fSELECT(GLOBAL)
  2962.         bra     kp_exit         ; get out of interrupt
  2963.   kp5:
  2964.         cmpi.b  #0xC3,D0        ; F9
  2965.         bne.s   kp6
  2966.         clr.w   fOPTION(GLOBAL)
  2967.         bra     kp_exit         ; get out of interrupt
  2968.   kp6:
  2969.         cmpi.b  #0x43,D0
  2970.         bne.s   kp_exit
  2971.         move.w  #1,fOPTION(GLOBAL)
  2972.   kp_exit:
  2973.         movem.l (SP)+,D0/A0/A4
  2974.         rts
  2975.  
  2976. oldKey: dc.l    0
  2977.         }
  2978.     }
  2979.  
  2980. Remove_Key()
  2981.     {
  2982.     register long *oldvec;
  2983.  
  2984.     oldvec = (long *)Kbdvbase();
  2985.  
  2986.     asm {
  2987.         lea     32(oldvec),oldvec   ; system IKBD vector
  2988.         lea     oldKey(PC),A0
  2989.         move.l  (A0),(oldvec)       ; recover the old vector
  2990.         }
  2991.     }
  2992.  
  2993.  
  2994. /************* Player Missle Graphics Stuff ************************/
  2995. /*                                                                 */
  2996.  
  2997. drawPlayer(ip)
  2998. register int ip;
  2999.     {
  3000.     register char *page,*spriteptr;
  3001.     register int clip,bits,xcoord;
  3002.     int plane0=((ip&1)?0:4);
  3003.     int plane1=((ip&2)?2:4);
  3004.     int byte = grafP[ip];
  3005.  
  3006. /* First check to see if sprite is even visible.  If not, exit routine */
  3007.  
  3008.    page=(char *)scr_emul;
  3009.    xcoord=hposP[ip];
  3010.    if((xcoord>42) && (xcoord<=207) ) {
  3011.         spriteptr=qP[ip]+32;            /* start=32, first 31 lines not used */
  3012.         bits = (xcoord & 7)<<1;         /* xbit, only even */
  3013.         asm {       /*
  3014.     lea     wide_byte(A4),A1 ; pointer to double-size bytes
  3015.      move.w  mdPMG(GLOBAL),D2 ; type of PMG display
  3016.     beq     exit_PMG
  3017.     move.w  byte(LOCAL),D1  ; graphics data
  3018.  
  3019.     moveq   #0,clip         ; default: no clipping
  3020.     move.w  xcoord,D0
  3021.     add.w   D0,D0           ; double for 2-pixel movement
  3022.     sub.w   #96,D0          ; trim off excess
  3023.     bpl.s   positive        ; if positive, no min x clipping
  3024.     moveq   #-1,clip        ; mark clipping on x
  3025.     moveq   #-8,D0          ; make x coord minimum of zero
  3026.     bra.s   out1            ; and skip this other stuff
  3027.   positive:
  3028.     cmpi.w  #200,xcoord     ; see if off the right edge
  3029.     blt.s   fixxcoord       ; no, so modify x for lookup
  3030.     moveq   #1,clip         ; yes, so set clipping flag
  3031.   fixxcoord:
  3032.     lsr.w   #1,D0           ; divide by 2 to get byte address
  3033.     andi.w  #0xFFF8,D0      ; and make sure it is even words
  3034.   out1:
  3035.     adda.w  D0,page         ; add x offset to screen
  3036.  
  3037.     move.l  page,A0         ; A0 is pointer to 2nd plane
  3038.     adda.w  plane0(LOCAL),page
  3039.     adda.w  plane1(LOCAL),A0
  3040.  
  3041.     move.w  #199,D3         ; counter: 200 lines
  3042.   loop:         moveq   #0,D0
  3043.     move.b  D1,D0
  3044.     btst    #2,D2
  3045.     beq.s   loop2
  3046.     move.b  (spriteptr)+,D0 ; get image byte
  3047.   loop2:
  3048.     beq.s   noplot          ; don't plot empty bytes
  3049.  
  3050.     add.w   D0,D0           ; double it to access tables
  3051.     move.w  0(A1,D0),D0     ; D0 now holds proper image byte
  3052.     swap    D0              ; move image into high word
  3053.     lsr.l   bits,D0         ; now shift image to proper position
  3054.     cmpi.w  #1,clip         ; clipping right edge?
  3055.     beq.s   lowword         ; if yes, then branch over this
  3056.     or.w    D0,8(page)      ; runoff image to 2nd word, plane 0
  3057.     or.w    D0,8(A0)        ; and also plane 1
  3058.   lowword:      cmpi    #-1,clip        ; clipping left edge?
  3059.     beq.s   noplot          ; if yes, then branch over this
  3060.     swap    D0              ; get original image, also shifted
  3061.     or.w    D0,(page)       ; stuff that in position, plane 0
  3062.     or.w    D0,(A0)         ; and plane 1
  3063.  
  3064.   noplot:
  3065.     lea     160(page),page  ; no matter what, point to next line
  3066.     lea     160(A0),A0
  3067.     dbf     D3,loop         ; count down all 200 lines
  3068.   exit_PMG:
  3069.     nop           */
  3070.                 }
  3071.         }
  3072.  return;
  3073.  
  3074.  asm {
  3075.  
  3076.   w_PMB:                        ; location 54279
  3077.     SWAP    DBUS
  3078.     MOVE.L  REGEA,REGMEA
  3079.     move.b  (REGMEA),REGEA
  3080.     cmp.b   DBUS,REGEA
  3081.     beq     w_PMB_exit
  3082.     move.b  DBUS,pmbase(GLOBAL)     ; write to high byte
  3083.     SAVEREGS
  3084.     }
  3085.     {
  3086.     int i;
  3087.  
  3088.     pmbase &= ~255;          /* clear out low byte */
  3089.     if (mem[559] & 16)
  3090.         {
  3091.         qM = mem + 768L + (unsigned)pmbase;
  3092.         qP[0] = qM + 256L;
  3093.         qP[1] = qM + 512L;
  3094.         qP[2] = qM + 768L;
  3095.         qP[3] = qM + 1024L;
  3096.         }
  3097.     else
  3098.         {
  3099.         qM = mem + 384L + (unsigned)pmbase;
  3100.         qP[0] = qM + 128L;
  3101.         qP[1] = qM + 256L;
  3102.         qP[2] = qM + 384L;
  3103.         qP[3] = qM + 512L;
  3104.         }
  3105.     for (i=0; i<4; i++)
  3106.         hposM[i] = hposP[i] = grafP[i] = 0;
  3107.     grafM = 0;
  3108.     }
  3109.   asm
  3110.     {
  3111.     LOADREGS
  3112.   w_PMB_exit:
  3113.     DISPATCH
  3114.  
  3115.   w_gP:                 ; location 53261
  3116.     SWAP    DBUS
  3117.     MOVE.b  DBUS,a(GLOBAL)
  3118.     andi.w  #3,REGEA
  3119.     MOVE.w  REGEA,ea(GLOBAL)
  3120.     SAVEREGS
  3121.     }
  3122.     {
  3123.     int i=ea;
  3124.  
  3125.     if (grafP[i] != a)
  3126.         {
  3127.         grafP[i] = a;
  3128.         if (mdPMG)
  3129.             drawPlayer(i);
  3130.         }
  3131.     }
  3132.  asm
  3133.     {
  3134.     LOADREGS
  3135.     DISPATCH
  3136.     }
  3137.     }
  3138.  
  3139. /* end of _XATARI.C */
  3140.  
  3141.