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

  1.  
  2. /***************************************************************************
  3.  
  4.    XFORMER.C   by Darek Mihocka  (CIS: 73657,2714    GEnie: DAREKM)
  5.  
  6.    Additional programming by Ignac A. Kolenko Jr. and Barry Green
  7.  
  8.    Created: July 15, 1986       Last update: June 18, 1987   13:30
  9.  
  10.    Coding convention used in this code:
  11.  
  12.    Code that's all bunched up like this:
  13.  
  14.     foo() {
  15.        if (bar) {
  16.            goo();
  17.          }
  18.      }
  19.  
  20.    should be re-written as:
  21.  
  22.      foo()
  23.          {
  24.          if (bar)
  25.              {
  26.              goo();
  27.              }
  28.          }
  29.  
  30.    For improved readability and easier debugging of complex expressions,
  31.    variable names should start with the following prefixes:
  32.  
  33.     f - (flag) integer that can only have 2 values
  34.     md - (mode) integer that can take on a few values
  35.     b - byte
  36.     ch - char
  37.     w - signed integer
  38.     u - unsigned integer
  39.     l - long
  40.     p - (near pointer) 16 bit pointer (not used, same as a q in this program)
  41.     q - (far pointer) 32 bit pointer
  42.     rgn - (range) a fixed array of n, where n is one of the above prefixes
  43.     mpxy - (map) an array of type y that maps an x to a y
  44.     st - (string) pointer to a character string, first byte is the length
  45.     sz - (zero string) pointer to a null terminated string
  46.  
  47.   Follow these rules or forever write buggy code!
  48.  
  49.   This file contains no tabs cuz the editor I use expands tabs.
  50.  
  51.  ***************************************************************************/
  52.  
  53. #include <stdio.h>
  54. #include <osbind.h>
  55. #include "_xformer.h"              /* defines and global vars */
  56.  
  57. #define MAXCOL  78
  58. #define MAXROW  22
  59. #define MAXBYTE 16
  60.  
  61. char strCR[3] = {'\n','\r',0 };
  62.  
  63. static char *hex= {"0123456789ABCDEF"} ;
  64.  
  65. char buf[80] ,        /* monitor line input buffer */
  66.      ch ,             /* character at buf[tp] */
  67.      asc[17] ,        /* buffer for ASCII dump */
  68.      hardcopy=FALSE;  /* if non-zero dumps to printer */
  69.  
  70. char
  71.      *mem,            /* 65536 bytes to simulate 6502 memory */
  72.      *stat,           /* status bits for each byte */
  73.      *scr,            /* pointer to start of screen */
  74.      *scr_emul,       /* pointer to start of emulation screen */
  75.      *exitptr ;       /* pointer to exit_emul */
  76.  
  77. int  len,             /* length of inputted line */
  78.      tp ,             /* pointer to current character in buf[] */
  79.      hand,            /* disk handle */
  80.      fRainbow=FALSE,  /* 128 colour on flag */
  81.      fCartA = FALSE,  /* cartridge present flag */
  82.      fCartB = FALSE,  /* cartridge present flag */
  83.      isread,          /* read/write flag for opcodes */
  84.      mode ;           /* screen rez */
  85.  
  86.  
  87. int rgPalette[2][16] = {{0x006,0,0,0x557,0,0,0,0,0,0,0,0,0,0,0,0x557}};
  88.  
  89. unsigned int pc ,     /* program counter (16 bits) */
  90.              ea ;
  91. unsigned char a,x,y,sp,ir, p, fTrace ;
  92.  
  93. int colours[16];
  94.  
  95. int fMON=FALSE;
  96.  
  97. int fExec;            /* TRUE to run binary loads */
  98.  
  99. struct DTA {                   /* for disk directories */
  100.          char reserved[21] ;
  101.          char attrib ;
  102.          int time, date ;
  103.          long size ;
  104.          char fname[11] ;
  105.        }  ioblock ;
  106.  
  107. struct disk_info {
  108.          long b_free,b_total,b_sec_siz,b_cl_siz ; } diskblock ;
  109.  
  110. extern long mnemonics[] ;
  111.  
  112. /*********************************************************************/
  113.  
  114. overlay "extra"
  115.  
  116. draw_menu ()
  117.     {
  118.     Setscreen(-1L,-1L,DISPMODE0);
  119.     colors4();
  120.     CR;
  121.     print ("  ST XFORMER v 1.1 DOS MENU"); CR;
  122.     CR;
  123.     print ("  A. DIRECTORY"); CR;
  124.     print ("  B. RUN CART."); CR;
  125.     print ("  L. BINARY LOAD "); CR;
  126.     print ("  M. RUN AT ADDR."); CR;
  127.     print ("  P. 6502 MONITOR");CR;
  128.     print ("  Q. Quit to Desktop"); CR;
  129.     CR;
  130.     }
  131.  
  132. help ()
  133.     {
  134.     print("   \033pCommand Summary for the 6502 Monitor\033q\n\r") ;
  135.     CR ;
  136.     print("  Syntax: ( all numbers are in hex )\n\r") ;
  137.     print("    ssss - starting address       eeee - ending address\n\r") ;
  138.     print("    dddd - destination address    nn   - an 8 bit value\n\r") ;
  139.     print("    [optional parameters are shown in brackets]\n\r") ;
  140.     CR ;
  141.     print(
  142.    "    : ssss nn [nn [nn [nn ...]]] - change memory starting from ssss\n\r") ;
  143.     print("    B - coldstart the Atari 800\n\r") ;
  144.     print("    D ssss [eeee] - display memory from ssss [to eeee]\n\r") ;
  145.     print("    G ssss - start emulating at ssss \n\r") ;
  146.     print("    H nn - nn is non-zero for hardcopy \n\r") ;
  147.     print("    I [mask] - dIr of files on the disk\n\r") ;
  148.     print("    L ssss [eeee] - disassemble from ssss [to eeee]\n\r") ;
  149.     print("    M ssss eeee dddd - move memory block from ssss to dddd\n\r") ;
  150.     print("    R[X] file - read binary file [and execute]\n\r") ;
  151.     print("    S [ssss] - single step at [ssss] or pc\n\r") ;
  152.     print("    T [ssss] - trace at [ssss] or pc\n\r") ;
  153.     print("    V - view emulated screen display\n\r") ;
  154.     print("    W ssss eeee file - write binary file from ssss to dddd\n\r") ;
  155.     print("    X - exit to menu") ;
  156.     }
  157.  
  158. outchar(x) char x ;
  159.   {
  160.   Bconout (2,x) ;     /* print to screen */
  161.   if ((hardcopy)&&(Bconstat(0)))
  162.     Bconout (0,x) ;   /* print to printer */
  163.   if ((Bconstat(2)!=0) && ((char)(Bconin(2))==' '))
  164.     Bconin(2);
  165.   }
  166.  
  167. put_line(lin)
  168. register char *lin ;         /* write string to screen */
  169.   {
  170.   register char c ;
  171.  
  172.   while (c=*lin++) put (c) ;
  173.   }
  174.  
  175.  
  176. get_line(maxc) int maxc ;       /* get line in buf[], set tp and len */
  177.   {
  178.   long key ;      /* scan code and character code returned by Bconin */
  179.   len = 0 ;       /* initialize input line length to 0 */
  180.  
  181.   LOOP
  182.     {
  183.     key = Bconin(2) ;                    /* get a key */
  184.     ch = (char) key ;                    /* isolate character code */
  185.     if (ch>='a' && ch<='z') ch -= 32 ;   /* lowercase becomes uppercase */
  186.     if (ch>=' ' && ch <='_') {           /* if it's printable */
  187.       put(ch) ;                          /* then print it and store it */
  188.       buf[len++] = ch ;
  189.       }                                   /* if Backspace, delete last */
  190.     if (ch==8 && len>0) {                /* character and reduce buffer */
  191.       print("\b \b") ;
  192.       len-- ;
  193.       }
  194.     if (len==0 && ch==0) {                /* if special key */
  195.       ch = (char) (key>>16) ;             /* get scan code */
  196.       if (ch==0x47) cls() ;                 /* is it Home? */
  197.       if (ch==0x62) help() ;              /* is it Help? */
  198.       break ;                             /* break out of loop */
  199.       }
  200.                         /* stay in loop until buffer full or Return pressed */
  201.     if (len==maxc || ch==13 || ch=='\n' || ch == '\033') break ;
  202.     }
  203.   CR ;
  204.   buf[len] = 0 ;        /* terminate input line with a null character */
  205.   tp = 0 ;              /* text pointer points to first character */
  206.   }
  207.  
  208.  
  209. skip_space ()           /* advance tp to point to non-space */
  210. {
  211.   while ((ch=buf[tp])==' ' && tp<len) tp++ ;
  212. }
  213.  
  214.  
  215. skip_blank ()            /* advance tp to point to non-blank */
  216. {
  217.   while (((ch=buf[tp])<'0' || (ch>'9' && ch<'A') || (ch>'F')) && tp<len) tp++ ;
  218. }
  219.  
  220.  
  221. unsigned char get_byte () {    /* return 8 bit value at tp */
  222.  
  223.   unsigned char byte=0, digit=0 ;
  224.  
  225.   skip_blank() ;
  226.   while ((tp<len) && (                           /* find next hex character */
  227.            ((ch = buf[tp]) >='0' && ch<='9') ||
  228.            (ch>='A' && ch<='F')
  229.            )
  230.          && (digit++<2) ) {
  231.     byte <<= 4 ;
  232.     byte += (ch>='0' && ch<='9') ? ch-48 : ch-55 ;
  233.     tp++ ;
  234.    }
  235.   return (byte) ;
  236. }
  237.  
  238.  
  239. unsigned int get_addr () {    /* return 16 bit value at tp */
  240.  
  241.   unsigned int addr=0, digit=0 ;
  242.  
  243.   skip_blank() ;
  244.   while ( (((ch = buf[tp]) >='0' && ch<='9')
  245.                || (ch>='A' && ch<='F'))
  246.                && (digit++<4) ) {
  247.     addr <<= 4 ;
  248.     addr += (ch>='0' && ch<='9') ? ch-48 : ch-55 ;
  249.     tp++ ;
  250.    }
  251.   return (addr) ;
  252. }
  253.  
  254.      /* disassemble #line commands starting at current pc */
  255.  
  256. disasm(line) int line ;
  257.     {
  258.  
  259.     int bits, modes ;
  260.     unsigned char opcode ;
  261.     long crunch ;
  262.  
  263.     while (line--)
  264.         {
  265.         showpc() ;
  266.         opcode = *(mem+pc) ;
  267.         crunch = mnemonics[opcode] ;
  268.  
  269.         modes = crunch&0x0FL ;
  270.  
  271.         showhex(pc) ;
  272.         put(' ') ;
  273.  
  274.         switch (modes)
  275.             {
  276.         case 0x00 :
  277.         case 0x0A :
  278.             print ("      ") ;
  279.             break ;
  280.         case 0x01 :
  281.         case 0x02 :
  282.         case 0x03 :
  283.         case 0x04 :
  284.         case 0x05 :
  285.         case 0x06 :
  286.         case 0x0B :
  287.             showhex(pc+1) ;
  288.             print ("    ") ;
  289.             break ;
  290.  
  291.         case 0x07 :
  292.         case 0x08 :
  293.         case 0x09 :
  294.         case 0x0C :
  295.             showhex(pc+1) ;
  296.             put(' ') ;
  297.             showhex(pc+2) ;
  298.             put(' ') ;
  299.             break ;
  300.             }
  301.  
  302.         for (bits=24 ; bits >0 ; bits -=8 )
  303.             {
  304.             put((char)(crunch>>24)) ;
  305.             crunch <<= 8 ;
  306.             }
  307.         put (' ') ;
  308.  
  309.         pc++ ;
  310.         switch (modes)
  311.             {
  312.         case 0x00 :
  313.             print ("         ") ;
  314.             break ;
  315.  
  316.         case 0x01 :
  317.             print (" #$") ;
  318.             showhex(pc++) ;
  319.             print ("    ") ;
  320.             break ;
  321.  
  322.         case 0x02 :
  323.             print(" $") ;
  324.             showhex(pc++) ;
  325.             print ("     ") ;
  326.             break ;
  327.  
  328.         case 0x03 :
  329.             print (" $") ;
  330.             showhex(pc++) ;
  331.             print (",X") ;
  332.             print ("   ") ;
  333.             break ;
  334.  
  335.         case 0x04 :
  336.             print (" $") ;
  337.             showhex (pc++) ;
  338.             print (",Y") ;
  339.             print ("   ") ;
  340.             break ;
  341.  
  342.         case 0x05 :
  343.             print (" ($") ;
  344.             showhex (pc++) ;
  345.             print (",X)") ;
  346.             print (" ") ;
  347.             break ;
  348.  
  349.         case 0x06 :
  350.             print (" ($") ;
  351.             showhex (pc++) ;
  352.             print ("),Y") ;
  353.             print (" ") ;
  354.             break ;
  355.  
  356.         case 0x07 :
  357.             print (" $") ;
  358.             showhex (pc+1) ;
  359.             showhex (pc) ;
  360.             print ("   ") ;
  361.             pc +=2 ;
  362.             break ;
  363.  
  364.         case 0x08 :
  365.             print (" $") ;
  366.             showhex (pc+1) ;
  367.             showhex (pc) ;
  368.             pc +=2 ;
  369.             print (",X") ;
  370.             print (" ") ;
  371.             break ;
  372.  
  373.         case 0x09 :
  374.             print (" $") ;
  375.             showhex (pc+1) ;
  376.             showhex (pc) ;
  377.             pc +=2 ;
  378.             print (",Y") ;
  379.             print (" ") ;
  380.             break ;
  381.  
  382.         case 0x0A :
  383.             print (" A") ;
  384.             print ("       ") ;
  385.             break ;
  386.  
  387.       case 0x0B :
  388.             print (" $") ;
  389.             showaddr (pc + 1 + (int)((char)(*(mem+pc)))) ;
  390.             print ("   ") ;
  391.             pc ++ ;
  392.             break ;
  393.  
  394.       case 0x0C :
  395.             print (" ($") ;
  396.             showhex(pc+1) ;
  397.             showhex(pc) ;
  398.             put (')') ;
  399.             print (" ") ;
  400.             pc+=2 ;
  401.             break ;
  402.             }
  403.         if (!fTrace) CR ;
  404.         }
  405.     }
  406.  
  407. showreg() {
  408.  
  409.   print ("PC=") ;  showpc() ;
  410.   print ("A=") ;   showbyte(a) ;
  411.   print (" X=") ;  showbyte(x) ;
  412.   print (" Y=") ;  showbyte(y) ;
  413.   print (" S=") ;  showbyte(sp) ;
  414.   print (" P=") ;  showbyte(p) ;
  415.   print (" ") ;
  416.   (p&NBIT) ? put('N') : put ('.') ;
  417.   (p&VBIT) ? put('V') : put ('.') ;
  418.   (p&BBIT) ? put('B') : put ('.') ;
  419.   (p&DBIT) ? put('D') : put ('.') ;
  420.   (p&IBIT) ? put('I') : put ('.') ;
  421.   (p&ZBIT) ? put('Z') : put ('.') ;
  422.   (p&CBIT) ? put('C') : put ('.') ;
  423.   put (' ') ;
  424. }
  425.  
  426. boot()
  427.     {
  428.     for (ea=0; ea<32767; mem[ea++]=0);
  429.     pc = (*(mem+0xFFFD)*256)+(*(mem+0xFFFC)) ; /* RESET vector */
  430.     p &= ~BBIT ;
  431.     emulate(0,0) ;
  432.     colors4();
  433.     }
  434.  
  435. /* routine to perform a JSR and come back on an RTS */
  436.  
  437. jsr(addr)
  438. unsigned int addr;
  439.     {
  440.     pc = addr;
  441.     p &= ~BBIT ;
  442.     mem[0x100|sp--] = 0xE4;
  443.     mem[0x100|sp--] = 0x70;   /* push blackboard vector on stack */
  444.     emulate(0,0) ;
  445.     colors4();
  446.     }
  447.  
  448.   /* routine to single step, trace, or execute at current pc */
  449.  
  450. emulate (count, mode) int count, mode ;
  451.     {
  452.     unsigned int pctemp ;
  453.     unsigned char ptemp ;
  454.     long usp;
  455.  
  456.     Cursconf(0,0);
  457.     switch (mode)
  458.         {
  459.     case 0 :       /* regular emulation */
  460.         {
  461.         static long RegA5;
  462.         show_emul() ;
  463.         colors16() ;
  464.         usp = Super(0L) ;     /* must go to supervisor mode */
  465.         *(char*)0x00000484L &= ~5; /* disable keyclick */
  466.         Super(usp) ;
  467.   asm
  468.     {
  469.     move.l    A5,RegA5(GLOBAL)  /* probably not needed any more */
  470.     }
  471.         IntOn();                /* turn on all interrupts */
  472.         usp = Super(0L) ;
  473.         execute() ;
  474.         Super(usp) ;
  475.         IntOff();               /* turn off interrupts */
  476.   asm
  477.     {
  478.     move.l    RegA5(GLOBAL),A5
  479.     }
  480.         usp = Super(0L) ;
  481.         *(char*)0x00000484L |= 5;  /* enable keyclick */
  482.         Super(usp) ;
  483.         show_scr() ;
  484.         if (fMON)
  485.             {
  486.             showreg() ;
  487.             CR ;
  488.             }
  489.         fTrace=0 ;
  490.         }
  491.         break ;
  492.  
  493.     case 1 :       /* single step mode */
  494.         pctemp = pc ;    /* remember pc                    */
  495.         fTrace=255 ;
  496.         disasm(1) ; /* dissassemble current opcode    */
  497.         pc = pctemp ;    /* restore pc                     */
  498.         emulate(0,0) ;
  499.         break ;
  500.  
  501.     case 2 :       /* trace mode */
  502.         p &= ~BBIT ;
  503.         while (count-- && !(p&BBIT)) emulate(0,1) ;
  504.         break ;
  505.         }
  506.     Cursconf(1,0);
  507.     }
  508.  
  509. dos()
  510.     {
  511.     int key;
  512.  
  513.     boot();
  514.     draw_menu();
  515.  
  516.     for(;;)
  517.         {
  518.         CR;
  519.         print ("  SELECT ITEM OR \033pRETURN\033q FOR MENU"); CR;
  520.         CR;
  521.         Cursconf(1,0);
  522.         key  = Bconin(2) & 0x5F;
  523.         put(key); CR;
  524.  
  525.         switch(key)
  526.             {
  527.         default:
  528.             draw_menu();
  529.             break;
  530.         case 'A':
  531.             print("DIRECTORY MASK: ");
  532.             get_line(MAXCOL) ;          /* get a line of input */
  533.             Directory(buf,0);
  534.             break;
  535.         case 'B':
  536.             pc = 0xA000;     /* ####### WRONG *******/
  537.             p &= ~BBIT ;
  538.             emulate(0,0) ;
  539.             break;
  540.         case 'L':
  541.             print("LOAD FILE: ");
  542.             get_line(MAXCOL) ;          /* get a line of input */
  543.             fExec=TRUE;
  544.             Bload(buf);
  545.             break;
  546.         case 'M':
  547.             print("RUN AT ADDRESS: ");
  548.             get_line(MAXCOL) ;
  549.             pc = get_addr();
  550.             p &= ~BBIT ;
  551.             emulate(0,0) ;
  552.             break;
  553.         case 'P':
  554.             mon();
  555.             break;
  556.         case 'Q':
  557.             return;
  558.             }
  559.         }
  560.     }
  561.  
  562. mon()            /* the 6502 monitor */
  563.     {
  564.  
  565.     int quit=0 ;                  /* quit flag */
  566.     char com ;                    /* command character */
  567.     int digit, chptr, cntr ;      /* temporary variables */
  568.     unsigned addr1, addr2, addr3, byt ;
  569.     unsigned char header[6] ;
  570.  
  571.     Setscreen(-1L,-1L,DISPMODE1);
  572.     fMON=TRUE;
  573.     show_scr();
  574.     CR;
  575.     Setcolor(0, 0x050);
  576.     Setcolor(15, 0x777);
  577.     print("6502 Monitor"); CR;
  578.  
  579.     Cursconf(1,0);
  580.     do
  581.         {
  582.         print ("\n>") ;           /* print prompt */
  583.         get_line(MAXCOL) ;          /* get a line of input */
  584.         skip_space() ;              /* skip any leading spaces */
  585.         com = buf[tp++] ;             /* get command character */
  586.  
  587.         if (com!='R') addr1 = get_addr() ;  /* no numbers for R */
  588.  
  589.         switch(com)
  590.            {
  591.  
  592.         case '\000' :        /* empty line redraws menu */
  593.         case ';' :           /* comment is ignored */
  594.             break ;
  595.  
  596.         case 'X' : quit++ ;  /* X to quit */
  597.             break ;
  598.  
  599.         case 'M' : pc = addr1 ;          /* block memory move */
  600.             addr2 = get_addr() ;
  601.             addr3 = get_addr() ;
  602.             while (addr1<=addr2) *(mem+addr3++) = *(mem+addr1++) ;
  603.             break ;
  604.  
  605.         case 'C' : pc = addr1 ;          /* block memory compare */
  606.             addr2 = get_addr() ;
  607.             addr3 = get_addr() ;
  608.             while (addr1<=addr2)
  609.                 if (*(mem+addr3++) != *(mem+addr1++))
  610.                     {
  611.                     print(" (");
  612.                     showaddr(addr1-1);
  613.                     print(") ");
  614.                     showhex(addr1-1);
  615.                     print("   (");
  616.                     showaddr(addr3-1);
  617.                     print(") ");
  618.                     showhex(addr3-1);
  619.                     CR;
  620.                     }
  621.             break ;
  622.  
  623.         case ':' :
  624.             pc = addr1 ;          /* modify memory */
  625.             skip_blank() ;
  626.             while (buf[tp] && (tp<len))
  627.                 {
  628.                 *(mem+pc++) = get_byte() ;
  629.                 skip_blank() ;
  630.                 }
  631.             break ;
  632.  
  633.         case 'D' :
  634.             pc = addr1 ;        /* dump memory */
  635.             addr2 = get_addr() ;
  636.             if (addr2 <= addr1) addr2 = addr1 + MAXBYTE - 1 ;
  637.                 do
  638.                     {
  639.                     showpc() ;
  640.                     for (cntr=0; cntr<MAXBYTE; cntr++)
  641.                         {
  642.                         if (pc<=addr2)
  643.                             {
  644.                             ch = (*(mem+pc))&0x7F ;
  645.                             asc[cntr] = (ch>=32 && ch<=127) ? ch : '.' ;
  646.                             showhex(pc++) ;
  647.                             put (' ');
  648.                             }
  649.                         else
  650.                             {
  651.                             asc[cntr] = ' ' ;
  652.                             print ("   ") ;
  653.                             }
  654.                         }
  655.                     for (cntr=0; cntr<MAXBYTE; cntr++) put(asc[cntr]) ;
  656.                     CR ;
  657.                     } while (pc<=addr2 && pc>0x000F) ;
  658.             break ;
  659.  
  660.         case 'L' :
  661.             if (len>1) pc = addr1 ;     /* disassemble memory */
  662.             disasm(MAXROW-4) ;
  663.             break ;
  664.  
  665.         case 'T' :
  666.             if (len>1) pc = addr1 ;     /* trace execution */
  667.             p &= ~BBIT ;
  668.             emulate(MAXROW-4,2) ;
  669.             break ;
  670.  
  671.         case 'B' :
  672.             boot();
  673.             break ;
  674.  
  675.         case 'G' :
  676.             pc = addr1 ;                /* execute 6502 code */
  677.             p &= ~BBIT ;
  678.             emulate(0,0) ;
  679.             break ;
  680.  
  681.         case 'S' :
  682.             if (len>1) pc = addr1 ;     /* step execution */
  683.             emulate(0,1) ;
  684.             break ;
  685.  
  686.         case '.' : showreg() ;            /* dump registers */
  687.             break ;
  688.  
  689.         case 'I' : skip_space();
  690.             CR;
  691.             Directory(&buf[2],0);
  692.             CR;
  693.             break ;
  694.  
  695.         case 'W' :
  696.             pc = addr1 ;            /* write memory to binary file */
  697.             addr2 = get_addr() ;
  698.             if (addr2 < addr1) break ;
  699.             skip_space() ;
  700.             if (tp==len) break ;
  701.             strncpy (&buf[len],".bin",5) ;      /* append to filename */
  702.             if ((hand=Fcreate (&buf[tp],0))<0) break ;
  703.             print ("Writing...") ; CR ;
  704.             header[0] = header[1] = 255 ;
  705.             header[2] = addr1 ;           /* lo - hi format */
  706.             header[3] = addr1>>8 ;
  707.             header[4] = addr2 ;
  708.             header[5] = addr2>>8 ;
  709.             if (Fwrite (hand,6L,header)<0)
  710.                 {
  711.                 print ("Write error") ; CR ;
  712.                 goto err_close ;
  713.                 }
  714.             if (Fwrite
  715.                  (hand,(long)addr2-(long)addr1+1L,
  716.                   mem+addr1)<0)
  717.                 print ("Write error") ; CR ;
  718.   err_close:
  719.             Fclose (hand) ;
  720.             break ;
  721.  
  722.         case 'R' :
  723.             if (buf[tp]=='X')
  724.                 {
  725.                 fExec=TRUE;
  726.                 tp++;
  727.                 }
  728.             else
  729.                 fExec=FALSE;
  730.             skip_space() ;            /* read binary file to memory */
  731.             if (tp==len) break ;
  732.             strncpy (&buf[len],".bin",5) ;
  733.  
  734.             Bload(&buf[tp]);
  735.             break;
  736.  
  737.         case 'H' :
  738.             hardcopy = addr1 ;         /* set hardcopy on/off flag */
  739.             break ;
  740.  
  741.         case 'V' :
  742.             show_emul() ;       /* view virtual machine screen */
  743.             getchar() ;
  744.             show_scr() ;
  745.             break ;
  746.  
  747.         default :
  748.             put(BEL) ;                 /* otherwise beep */
  749.             }
  750.         } while (!quit) ;
  751.  
  752.     Setscreen(-1L,-1L,DISPMODE0);
  753.     fMON=FALSE;
  754.     show_scr();
  755.     Cursconf(0,0);
  756.     }
  757.  
  758. /* Binary load a file *****************************************
  759.  
  760.    -szName points to GEMDOS compatible name
  761.  
  762.  returns: 1 - OK   0 - error
  763. */
  764.  
  765. Bload(szName)
  766. char *szName;
  767.     {
  768.     register unsigned addr1, addr2 ;
  769.     unsigned char header[6] ;
  770.     register int cntr ;      /* temporary variables */
  771.  
  772.     if ((hand = Fopen (szName,0))<0)
  773.         {
  774.         print ("FILE NOT FOUND") ; CR ;
  775.         goto Rclose ;
  776.         }
  777.  
  778.     mem[0x2E0] = mem[0x2E1] = 0;     /* clear RUN and INIT vectors */
  779.     mem[0x2E2] = mem[0x2E3] = 0;
  780.  
  781.     if (Fread (hand,6L,header)<0)
  782.         {
  783.         print ("READ ERROR") ; CR ;
  784.         goto Rclose ;
  785.         }
  786.  
  787.     if (header[1]&header[0] != 255)  /* verify it's binary file */
  788.         {
  789.         print ("NOT BINARY FILE") ;
  790.         goto Rclose ;
  791.         }
  792.  
  793.     addr1 = header[2] + (header[3] << 8) ;
  794.     addr2 = header[4] + (header[5] << 8) ;
  795.  
  796.     if (Fread (hand,(long)addr2-(long)addr1+1L, mem+addr1)<0)
  797.         {
  798.         print ("READ ERROR") ;
  799.         goto Rclose ;
  800.         }
  801.  
  802.     if (fMON)
  803.         {
  804.         printf ("SEGMENT START: %4x  END: %4x\n",addr1,addr2) ;
  805.         fflush(stdout);
  806.         }
  807.     cntr=0;
  808.  
  809. more_segs:
  810.     header[0]=header[1]=255;
  811.     if (Fread (hand,2L,header)<0)
  812.         {
  813.         print ("READ ERROR") ;
  814.         goto Rclose ;
  815.         }
  816.  
  817.  /* check if EOF reached */
  818.     if ((cntr++ == 2) || ((header[1]==26) && (header[0]==26))
  819.             || ((header[1]==0) && (header[0] == 0)))
  820.         {
  821.         Fclose (hand) ;
  822.         if (fExec && (mem[0x2E0]|mem[0x2E1]))   /* run location */
  823.             jsr((unsigned)mem[0x2E0] + (unsigned)(256*(unsigned)(mem[0x2E1])));
  824.         show_scr();
  825.         return;
  826.         }
  827.  
  828.     if (header[1]&header[0] == 255)
  829.         goto more_segs ;
  830.  
  831.     cntr=0;
  832.     if (Fread (hand,2L,&header[2])<0)
  833.         goto Rclose;
  834.     addr1 = header[0] + (header[1] << 8) ;
  835.     addr2 = header[2] + (header[3] << 8) ;
  836.     if (Fread(hand,(long)addr2-(long)addr1+1L, mem+addr1)<0)
  837.         {
  838.         print ("READ ERROR") ;
  839.         goto Rclose ;
  840.         }
  841.  
  842.     if (fMON)
  843.         {
  844.         printf ("SEGMENT START: %4x  END: %4x\n",addr1,addr2) ;
  845.         fflush(stdout);
  846.         }
  847.  
  848.     if (fExec && (mem[0x2E2]|mem[0x2E3]))    /* initialize location */
  849.         {
  850.         jsr((unsigned)mem[0x2E2] + (unsigned)(256*(unsigned)(mem[0x2E3])));
  851.         mem[0x2E2] = mem[0x2E3] = 0;
  852.         show_scr();
  853.         }
  854.     goto more_segs;
  855.  
  856. Rclose:
  857.     Fclose (hand) ;
  858.     show_scr();
  859.     }
  860.  
  861.  
  862. StoreCols()
  863.     {
  864.     register cw=16;
  865.  
  866.     while (cw--)
  867.         colours[cw] = Setcolor(cw,-1);
  868.     }
  869.  
  870. /* restore old colours */
  871.  
  872. RestoreCols()
  873.     {
  874.     register cw=16;
  875.  
  876.     while (cw--)
  877.         Setcolor(cw,colours[cw]);
  878.     }
  879.  
  880. /* copy from pchFrom to pchTo and return pointer to byte after */
  881.  
  882. char *blit(pchFrom, pchTo)
  883. register char *pchFrom, *pchTo;
  884.     {
  885.     while (*pchFrom)
  886.         *pchTo++ = *pchFrom++;
  887.     return(pchTo);
  888.     }
  889.  
  890. /* copy ch to pchTo cb times and return pointer to byte after */
  891.  
  892. char *blitc(ch, pchTo, cb)
  893. register char ch;
  894. register char *pchTo;
  895. register unsigned int cb;
  896.     {
  897.     while (cb--)
  898.         *pchTo++ = ch;
  899.     return(pchTo);
  900.     }
  901.  
  902. showpc()
  903.     {                          /* print out PC */
  904.     int bit ;
  905.  
  906.     for (bit = 12; bit>=0; bit-=4)
  907.         put (hex[(pc>>bit)&0x0F]) ;
  908.     print(": ") ;
  909.     }
  910.  
  911.  
  912. showaddr(addr) unsigned int addr ;  /* print 16 bit number */
  913.     {
  914.     put (hex[addr>>12]) ;
  915.     put (hex[(addr>>8)&0x0f]) ;
  916.     put (hex[(addr>>4)&0x0f]) ;
  917.     put (hex[addr&0x0f]) ;
  918.     }
  919.  
  920. showhex(addr) unsigned int addr ;   /* print 8 bit number in memory */
  921.     {
  922.     unsigned char byte ;
  923.  
  924.     byte = *(mem+addr) ;
  925.     put (hex[byte>>4]) ;
  926.     put (hex[byte&0x0f]) ;
  927.     }
  928.  
  929. showbyte(byte) unsigned char byte ; /* print 8 bit number */
  930.     {
  931.     put (hex[byte>>4]) ;
  932.     put (hex[byte&0x0f]) ;
  933.     }
  934.  
  935. show_emul()
  936.     {                       /* display virtual video chip output */
  937.     long usp;
  938.     Setscreen (scr_emul,scr_emul,-1) ;
  939.     usp = Super(0L) ;
  940.     *(char *)0xFFFF8260=DISPMODE0;
  941.     Super(usp);
  942.     colors16();
  943.     }
  944.  
  945. show_scr()
  946.     {                        /* display 6502 monitor or DOS output */
  947.     long usp;
  948.     Setscreen (scr,scr,-1) ;
  949.     usp = Super(0L) ;
  950.     if (fMON)
  951.         *(char *)0xFFFF8260=DISPMODE1;
  952.     else
  953.         *(char *)0xFFFF8260=DISPMODE0;
  954.     Super(usp);
  955.     colors4();
  956.     }
  957.  
  958. cls()
  959.     {
  960.     put (27) ; put ('E') ;
  961.     }
  962.  
  963. colors4()
  964.     {
  965.     Setpalette(rgPalette[0]);
  966.     }
  967.  
  968. colors16()
  969.     {
  970.     Setpalette(rgPalette[1]);
  971.     }
  972.  
  973. /***************  Routines to do the rainbow title page *************/
  974.  
  975. #define HBLANK 0x68L
  976. #define VBLANK 0x70L
  977.  
  978. extern hblank(), old_hblank();
  979. extern vblank(), old_vblank();
  980. extern where_col();
  981.  
  982. ignore()
  983.     {
  984.   asm
  985.     {
  986. vcount:
  987.     nop
  988.     nop
  989. hcount:
  990.     nop
  991. hblank:
  992.     movem.l D0/A0,-(A7)
  993.     clr.l   D0
  994.     move.b  0x8207,-(A7)
  995.     move.w  (A7)+,D0
  996.     move.b  0x8209,D0
  997.     divu    #20,D0
  998.     add.w   vcount(PC),D0
  999.     lsr.w   #3,D0
  1000.     andi.l  #254,D0
  1001.     move.l  where_col(PC),A0
  1002.     move.w  0(A0,D0.L),D0
  1003.     move.w  D0,0x8246
  1004.     movem.l (A7)+,D0/A0
  1005.     rte
  1006. old_hblank:
  1007.     dc.l    0
  1008.     nop
  1009. where_col:
  1010.     dc.l    0
  1011.  
  1012. vblank:
  1013.     movem.l D0/A0/A1,-(A7)
  1014.     lea     hcount,A1
  1015.     lea     vcount,A0
  1016.     move.w  (A0),D0
  1017.     addq.w  #7,D0
  1018.     move.w  D0,(A0)
  1019.     move.w  D0,(A1)
  1020.     movem.l (A7)+,D0/A0/A1
  1021. old_vblank:
  1022.     jmp     0xfff00666L         ; old_vblank
  1023.     }
  1024.     }
  1025.  
  1026. color_on()
  1027.     {
  1028.     long    usp;
  1029.     if (fRainbow)
  1030.         return;
  1031.  
  1032.     usp=Super(0L);
  1033.   asm
  1034.     {
  1035.     lea     rainbow(GLOBAL),A0
  1036.     lea     where_col,A1
  1037.     move.l  A0,(A1)
  1038.     lea     old_vblank,A0
  1039.     move.l  VBLANK,2(A0)
  1040.     lea     vblank,A0
  1041.     move.l  A0,VBLANK
  1042.     lea     old_hblank,A0
  1043.     move.l  HBLANK,(A0)
  1044.     lea     hblank,A0
  1045.     move.l  A0,HBLANK
  1046.     andi.w  #0xF0FF,SR
  1047.     ori.w   #0x0100,SR
  1048.     }
  1049.     Super(usp);
  1050.     fRainbow=TRUE;
  1051.     }
  1052.  
  1053. color_off()
  1054.     {
  1055.     long    usp;
  1056.     if (!fRainbow)
  1057.         return;
  1058.  
  1059.     usp=Super(0L);
  1060.   asm
  1061.     {
  1062.     andi.w  #0xF0FF,SR
  1063.     ori.w   #0x0300,SR
  1064.     lea     old_hblank,A0
  1065.     move.l  (A0),HBLANK
  1066.     lea     old_vblank,A0
  1067.     move.l  2(A0),VBLANK
  1068.     }
  1069.     Super(usp);
  1070.     fRainbow=FALSE;
  1071.     }
  1072.  
  1073. scroll(qscr,qFrom,cScan)
  1074. register char *qscr;
  1075. register char *qFrom;
  1076. register int cScan;
  1077.     {
  1078.   asm
  1079.     {
  1080.     subq.w  #1,cScan
  1081.   LOOPscroll:
  1082.     move.l  (qFrom)+,(qscr)+
  1083.     move.l  (qFrom)+,(qscr)+
  1084.     move.l  (qFrom)+,(qscr)+
  1085.     move.l  (qFrom)+,(qscr)+
  1086.     move.l  (qFrom)+,(qscr)+
  1087.     move.l  (qFrom)+,(qscr)+
  1088.     move.l  (qFrom)+,(qscr)+
  1089.     move.l  (qFrom)+,(qscr)+
  1090.     move.l  (qFrom)+,(qscr)+
  1091.     move.l  (qFrom)+,(qscr)+
  1092.     move.l  (qFrom)+,(qscr)+
  1093.     move.l  (qFrom)+,(qscr)+
  1094.     move.l  (qFrom)+,(qscr)+
  1095.     move.l  (qFrom)+,(qscr)+
  1096.     move.l  (qFrom)+,(qscr)+
  1097.     move.l  (qFrom)+,(qscr)+
  1098.     move.l  (qFrom)+,(qscr)+
  1099.     move.l  (qFrom)+,(qscr)+
  1100.     move.l  (qFrom)+,(qscr)+
  1101.     move.l  (qFrom)+,(qscr)+
  1102.     dbf     cScan,LOOPscroll
  1103.     }
  1104.     }
  1105.  
  1106. fade_out()
  1107.     {
  1108.     long qScreen;
  1109.     int count;
  1110.  
  1111.     qScreen = Physbase();
  1112.  
  1113.     for (count=0; count<199; count++)
  1114.         {
  1115.         Setcolor(3, 199-count);
  1116.         Sound(2,210-count,10,15);
  1117.         scroll(qScreen, qScreen+160, 398);
  1118.         }
  1119.     Sound(0,8,10,15);
  1120.     Sound(2,9,10,15);
  1121.     }
  1122.  
  1123.  
  1124. /********* good a place as any to put a disk directory routine *******/
  1125.  
  1126. Directory(mask,handle)
  1127. register char *mask;
  1128. int handle;
  1129.    {
  1130.    register struct DTA *dta ;
  1131.    register char *pch;
  1132.    register int  ok ;
  1133.    register long fre_by;
  1134.    int cSecs;
  1135.    char DOSbuf[20];
  1136.  
  1137.    if (!(*mask))
  1138.         mask = "*.*";
  1139.  
  1140.    ok = Fsfirst (mask,17) ;
  1141.    dta = (struct DTA *) Fgetdta();
  1142.    while (ok >= 0)
  1143.       {
  1144.       blitc(' ',DOSbuf,17);
  1145.  
  1146.       pch = &dta->fname[0];
  1147.       if (!(*pch=='.' || *pch=='/' || *pch=='_'))
  1148.           {
  1149.           int cb=0;
  1150.  
  1151.           if (dta->attrib & 1)
  1152.               DOSbuf[1] = '*';
  1153.  
  1154.           while ((cb<8) && (*pch) && (*pch!='.'))
  1155.               {
  1156.               DOSbuf[cb++ +2] = *pch++;
  1157.               }
  1158.           cb=8;
  1159.           while (*++pch)
  1160.              {
  1161.              DOSbuf[cb++ +2] = *pch;
  1162.              }
  1163.  
  1164.           cSecs = (int)((dta->size+124L)/125L);
  1165.  
  1166.           DOSbuf[14] = '0' + (cSecs/100);
  1167.           DOSbuf[15] = '0' + ((cSecs/10)%10);
  1168.           DOSbuf[16] = '0' + (cSecs%10);
  1169.  
  1170.           if (handle)
  1171.                {
  1172.                DOSbuf[17] = 155;
  1173.                Fwrite (handle,18L,DOSbuf);
  1174.                }
  1175.           else
  1176.                {
  1177.                DOSbuf[17]=0;
  1178.                print(DOSbuf) ;
  1179.                CR;
  1180.                }
  1181.           }
  1182.       ok = Fsnext () ;
  1183.       }
  1184.  
  1185.    Dfree (&diskblock,0) ;
  1186.    fre_by = (diskblock.b_sec_siz * diskblock.b_cl_siz * diskblock.b_free) ;
  1187.    cSecs = (int)((fre_by+127L)/128L);
  1188.    if (cSecs>999 || cSecs<0)
  1189.         cSecs=999;
  1190.    DOSbuf[0] = '0' + (cSecs/100);
  1191.    DOSbuf[1] = '0' + ((cSecs/10)%10);
  1192.    DOSbuf[2] = '0' + (cSecs%10);
  1193.  
  1194.    blit(" FREE SECTORS",&DOSbuf[3]);
  1195.    if (handle)
  1196.        {
  1197.        DOSbuf[16] = 155;
  1198.        Fwrite (handle,17L,DOSbuf);
  1199.        }
  1200.    else
  1201.        {
  1202.        DOSbuf[16]=0;
  1203.        print(DOSbuf) ;
  1204.        CR;
  1205.        CR;
  1206.        }
  1207.    }
  1208.  
  1209.  
  1210. /***************************************************************************/
  1211.  
  1212. overlay "main"
  1213.  
  1214. main()
  1215.     {
  1216.  
  1217.     appl_init();
  1218.  
  1219.     StoreCols();
  1220.     cls();
  1221.  
  1222.     scr = (char *) Physbase() ;   /* find screen memory pointer */
  1223.     scr_emul = scr - 32768L ;
  1224.     mem = scr - 32768L - 65536L;  /* must be on a 64K boundary!!!! */
  1225.     stat = mem - 65536L + 32768L ;  /* use relative addressing */
  1226.  
  1227.     mode = Getrez();             /* get current screen resolution */
  1228.  
  1229.     if (mode==2)
  1230.         {
  1231.         form_alert(1,"[0][ Works only |  in color  ][ SORRY! ]") ;
  1232.         exit(0) ;
  1233.         }
  1234.     {                             /* load the operating system */
  1235.     int hand ;
  1236.     char *qch;
  1237.  
  1238.     if ((hand=Fopen ("_*.OSB",0))<0)
  1239.         {
  1240.         form_alert(1,"[0][  _*.OSB file |   missing!   ][ Read docs! ]");
  1241.         exit(0) ;
  1242.         }
  1243.     if (((Fread (hand,7174L,mem+0xE400L-6L))<0) || (*(mem+0xE400L-6L) != -1))
  1244.         {
  1245.         form_alert(1,"[0][  _*.OSB file |   invalid!   ][ Read docs! ]");
  1246.         exit(0) ;
  1247.         }
  1248.     Fclose (hand) ;
  1249.  
  1250.     if ((hand=Fopen ("_*.FNT",0))<0)
  1251.         {
  1252.         form_alert(1,"[0][  _*.FNT file |   missing!   ][ Read docs! ]");
  1253.         exit(0) ;
  1254.         }
  1255.     if (((Fread (hand,1030L,mem+0xE000L-6L))<0) || (*(mem+0xE000L-6L) != -1))
  1256.         {
  1257.         form_alert(1,"[0][  _*.OSB file |   invalid!   ][ Read docs! ]");
  1258.         exit(0) ;
  1259.         }
  1260.     Fclose (hand) ;
  1261.  
  1262.     if ((hand=Fopen ("_*.FP",0))<0)
  1263.         {
  1264.         form_alert(1,"[0][  _*.FP file |   missing!   ][ Read docs! ]");
  1265.         exit(0) ;
  1266.         }
  1267.     if (((Fread (hand,2054L,mem+0xD800L-6L))<0) || (*(mem+0xD800L-6L) != -1))
  1268.         {
  1269.         form_alert(1,"[0][  _*.OSB file |   invalid!   ][ Read docs! ]");
  1270.         exit(0) ;
  1271.         }
  1272.     Fclose (hand) ;
  1273.  
  1274.     if ((hand=Fopen ("_*.CTA",0))>=0)
  1275.         {
  1276.         if (((Fread(hand,8198L,mem+0xA000L-6L))<0) || (*(mem+0xA000L-6) != -1))
  1277.             {
  1278.             form_alert(1,"[0][   cart B  |   invalid!   ][ Read docs! ]");
  1279.             exit(0) ;
  1280.             }
  1281.         else
  1282.            fCartA = TRUE;
  1283.        }
  1284.     Fclose (hand) ;
  1285.  
  1286.     if ((hand=Fopen ("_*.CTB",0))>=0)
  1287.         {
  1288.         if (((Fread(hand,8198L,mem+0x8000L-6L))<0) || (*(mem+0x8000L-6) != -1))
  1289.             {
  1290.             form_alert(1,"[0][   cart A  |   invalid!   ][ Read docs! ]");
  1291.             exit(0) ;
  1292.             }
  1293.         else
  1294.             fCartB = TRUE;
  1295.         }
  1296.     Fclose (hand) ;
  1297.     }
  1298.  
  1299.     InitMachine();        /* set up memory, initialize all arrays, etc */
  1300.  
  1301.     fMON = TRUE;       /* force 80 columns */
  1302.     Setscreen(-1L,-1L,DISPMODE1);
  1303.     show_scr();
  1304.     fMON = FALSE;
  1305.     Setcolor(0, 0x000);
  1306.  
  1307.     print("                         ST LOG presents:");
  1308.     CR; CR;
  1309.     print("       ST XFORMER v1.11 Atari 800 simulator by Darek Mihocka");
  1310.     CR; CR;
  1311.    print ("  OS and BASIC (c) 1978,1979 by Atari Corp., all rights reserved.");
  1312.     CR;
  1313.     print ("  Used with permission.");
  1314.     CR; CR;
  1315.  print ("  Fastchip by Charles Marslett & alternate OS used with permission:");
  1316.     CR;
  1317.     print ("    (c) Newell Industries, 602 E. HWY 78, Wylie, TX 75098");
  1318.     CR; CR;
  1319.     print ("  Designed and programmed by Darek Mihocka.");
  1320.     CR;
  1321.     print ("  Additional programming by Ignac A. Kolenko Jr. & Barry Green.");
  1322.     CR;
  1323.     print ("  Report bugs and improvements to DAREKM on GEnie.");
  1324.     CR;
  1325.     print ("  Testing hardware supplied by Carmine Caccioppoli.");
  1326.     CR;
  1327.     print ("  Thanks to John Nagy, George and Jim Adamson for their help.");
  1328.     CR; CR;
  1329.     print ("  Development hardware supplied by:");
  1330.     CR;
  1331.     print ("    Xanth F/X, 14100 NE 20th #105, Bellevue, WA 98007");
  1332.     CR; CR;
  1333.  
  1334.     if (!(fCartA|fCartB))
  1335.         print ("  NO CARTRIDGE PRESENT  48K RAM");
  1336.     else if (!fCartB)
  1337.         print ("  8K CARTRIDGE PRESENT  40K RAM");
  1338.     else
  1339.         print ("  16K CARTRIDGE PRESENT 32K RAM");
  1340.     CR; CR;
  1341.     print ("  Alt=BREAK  F4=caps  F5=inverse");
  1342.     print ("  F7..F9=START SELECT OPTION  F10=RESET");
  1343.     CR; CR;
  1344.     print ("  Press any key to power up the Atari 800...");
  1345.  
  1346.     color_on();
  1347.     Sound(0,199,10,15);
  1348.     Sound(1,200,10,15);
  1349.     Bconin(2);
  1350.     color_off();
  1351.  
  1352.     Setcolor(0,0);
  1353.     fade_out();
  1354.     Sound(0,0,0,0);
  1355.     Sound(1,0,0,0);
  1356.     Sound(2,0,0,0);
  1357.  
  1358.     dos();
  1359.  
  1360.     Setscreen(-1L,-1L,mode);
  1361.     RestoreCols();
  1362.  
  1363.     appl_exit();
  1364.     }
  1365.  
  1366. /* end of _XFORMER.C */
  1367.  
  1368.