home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Mixed Mode Maddness / Compilier / Source / HelloWorld.c
Encoding:
C/C++ Source or Header  |  2000-06-24  |  37.9 KB  |  1,804 lines

  1. /*  Assembler for the MOS Technology 650X series of microprocessors
  2.  *  Written by J. H. Van Ornum (201) 949-1781
  3.  *        AT&T Bell Laboratories
  4.  *         Holmdel, NJ
  5.  *
  6.  *
  7.  *  Two changes to version 1.4 have been made to "port" as6502 to CP/M(tm).
  8.  *  A "tolower()" function call was add to the command line processing
  9.  *  code to (re)map the command line arguments to lower case (CP/M
  10.  *  converts all command line arguments to upper case).  The readline()
  11.  *  function has code added to "ignore" the '\r' character (CP/M includes
  12.  *  the \r character along with \n).
  13.  *
  14.  *  The ability to process multiple files on the command line has been
  15.  *  added.  Now one can do, for example:
  16.  *
  17.  *    as6502 -nisvo header.file source.file data.file ...
  18.  *
  19.  *    George V. Wilder
  20.  *    IX 1A-360 x1937
  21.  *    ihuxp!gvw1
  22.  *
  23.  *  All files merged and modified for Macintosh, 02.27.95  
  24.  *  R. T. Kneusel
  25.  *
  26.  *  Mac changes commented out, look for MACINTOSH if you want
  27.  *  them back in.  RTK, 24-Jul-97
  28.  *
  29.  *  John Saeger was here. (john@whimsey.com)
  30.  *  ----------------------------------------
  31.  *  (July 7, 1998)
  32.  *
  33.  *  Mac changes and CPMEOF removed.
  34.  *  Merged header file (no more assm.h).
  35.  *  Removed split address mode.
  36.  *  Always print symbol table at end of listing.
  37.  *  Reversed sense of lflag (default off).
  38.  *  Increased size of symbol table.
  39.  *  Removed debug printout, but print symbol table usage at end of listing.
  40.  *  Added org pseudo op.
  41.  *  Added binary file output to 6502.bin.
  42.  *  Added error message "Can't relocate backwards."
  43.  *  Removed text file output 6502.out.
  44.  *  Reversed sense of oflag (default on).
  45.  *  Reformat listing line slightly, allow more source lines.
  46.  *  Adopted larger opcode and step tables from Joel Swank's Amiga version of as6502.
  47.  *  Added undocumented opcodes, and addressing mode IMM3 (for undoc NOOPs).
  48.  *  Disallow . as first char in symbol name.  Means current value of location counter.
  49.  *  Modify Class2() to prevent backward relocation if undefined label.
  50.  *  ----------------------------------------
  51.  *
  52.  *
  53.  *    Paul Baxter was Here 6/21/2000
  54.  *        Mac Compatable AGAIN
  55.  *        use function prototypes
  56.  *        use global notation g### for global vars
  57.  *        clean up argument parsing
  58.  *        set maxmum symbol size to 512 bytes (just because)
  59.  *        now use -l -v -o etc instead of -lvo (makes it compatable for MPW commando)
  60.  *        arguments may be passed in any order
  61.  *        fix list position for comments with one byte opcodes
  62.  *        use stdin for input file if none given
  63.  *        use stderr for error messages
  64.  *        add .incl directive
  65.  */
  66.  
  67. #include <stdlib.h>
  68. #include <stdio.h>
  69. #include <string.h>
  70. #include <ctype.h>
  71. #include <console.h>
  72. #include <MixedMode.h>
  73.  
  74. #define LAST_CH_POS    132
  75. #define SFIELD        23
  76. #define STABSZ        32000    /* was 6000 */
  77. #define SBOLSZ        512
  78.  
  79. /*
  80.  * symbol flags
  81.  */
  82. #define DEFZRO    2            /* defined - page zero address    */
  83. #define MDEF    3            /* multiply defined        */
  84. #define UNDEF    1            /* undefined - may be zero page */
  85. #define DEFABS    4            /* defined - two byte address    */
  86. #define UNDEFAB 5            /* undefined - two byte address */
  87.  
  88. /*
  89.  * operation code flags
  90.  */
  91. #define PSEUDO    0x6000
  92. #define CLASS1    0x2000
  93. #define CLASS2    0x4000
  94.  
  95. #define IMM3    0x8000        /* opval + 0x80 2 byte  for NOOP # */
  96. #define IMM1    0x1000        /* opval + 0x00    2 byte    */
  97. #define IMM2    0x0800        /* opval + 0x08    2 byte    */
  98. #define ABS        0x0400        /* opval + 0x0C    3 byte    */
  99. #define ZER        0x0200        /* opval + 0x04    2 byte    */
  100. #define INDX    0x0100        /* opval + 0x00    2 byte    */
  101. #define ABSY2    0x0080        /* opval + 0x1C    3 byte    */
  102. #define INDY    0x0040        /* opval + 0x10    2 byte    */
  103. #define ZERX    0x0020        /* opval + 0x14    2 byte    */
  104. #define ABSX    0x0010        /* opval + 0x1C    3 byte    */
  105. #define ABSY    0x0008        /* opval + 0x18    3 byte    */
  106. #define ACC        0x0004        /* opval + 0x08    1 byte    */
  107. #define IND        0x0002        /* opval + 0x2C    3 byte    */
  108. #define ZERY    0x0001        /* opval + 0x14    2 byte    */
  109.  
  110. /*
  111.  * pass flags
  112.  */
  113. #define FIRST_PASS    0
  114. #define LAST_PASS    1
  115. #define DONE        2
  116.  
  117. #define EOL            '\n'
  118. #define kHASH_SIZE    128
  119. #define kHEX_SIZE    5
  120.  
  121. FILE    *gIptr;                    /* input file */
  122. FILE    *gBinptr;                /* output file */
  123. unsigned int gFile_loc;            /* gets location counter on first write, 
  124.                                    then incremented byte by byte.
  125.                                       fill is written to file to make file_loc==loccnt
  126.                                        when there is a re-org */
  127. int        gErrcnt;                /* error counter */
  128. int        gInited = 0;            /* Bin file created */
  129. int        gHash_tbl[kHASH_SIZE];    /* pointers to starting links in gSymtab */
  130. char    gHex[kHEX_SIZE];        /* hexadecimal character buffer */
  131. unsigned int gLoccnt;            /* location counter    */
  132. int        gLablptr;                /* label pointer into symbol table */
  133. int        gNxt_free;                /* next free location in gSymtab */
  134. int        gOpflg;                    /* operation code flags */
  135. int        gOpval;                    /* operation code value */
  136. int        gPass;                    /* pass counter        */
  137. char    gPrlnbuf[LAST_CH_POS+1];/* print line buffer    */
  138. unsigned int    gSlnum;            /* source line number counter */
  139. char    gSymtab[STABSZ];        /* symbol table        */
  140.                                 /* struct sym_tab        */
  141.                                 /* {    char    size;        */
  142.                                 /*    char    chars[size];    */
  143.                                 /*    char    flag;        */
  144.                                 /*    int    value;        */
  145.                                 /*    int    next_pointer    */
  146.                                 /* }                */
  147. char    gSymbol0[SBOLSZ];        /* temporary symbol storage    */
  148. int        gUdtype;                /* undefined symbol type    */
  149. int        gUndef;                    /* undefined symbol in expression flg  */
  150. int        gValue;                    /* operand field value */
  151. char    gZpref;                    /* zero page reference flag    */
  152.  
  153.  
  154. int        gIflag=0;                /* ignore .nlst flag */
  155. int        gLflag=0;                /* enable listing flag */
  156. int        gSflag=0;                /* do a symbol table print at end of listing */
  157. int        gOflag=1;                /* object output flag */
  158. int        gVflag=0;                /* printversion flag */
  159. int        gDflag=0;                /* Diagnostoc flag */
  160. int        gNextInputFile=0;        /* source file index */
  161. int        gLastInputFile=0;        /* last file index */
  162. char* gFiles[] = {                /* array of files to be processed */
  163.     "", "", "", "", "", "", "", "", "", "",
  164.     "", "", "", "", "", "", "", "", "", ""
  165. };
  166. #define kMAXFILES    sizeof(gFiles) / sizeof(char*)
  167.  
  168. void DefaultOption(int* var);
  169. void NoOutputOption(int* var);
  170. void VersionOption(int* var);
  171. void ListingOption(int* var);
  172. void PrintOpTable(int* val);
  173.  
  174.  
  175. typedef void (*OptionFunPtr)(int* var);
  176. typedef struct {
  177.     char* option;
  178.     int*  variable;
  179.     OptionFunPtr fun;
  180. } OptionSet;
  181. OptionSet gOptions[] = {
  182.      { "-i", &gIflag, ListingOption},
  183.      { "-l", &gLflag, DefaultOption},
  184.      { "-s", &gSflag, DefaultOption },
  185.      { "-v", &gVflag, VersionOption },
  186.      { "-o", &gOflag, NoOutputOption },
  187.      { "-d", &gDflag, PrintOpTable }
  188. };
  189. #define kNumOptions sizeof(gOptions) / sizeof(OptionSet)
  190.  
  191. int    gField[] =
  192. {
  193.     SFIELD,
  194.     SFIELD + 8,
  195.     SFIELD + 14,
  196.     SFIELD + 23,
  197.     SFIELD + 43,
  198.     SFIELD + 75
  199. };
  200.  
  201. #define A    0x20)+('A'&0x1f))
  202. #define B    0x20)+('B'&0x1f))
  203. #define C    0x20)+('C'&0x1f))
  204. #define D    0x20)+('D'&0x1f))
  205. #define E    0x20)+('E'&0x1f))
  206. #define F    0x20)+('F'&0x1f))
  207. #define G    0x20)+('G'&0x1f))
  208. #define H    0x20)+('H'&0x1f))
  209. #define I    0x20)+('I'&0x1f))
  210. #define J    0x20)+('J'&0x1f))
  211. #define K    0x20)+('K'&0x1f))
  212. #define L    0x20)+('L'&0x1f))
  213. #define M    0x20)+('M'&0x1f))
  214. #define N    0x20)+('N'&0x1f))
  215. #define O    0x20)+('O'&0x1f))
  216. #define P    0x20)+('P'&0x1f))
  217. #define Q    0x20)+('Q'&0x1f))
  218. #define R    0x20)+('R'&0x1f))
  219. #define S    0x20)+('S'&0x1f))
  220. #define T    0x20)+('T'&0x1f))
  221. #define U    0x20)+('U'&0x1f))
  222. #define V    0x20)+('V'&0x1f))
  223. #define W    0x20)+('W'&0x1f))
  224. #define X    0x20)+('X'&0x1f))
  225. #define Y    0x20)+('Y'&0x1f))
  226. #define Z    0x20)+('Z'&0x1f))
  227.  
  228.  
  229.  
  230. #define OPSIZE    127                /* # of opcodes in optab - 1 */
  231.  
  232. int    gOptab[]    =                /* nmemonic operation code table    */
  233. {                                /* '.' = 31, '*' = 30, '=' = 29        */
  234.     ((0*0x20)+(29)),PSEUDO,1,                    /* = */
  235.     ((((0*0x20)+(30))*0x20)+(29)),PSEUDO,3,                /* *= */
  236.     ((((((0*A*D*C,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x61,
  237.     ((((((0*A*N*C,IMM1,0x0b,
  238.     ((((((0*A*N*D,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x21,
  239.     ((((((0*A*N*E,IMM1,0x8b,
  240.     ((((((0*A*R*R,IMM1,0x6b,
  241.     ((((((0*A*S*L,ABS|ZER|ZERX|ABSX|ACC,0x02,
  242.     ((((((0*A*S*R,IMM1,0x4b,
  243.     ((((((0*B*C*C,CLASS2,0x90,
  244.     ((((((0*B*C*S,CLASS2,0xb0,
  245.     ((((((0*B*E*Q,CLASS2,0xf0,
  246.     ((((((0*B*I*T,ABS|ZER,0x20,
  247.     ((((((0*B*M*I,CLASS2,0x30,
  248.     ((((((0*B*N*E,CLASS2,0xd0,
  249.     ((((((0*B*P*L,CLASS2,0x10,
  250.     ((((((0*B*R*K,CLASS1,0x00,
  251.     ((((((0*B*V*C,CLASS2,0x50,
  252.     ((((((0*B*V*S,CLASS2,0x70,
  253.     ((((((0*C*L*C,CLASS1,0x18,
  254.     ((((((0*C*L*D,CLASS1,0xd8,
  255.     ((((((0*C*L*I,CLASS1,0x58,
  256.     ((((((0*C*L*V,CLASS1,0xb8,
  257.     ((((((0*C*M*P,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xc1,
  258.     ((((((0*C*P*X,IMM1|ABS|ZER,0xe0,
  259.     ((((((0*C*P*Y,IMM1|ABS|ZER,0xc0,
  260.     ((((((0*D*C*P,ZER|ZERX|ABS|ABSX|ABSY|INDX|INDY,0xc3,
  261.     ((((((0*D*E*C,ABS|ZER|ZERX|ABSX,0xc2,
  262.     ((((((0*D*E*X,CLASS1,0xca,
  263.     ((((((0*D*E*Y,CLASS1,0x88,
  264.     ((((((0*E*O*R,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x41,
  265.     ((((((0*I*N*C,ABS|ZER|ZERX|ABSX,0xe2,
  266.     ((((((0*I*N*X,CLASS1,0xe8,
  267.     ((((((0*I*N*Y,CLASS1,0xc8,
  268.     ((((((0*I*S*B,ZER|ZERX|ABS|ABSX|ABSY|INDX|INDY,0xe3,
  269.     ((((((0*J*A*M,CLASS1,0x02,
  270.     ((((((0*J*M*P,ABS|IND,0x40,
  271.     ((((((0*J*S*R,ABS,0x14,
  272.     ((((((0*L*A*S,ABSY,0xa3,
  273.     ((((((0*L*A*X,ZER|ZERY|ABS|ABSY2|INDX|INDY,0xa3,
  274.     ((((((0*L*D*A,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xa1,
  275.     ((((((0*L*D*X,IMM1|ABS|ZER|ABSY2|ZERY,0xa2,
  276.     ((((((0*L*D*Y,IMM1|ABS|ZER|ABSX|ZERX,0xa0,
  277.     ((((((0*L*S*R,ABS|ZER|ZERX|ABSX|ACC,0x42,
  278.     ((((((0*L*X*A,IMM1,0xab,
  279.     ((((((0*N*O*P,CLASS1,0xea,                /* 0x39f0 */
  280.     ((((((0*N*O*O^((0*P,IMM3|ZER|ZERX|ABS|ABSX,0x00,    /* 0x39ff */
  281.     ((((((0*O*R*A,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x01,
  282.     ((((((0*O*R*G,PSEUDO,3,
  283.     ((((((0*P*H*A,CLASS1,0x48,
  284.     ((((((0*P*H*P,CLASS1,0x08,
  285.     ((((((0*P*L*A,CLASS1,0x68,
  286.     ((((((0*P*L*P,CLASS1,0x28,
  287.     ((((((0*R*L*A,ZER|ZERX|ABS|ABSX|ABSY|INDX|INDY,0x23,
  288.     ((((((0*R*O*L,ABS|ZER|ZERX|ABSX|ACC,0x22,
  289.     ((((((0*R*O*R,ABS|ZER|ZERX|ABSX|ACC,0x62,
  290.     ((((((0*R*R*A,ZER|ZERX|ABS|ABSX|ABSY|INDX|INDY,0x63,
  291.     ((((((0*R*T*I,CLASS1,0x40,
  292.     ((((((0*R*T*S,CLASS1,0x60,
  293.     ((((((0*S*A*X,ZER|ZERY|ABS|INDX,0x83,
  294.     ((((((0*S*B*C,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xe1,
  295.     ((((((0*S*B*X,IMM1,0xcb,
  296.     ((((((0*S*E*C,CLASS1,0x38,
  297.     ((((((0*S*E*D,CLASS1,0xf8,
  298.     ((((((0*S*E*I,CLASS1,0x78,
  299.     ((((((0*S*H*A,ABSY2|INDY,0x83,
  300.     ((((((0*S*H*S,ABSY,0x83,
  301.     ((((((0*S*H*X,ABSY,0x86,
  302.     ((((((0*S*H*Y,ABSX,0x80,
  303.     ((((((0*S*L*O,ZER|ZERX|ABS|ABSX|ABSY|INDX|INDY,0x03,
  304.     ((((((0*S*R*E,ZER|ZERX|ABS|ABSX|ABSY|INDX|INDY,0x43,
  305.     ((((((0*S*T*A,ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x81,
  306.     ((((((0*S*T*X,ABS|ZER|ZERY,0x82,
  307.     ((((((0*S*T*Y,ABS|ZER|ZERX,0x80,
  308.     ((((((0*T*A*X,CLASS1,0xaa,
  309.     ((((((0*T*A*Y,CLASS1,0xa8,
  310.     ((((((0*T*S*X,CLASS1,0xba,
  311.     ((((((0*T*X*A,CLASS1,0x8a,
  312.     ((((((0*T*X*S,CLASS1,0x9a,
  313.     ((((((0*T*Y*A,CLASS1,0x98,
  314.     ((((((0*U*S*B^((0*C,IMM1,0xeb,
  315.     ((((((0*0x20)+(31))*W*O^((((0*R*D,PSEUDO,2,    /* 0x7cab */
  316.     ((((((0*0x20)+(31))*I*N^((((0*C*L,PSEUDO,7,    /* 0x7d42 */
  317.     ((((((0*0x20)+(31))*B*Y^((((0*T*E,PSEUDO,0,    /* 0x7edc */
  318.     ((((((0*0x20)+(31))*D*B^((((0*Y*T,PSEUDO,6,    /* 0x7fb6 */
  319.     ((((((0*0x20)+(31))*N*L^((((0*S*T,PSEUDO,5,    /* 0x7fb8 */
  320.     ((((((0*0x20)+(31))*L*I^((((0*S*T,PSEUDO,4,    /* 0x7ffd */
  321.     0x7fff,0,0,
  322.     0x7fff,0,0,
  323.     0x7fff,0,0,
  324.     0x7fff,0,0,
  325.     0x7fff,0,0,
  326.     0x7fff,0,0,
  327.     0x7fff,0,0,
  328.     0x7fff,0,0,
  329.     0x7fff,0,0,
  330.     0x7fff,0,0,
  331.     0x7fff,0,0,
  332.     0x7fff,0,0,
  333.     0x7fff,0,0,
  334.     0x7fff,0,0,
  335.     0x7fff,0,0,
  336.     0x7fff,0,0,
  337.     0x7fff,0,0,
  338.     0x7fff,0,0,
  339.     0x7fff,0,0,
  340.     0x7fff,0,0,
  341.     0x7fff,0,0,
  342.     0x7fff,0,0,
  343.     0x7fff,0,0,
  344.     0x7fff,0,0,
  345.     0x7fff,0,0,
  346.     0x7fff,0,0,
  347.     0x7fff,0,0,
  348.     0x7fff,0,0,
  349.     0x7fff,0,0,
  350.     0x7fff,0,0,
  351.     0x7fff,0,0,
  352.     0x7fff,0,0,
  353.     0x7fff,0,0,
  354.     0x7fff,0,0,
  355.     0x7fff,0,0,
  356.     0x7fff,0,0,
  357.     0x7fff,0,0,
  358.     0x7fff,0,0,
  359.     0x7fff,0,0,
  360.     0x7fff,0,0,
  361.     0x7fff,0,0,
  362.     0x7fff,0,0
  363. };
  364.  
  365. /* binary search steps for opcode table */
  366.  
  367. int    gStep[] =
  368. {
  369.     3*((OPSIZE+1)/2),
  370.     3*((((OPSIZE+1)/2)+1)/2),
  371.     3*((((((OPSIZE+1)/2)+1)/2)+1)/2),
  372.     3*((((((((OPSIZE+1)/2)+1)/2)+1)/2)+1)/2),
  373.     3*((((((((((OPSIZE+1)/2)+1)/2)+1)/2)+1)/2)+1)/2),
  374.     3*(2),
  375.     3*(1),
  376.     0
  377. };
  378.  
  379. int initialize(char* theFile);
  380. int readline(void);
  381. int assemble(void);
  382. int stprnt(void);
  383. int wrapup(void);
  384. int binputc (char ch, FILE * fileptr);
  385. int hexcon(int digit, int num);
  386. int println(void);
  387. int colsym(int * ip);
  388. int stlook(void);
  389. int oplook(int *ip);
  390. int labldef(int lval);
  391. int error(char* stptr);
  392. int loadlc(int val, int f, int outflg);
  393. int pseudo(int* ip);
  394. int class1(void);
  395. int class2(int* ip);
  396. int class3(int* ip);
  397. int stinstal(void);
  398. int loadv(int val, int f, int outflg);
  399. int symval(int* ip);
  400. int evaluate(int* ip);
  401. int colnum(int* ip);
  402. void parseArgs( int argc, char *argv[]);
  403. void FixUpAPP(void);
  404.  
  405. int main(int argc, char *argv[]);
  406. #define k6502CPU    3
  407.  
  408.  
  409.  
  410. RoutineDescriptor myDescriptor = {
  411.     _MixedModeMagic,
  412.     kRoutineDescriptorVersion,                                    // version
  413.     kSelectorsAreNotIndexable,                                    // Routine Descriptor Flags 
  414.     0,                                                            // reserved1
  415.     0,                                                            // reserved2
  416.     0,                                                            // selectorInfo
  417.     0,                                                            // routineCount
  418.     {
  419.         0,                                                        // procInfo
  420.         0,                                                        // reserved
  421.         k6502CPU,                                                // ISA
  422.         kProcDescriptorIsRelative,                                // routineFlags
  423.         (ProcPtr)sizeof(myDescriptor),                        // WHERE
  424.         0,                                                        // reserved2
  425.         0                                                        // selector
  426.     }
  427. };    
  428.  
  429.  
  430. int main(int argc, char *argv[])
  431. {
  432.     int    i;
  433.     int localspot[kMAXFILES];
  434.  
  435.     argc = ccommand(&argv);
  436.  
  437.     gPass = FIRST_PASS;
  438.     for (i = 0; i < kHASH_SIZE; i++)
  439.         gHash_tbl[i] = -1;
  440.  
  441.     gErrcnt = gLoccnt = gSlnum = 0;
  442.  
  443.     while (gPass != DONE) {
  444.  
  445.         parseArgs(argc, argv);
  446.         initialize(gFiles[gNextInputFile]);
  447.  
  448.         if (gPass == FIRST_PASS) {
  449.             localspot[gNextInputFile] = gLoccnt;    // save start position of file
  450.         }
  451.         else if(gPass == LAST_PASS) {
  452.             gLoccnt = localspot[gNextInputFile];    // restore start position of file
  453.             gSlnum = 0;                                // Line number
  454.         }
  455.         
  456.         while (readline() != -1)
  457.             assemble();
  458.  
  459.         if (gErrcnt != 0) {
  460.             gPass = DONE;
  461.             fprintf(stderr, "Terminated with error counter = %d\n", gErrcnt);
  462.         }
  463.  
  464.         switch (gPass) {
  465.             case FIRST_PASS:
  466.                 // see if we have any more files to do
  467.                 if (gFiles[gNextInputFile + 1][0] == 0) {
  468.                     gPass = LAST_PASS;
  469.                     gNextInputFile = 0;
  470.                 }
  471.                 else {
  472.                     gNextInputFile++;
  473.                 }
  474.                 break;
  475.  
  476.             case LAST_PASS:
  477.                 // see if we have any more files to do
  478.                 if (gFiles[gNextInputFile + 1][0] == 0) {
  479.                     gPass = DONE;
  480.                     if (gSflag) {
  481.                         stprnt();
  482.                     }
  483.                 }
  484.                 else {
  485.                     gNextInputFile++;
  486.                 }
  487.                 break;
  488.                 
  489.             default:
  490.                 break;
  491.         }
  492.         wrapup();
  493.     }
  494.     
  495.     FixUpAPP();
  496.  
  497.     return(0);
  498. }
  499.  
  500. /*****************************************************************************/
  501.  
  502. /* initialize opens files */
  503.  
  504. int initialize(char* theFile)
  505. {
  506.     UInt32 jumpcode;
  507.     
  508.     if (theFile[0] == 0) {
  509.         gIptr = stdin;
  510.     }
  511.     else if ((gIptr = fopen(theFile, "r")) == NULL) {
  512.         fprintf(stderr, "Open error for file '%s'.\n", theFile);
  513.         exit(1);
  514.     }
  515.  
  516.     if ((gInited == 0) && (gOflag == 1)) {
  517.         if ((gBinptr = fopen("6502.bin", "wb")) == NULL) {
  518.             fprintf(stderr, "Can't create 6502.bin.\n");
  519.             exit(1);
  520.         }
  521.         jumpcode = 0x00000001;
  522.         fwrite(&jumpcode, sizeof(jumpcode), 1, gBinptr);
  523.         fwrite(&myDescriptor, sizeof(myDescriptor), 1, gBinptr);
  524.         gInited++; 
  525.     }
  526.     return 0;
  527. }
  528.  
  529.  
  530. /* readline reads and formats an input line    */
  531.  
  532. int readline(void)
  533. {
  534.     int    i;        /* pointer into prlnbuf */
  535.     int    j;        /* pointer to current field start    */
  536.     int    ch;        /* current character        */
  537.     int    cmnt;        /* comment line flag    */
  538.     int    spcnt;        /* consecutive space counter    */
  539.     int    string;        /* ASCII string flag    */
  540.     int    temp1;        /* temp used for line number conversion */
  541.  
  542.     temp1 = ++gSlnum;
  543.     for (i = 0; i < LAST_CH_POS; i++)
  544.         gPrlnbuf[i] = ' ';
  545.     i = 4;
  546.     while (temp1 != 0) {    /* put source line number into prlnbuf */
  547.         gPrlnbuf[i--] = temp1 % 10 + '0';
  548.         temp1 /= 10;
  549.     }
  550.     i = SFIELD;
  551.     cmnt = spcnt = string = 0;
  552.     j = 1;
  553.     while ((ch = getc(gIptr)) != EOL) {
  554.         gPrlnbuf[i++] = ch;
  555.         if ((ch == ' ') && (string == 0)) {
  556.             if (spcnt != 0)
  557.                 --i;
  558.             else if (cmnt == 0) {
  559.                 ++spcnt;
  560.                 if (i < gField[j])
  561.                     i = gField[j];
  562.                 if (++j > 3) {
  563.                     spcnt = 0;
  564.                     ++cmnt;
  565.                 }
  566.             }
  567.         }
  568.         else if (ch == '\t') {
  569.             gPrlnbuf[i - 1] = ' ';
  570.             spcnt = 0;
  571.             if (cmnt == 0) {
  572.                 if (i < gField[j])
  573.                     i = gField[j];
  574.                 if (++j > 3)
  575.                     ++cmnt;
  576.             }
  577.             else i = (i + 8) & 0x78;
  578.         }
  579.         else if ((ch == ';') && (string == 0)) {
  580.             spcnt = 0;
  581.             if (i == SFIELD + 1)
  582.                 ++cmnt;
  583.             else if (gPrlnbuf[i - 2] != '\'') {
  584.                 ++cmnt;
  585.                 gPrlnbuf[i-1] = ' ';
  586.                 if (i <= gField[3])
  587.                     i = gField[3] + 1;
  588.                 gPrlnbuf[i++] = ';';
  589.             }
  590.         }
  591.         else if (ch == EOF)
  592.             return(-1);
  593.         else {
  594.             if ((ch == '"') && (cmnt == 0))
  595.                 string = string ^ 1;
  596.             spcnt = 0;
  597.             if (i >= LAST_CH_POS - 1)
  598.                 --i;
  599.         }
  600.     }
  601.     gPrlnbuf[i] = 0;
  602.     return(0);
  603. }
  604.  
  605. /*
  606.  * binputc() output a binary character to a binary file
  607.  */
  608.  
  609. int binputc (char ch, FILE * fileptr)
  610. {
  611.     return fwrite(&ch, 1, 1, fileptr);
  612. }
  613.  
  614. /*
  615.  * wrapup() closes the source file
  616.  */
  617.  
  618. int wrapup(void)
  619. {
  620.  
  621.     if (gIptr != stdin)
  622.         fclose(gIptr);
  623.  
  624.     if ((gPass == DONE) && (gOflag != 0) && (gInited > 0)) {
  625.         fclose(gBinptr);
  626.     }
  627.     return 0;
  628. }
  629.  
  630. /* symbol table print
  631.  */
  632.  
  633. int stprnt(void)
  634. {
  635.     int    i, j, k;
  636.  
  637. //    fputc('\014', stdout);
  638.     fprintf(stdout, "\n\nSymbol Table\n\n");
  639.     i = 0;
  640.     while    ((j = gSymtab[i++]) != 0) {
  641.         for (k = j; k > 0; k--)
  642.             fputc(gSymtab[i++], stdout);
  643.         for (k = 20 - j; k > 0; k--)
  644.             fputc(' ', stdout);
  645.         ++i;
  646.         j = (gSymtab[i++] & 0xff);
  647.         j += (gSymtab[i++] << 8);
  648.         hexcon(4, j);
  649.         fprintf(stdout, "\t%c%c%c%c\n",
  650.             gHex[1], gHex[2], gHex[3], gHex[4]);
  651.         i += 2;
  652.     }
  653.  
  654.     fprintf(stdout, "\nUsed %d bytes of symbol table space out of %d.\n", gNxt_free, STABSZ);
  655.     return 0;
  656. }
  657.  
  658. /* translate source line to machine language */
  659.  
  660. int assemble(void)
  661. {
  662.     int    flg;
  663.     int    i;        /* prlnbuf pointer */
  664.  
  665.     if ((gPrlnbuf[SFIELD] == ';') | (gPrlnbuf[SFIELD] == 0)) {
  666.         if (gPass == LAST_PASS)
  667.             println();
  668.         return 0;
  669.     }
  670.     gLablptr = -1;
  671.     i = SFIELD;
  672.     gUdtype = UNDEF;
  673.     if (colsym(&i) != 0 && (gLablptr = stlook()) == -1)
  674.         return 0;
  675.     while (gPrlnbuf[++i] == ' ')
  676.         ;    /* find first non-space */
  677.     if ((flg = oplook(&i)) < 0) {    /* collect operation code */
  678.         labldef(gLoccnt);
  679.         if (flg == -1)
  680.             error("Invalid operation code");
  681.         if ((flg == -2) && (gPass == LAST_PASS)) {
  682.             if (gLablptr != -1)
  683.                 loadlc(gLoccnt, 1, 0);
  684.             println();
  685.         }
  686.         return 0;
  687.     }
  688.     if (gOpflg == PSEUDO)
  689.         pseudo(&i);
  690.     else if (labldef(gLoccnt) == -1)
  691.         return 0;
  692.     else {
  693.         if (gOpflg == CLASS1)
  694.             class1();
  695.         else if (gOpflg == CLASS2)
  696.             class2(&i);
  697.         else class3(&i);
  698.     }
  699.     return 0;
  700. }
  701.  
  702. /****************************************************************************/
  703.  
  704. /* printline prints the contents of prlnbuf */
  705.  
  706. int println(void)
  707. {
  708.     if (gLflag > 0)
  709.         fprintf(stdout, "%s\n", gPrlnbuf);
  710.  
  711.     return 0;
  712. }
  713.  
  714. /* colsym() collects a symbol from prlnbuf into gSymbol0[],
  715.  *    leaves prlnbuf pointer at first invalid symbol character,
  716.  *    returns 0 if no symbol collected
  717.  */
  718.  
  719. int colsym(int * ip)
  720. {
  721.     int    valid;
  722.     int    i;
  723.     char    ch;
  724.  
  725.     valid = 1;
  726.     i = 0;
  727.     while (valid == 1) {
  728.         ch = gPrlnbuf[*ip];
  729.         if (ch == '_' || ch == '.')
  730.             ;
  731.         else if (ch >= 'a' && ch <= 'z')
  732.             ;
  733.         else if (ch >= 'A' && ch <= 'Z')
  734.             ;
  735.         else if (i >= 1 && ch >= '0' && ch <= '9')
  736.             ;
  737.         else if (i == 1 && ch == '=')
  738.             ;
  739.         else valid = 0;
  740.         if (valid == 1) {
  741.             if (i < SBOLSZ - 1)
  742.                 gSymbol0[++i] = ch;
  743.             (*ip)++;
  744.         }
  745.     }
  746.     if (i == 1) {
  747.         switch (gSymbol0[1]) {
  748.         case 'A': case 'a':
  749.         case 'X': case 'x':
  750.         case 'Y': case 'y':
  751.             error("Symbol is reserved (A, X or Y)");
  752.             i = 0;
  753.         }
  754.     }
  755.     gSymbol0[0] = i;
  756.     return(i);
  757. }
  758.  
  759. /* symbol table lookup
  760.  *    if found, return pointer to symbol
  761.  *    else, install symbol as undefined, and return pointer
  762.  */
  763.  
  764. int stlook(void)
  765. {
  766.     int    found;
  767.     int    hptr;
  768.     int    j;
  769.     int    nptr;
  770.     int    pptr;
  771.     int    ptr;
  772.  
  773.     hptr = 0;
  774.     for (j = 0; j < gSymbol0[0]; j++)
  775.         hptr += gSymbol0[j];
  776.     hptr %= kHASH_SIZE;
  777.     ptr = gHash_tbl[hptr];
  778.     if (ptr == -1) {        /* no entry for this link */
  779.         gHash_tbl[hptr] = gNxt_free;
  780.         return(stinstal());
  781.     }
  782.     while (gSymtab[ptr] != 0) {    /* 0 count = end of table */
  783.         found = 1;
  784.         for (j = 0; j <= gSymbol0[0]; j++) {
  785.             if (gSymbol0[j] != gSymtab[ptr + j]) {
  786.                 found = 0;
  787.                 pptr = ptr + gSymtab[ptr] + 4;
  788.                 nptr = (gSymtab[pptr + 1] << 8) + (gSymtab[pptr] & 0xff);
  789.                 nptr &= 0xffff;
  790.                 if (nptr == 0) {
  791.                     gSymtab[ptr + gSymtab[ptr] + 4] = gNxt_free & 0xff;
  792.                     gSymtab[ptr + gSymtab[ptr] + 5] = (gNxt_free >> 8) & 0xff;
  793.                     return(stinstal());
  794.                 }
  795.                 ptr = nptr;
  796.                 break;
  797.             }
  798.         }
  799.         if (found == 1)
  800.             return(ptr);
  801.     }
  802.     error("Symbol not found");
  803.     return(-1);
  804. }
  805.  
  806. /*  install symbol into gSymtab
  807.  */
  808. int stinstal(void)
  809. {
  810.     register    int    j;
  811.     register    int    ptr1;
  812.     register    int    ptr2;
  813.  
  814.     ptr1 = ptr2 = gNxt_free;
  815.     if ((ptr1 + gSymbol0[0] + 6) >= STABSZ) {
  816.         error("Symbol table full");
  817.         return(-1);
  818.     }
  819.     for (j = 0; j <= gSymbol0[0]; j++)
  820.         gSymtab[ptr1++] = gSymbol0[j];
  821.     gSymtab[ptr1] = gUdtype;
  822.     gNxt_free = ptr1 + 5;
  823.     return(ptr2);
  824. }
  825.  
  826. /* operation code table lookup
  827.  *    if found, return pointer to symbol,
  828.  *    else, return -1
  829.  */
  830.  
  831. int oplook(int *ip)
  832. {
  833.     register    char    ch;
  834.     register    int    i;
  835.     register    int    j;
  836.     int    k;
  837.     int    temp[2];
  838.  
  839.     i = j = 0;
  840.     temp[0] = temp[1] = 0;
  841.     while((ch=gPrlnbuf[*ip])!= ' ' && ch!= 0 && ch!= '\t' && ch!= ';') {
  842.         if (ch >= 'A' && ch <= 'Z')
  843.             ch &= 0x1f;
  844.         else if (ch >= 'a' && ch <= 'z')
  845.             ch &= 0x1f;
  846.         else if (ch == '.')
  847.             ch = 31;
  848.         else if (ch == '*')
  849.             ch = 30;
  850.         else if (ch == '=')
  851.             ch = 29;
  852.         else return(-1);
  853.         temp[j] = (temp[j] * 0x20) + (ch & 0xff);
  854.         if (ch == 29)
  855.             break;
  856.         ++(*ip);
  857.         if (++i >= 3) {
  858.             i = 0;
  859.             if (++j >= 2) {
  860.                 return(-1);
  861.             }
  862.         }
  863.     }
  864.     if ((j = temp[0]^temp[1]) == 0)
  865.         return(-2);
  866.     k = 0;
  867.     i = gStep[k] - 3;
  868.     do {
  869.         if (j == gOptab[i]) {
  870.             gOpflg = gOptab[++i];
  871.             gOpval= gOptab[++i];
  872.             return(i);
  873.         }
  874.         else if (j < gOptab[i])
  875.             i -= gStep[++k];
  876.         else i += gStep[++k];
  877.     } while (gStep[k] != 0);
  878.     return(-1);
  879. }
  880.  
  881.  
  882. /* error printing routine */
  883.  
  884. int error(char* stptr)
  885. {
  886.     loadlc(gLoccnt, 0, 1);
  887.     gLoccnt += 3;
  888.     loadv(0,0,0);
  889.     loadv(0,1,0);
  890.     loadv(0,2,0);
  891.     fprintf(stderr, "%s\n", gPrlnbuf);
  892.     fprintf(stderr, "%s\n", stptr);
  893.     gErrcnt++;
  894.  
  895.     return 0;
  896. }
  897.  
  898. /* load 16 bit value in printable form into prlnbuf */
  899.  
  900. int loadlc(int val, int f, int outflg)
  901. {
  902.     static int first_write=1;        /* first write to output file */
  903.     int    i;
  904.  
  905.     i = 7 + 7*f;
  906.     hexcon(4, val);
  907.  
  908.     gPrlnbuf[i++] = gHex[1];
  909.     gPrlnbuf[i++] = gHex[2];
  910.     gPrlnbuf[i++] = gHex[3];
  911.     gPrlnbuf[i]   = gHex[4];
  912.  
  913.     if ((gPass == LAST_PASS) && (gOflag != 0) && (outflg != 0)) {
  914.         if (first_write) {
  915.             gFile_loc = gLoccnt;
  916.             first_write = 0;
  917.         }
  918.         if (gFile_loc > gLoccnt) {
  919.  
  920.             /* can't call error from here, error calls us */
  921.  
  922.             fprintf(stderr, "%s\n", gPrlnbuf);
  923.             fprintf(stderr, "Can't relocate backwards.\n");
  924.             gErrcnt++;
  925.             return 0;
  926.         }
  927.         while (gFile_loc < gLoccnt) {
  928.             binputc(0, gBinptr);
  929.             ++gFile_loc;
  930.         }
  931.     }
  932.     return 0;
  933. }
  934.  
  935. /* load value in hex into prlnbuf[contents[i]] */
  936. /* and output hex characters to obuf if LAST_PASS & oflag == 1 */
  937.  
  938. int loadv(int val, int f, int outflg)
  939. {
  940.  
  941.     hexcon(2, val);
  942.     gPrlnbuf[13 + 3*f] = gHex[1];
  943.     gPrlnbuf[14 + 3*f] = gHex[2];
  944.     if ((gPass == LAST_PASS) && (gOflag != 0) && (outflg != 0)) {
  945.         binputc(val, gBinptr);
  946.         ++gFile_loc;
  947.     }
  948.     return 0;
  949. }
  950.  
  951. /* convert number supplied as argument to hexadecimal in hex[digit] (lsd)
  952.         through hex[1] (msd)        */
  953.  
  954. int hexcon(int digit, int num)
  955. {
  956.  
  957.     for (; digit > 0; digit--) {
  958.         gHex[digit] = (num & 0x0f) + '0';
  959.         if (gHex[digit] > '9')
  960.             gHex[digit] += 'A' -'9' - 1;
  961.         num >>= 4;
  962.     }
  963.     return 0;
  964. }
  965.  
  966. /* assign <value> to label pointed to by gLablptr,
  967.  *    checking for valid definition, etc.
  968.  */
  969.  
  970. int labldef(int lval)
  971. {
  972.     int    i;
  973.     
  974.     if (gLablptr != -1) {
  975.         gLablptr += gSymtab[gLablptr] + 1;
  976.         if (gPass == FIRST_PASS) {
  977.             if (gSymtab[gLablptr] == UNDEF) {
  978.                 gSymtab[gLablptr + 1] = lval & 0xff;
  979.                 i = gSymtab[gLablptr + 2] = (lval >> 8) & 0xff;
  980.                 if (i == 0)
  981.                     gSymtab[gLablptr] = DEFZRO;
  982.                 else    gSymtab[gLablptr] = DEFABS;
  983.             }
  984.             else if (gSymtab[gLablptr] == UNDEFAB) {
  985.                 gSymtab[gLablptr] = DEFABS;
  986.                 gSymtab[gLablptr + 1] = lval & 0xff;
  987.                 gSymtab[gLablptr + 2] = (lval >> 8) & 0xff;
  988.             }
  989.             else {
  990.                 gSymtab[gLablptr] = MDEF;
  991.                 gSymtab[gLablptr + 1] = 0;
  992.                 gSymtab[gLablptr + 2] = 0;
  993.                 error("Label multiply defined");
  994.                 return(-1);
  995.             }
  996.         }
  997.         else {
  998.             i = (gSymtab[gLablptr + 2] << 8) +
  999.                 (gSymtab[gLablptr+1] & 0xff);
  1000.             i &= 0xffff;
  1001.             if (i != lval && gPass == LAST_PASS) {
  1002.                 error("Sync error");
  1003.                 return(-1);
  1004.             }
  1005.         }
  1006.     }
  1007.     return(0);
  1008. }
  1009.  
  1010. /* determine the value of the symbol,
  1011.  * given pointer to first character of symbol in gSymtab
  1012.  */
  1013.  
  1014. int symval(int* ip)
  1015. {
  1016.     int    ptr;
  1017.     int    svalue;
  1018.  
  1019.     svalue = 0;
  1020.     colsym(ip);
  1021.     if ((ptr = stlook()) == -1)
  1022.         gUndef = 1;        /* no room error */
  1023.     else if (gSymtab[ptr + gSymtab[ptr] + 1] == UNDEF)
  1024.         gUndef = 1;
  1025.     else if (gSymtab[ptr + gSymtab[ptr] + 1] == UNDEFAB)
  1026.         gUndef = 1;
  1027.     else svalue = ((gSymtab[ptr + gSymtab[ptr] + 3] << 8) +
  1028.         (gSymtab[ptr + gSymtab[ptr] + 2] & 0xff)) & 0xffff;
  1029.     if (gSymtab[ptr + gSymtab[ptr] + 1] == DEFABS)
  1030.         gZpref = 1;
  1031.     if (gUndef != 0)
  1032.         gZpref = 1;
  1033.     return(svalue);
  1034. }
  1035.  
  1036.  
  1037. /* class 1 machine operations processor - 1 byte, no operand field */
  1038.  
  1039. int class1(void)
  1040. {
  1041.     if (gPass == LAST_PASS) {
  1042.         loadlc(gLoccnt, 0, 1);
  1043.         loadv(gOpval, 0, 1);
  1044.         println();
  1045.     }
  1046.     gLoccnt++;
  1047.     return 0;
  1048. }
  1049.  
  1050.  
  1051. /* class 2 machine operations processor - 2 byte, relative addressing */
  1052.  
  1053. int class2(int* ip)
  1054. {
  1055.  
  1056.     if (gPass == LAST_PASS) {
  1057.         while (gPrlnbuf[++(*ip)] == ' ')
  1058.             ;
  1059.         if (evaluate(ip) != 0) {
  1060.             gLoccnt += 2;
  1061.             return 0;
  1062.         }
  1063.         loadlc(gLoccnt, 0, 1);
  1064.         loadv(gOpval, 0, 1);
  1065.         gLoccnt += 2;
  1066.         if ((gValue -= gLoccnt) >= -128 && gValue < 128) {
  1067.             loadv(gValue, 1, 1);
  1068.             println();
  1069.         }
  1070.         else error("Invalid branch address");
  1071.     }
  1072.     else gLoccnt += 2;
  1073.  
  1074.     return 0;
  1075. }
  1076.  
  1077.  
  1078. /* class 3 machine operations processor - various addressing modes */
  1079.  
  1080. int class3(int* ip)
  1081. {
  1082.     char    ch;
  1083.     int    code;
  1084.     int    flag;
  1085.     int    i;
  1086.     int    ztmask;
  1087.  
  1088.     while ((ch = gPrlnbuf[++(*ip)]) == ' ')
  1089.         ;
  1090.     switch(ch) {
  1091.     case 0:
  1092.     case ';':
  1093.         error("Operand field missing");
  1094.         return 0;
  1095.     case 'A':
  1096.     case 'a':
  1097.         if ((ch = gPrlnbuf[*ip + 1]) == ' ' || ch == 0) {
  1098.             flag = ACC;
  1099.             break;
  1100.         }
  1101.     default:
  1102.         switch(ch = gPrlnbuf[*ip]) {
  1103.         case '#': case '=':
  1104.             flag = IMM1 | IMM2 | IMM3;
  1105.             ++(*ip);
  1106.             break;
  1107.         case '(':
  1108.             flag = IND | INDX | INDY;
  1109.             ++(*ip);
  1110.             break;
  1111.         default:
  1112.             flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY;
  1113.         }
  1114.         if ((flag & (INDX | INDY | ZER | ZERX | ZERY) & gOpflg) != 0)
  1115.             gUdtype = UNDEFAB;
  1116.         if (evaluate(ip) != 0)
  1117.             return 0;
  1118.         if (gZpref != 0) {
  1119.             flag &= (ABS | ABSX | ABSY | ABSY2 | IND | IMM1 | IMM2 | IMM3);
  1120.             ztmask = 0;
  1121.         }
  1122.         else ztmask = ZER | ZERX | ZERY;
  1123.         code = 0;
  1124.         i = 0;
  1125.         while (( ch = gPrlnbuf[(*ip)++]) != ' ' && ch != 0 && i++ < 4) {
  1126.             code *= 8;
  1127.             switch(ch) {
  1128.             case ')':        /* ) = 4 */
  1129.                 ++code;
  1130.             case ',':        /* , = 3 */
  1131.                 ++code;
  1132.             case 'X':        /* X = 2 */
  1133.             case 'x':
  1134.                 ++code;
  1135.             case 'Y':        /* Y = 1 */
  1136.             case 'y':
  1137.                 ++code;
  1138.                 break;
  1139.             default:
  1140.                 flag = 0;
  1141.             }
  1142.         }
  1143.         switch(code) {
  1144.         case 0:        /* no termination characters */
  1145.             flag &= (ABS | ZER | IMM1 | IMM2 | IMM3);
  1146.             break;
  1147.         case 4:        /* termination = ) */
  1148.             flag &= IND;
  1149.             break;
  1150.         case 25:        /* termination = ,Y */
  1151.             flag &= (ABSY | ABSY2 | ZERY);
  1152.             break;
  1153.         case 26:        /* termination = ,X */
  1154.             flag &= (ABSX | ZERX);
  1155.             break;
  1156.         case 212:        /* termination = ,X) */
  1157.             flag &= INDX;
  1158.             break;
  1159.         case 281:        /* termination = ),Y */
  1160.             flag &= INDY;
  1161.             break;
  1162.         default:
  1163.             flag = 0;
  1164.         }
  1165.     }
  1166.     if ((gOpflg &= flag) == 0) {
  1167.         error("Invalid addressing mode");
  1168.         return 0;
  1169.     }
  1170.     if ((gOpflg & ztmask) != 0)
  1171.         gOpflg &= ztmask;
  1172.     switch(gOpflg) {
  1173.     case ACC:        /* single byte - class 3 */
  1174.         if (gPass == LAST_PASS) {
  1175.             loadlc(gLoccnt, 0, 1);
  1176.             loadv(gOpval + 8, 0, 1);
  1177.             println();
  1178.         }
  1179.         gLoccnt++;
  1180.         return 0;
  1181.  
  1182.     case IMM3:        /* double byte - class 3 */
  1183.         gOpval += 108;    
  1184.     
  1185.     case ZERX: case ZERY:
  1186.         gOpval += 4;
  1187.     case INDY:
  1188.         gOpval += 8;
  1189.     case IMM2:
  1190.         gOpval += 4;
  1191.     case ZER:
  1192.         gOpval += 4;
  1193.     case INDX: case IMM1:
  1194.         if (gPass == LAST_PASS) {
  1195.             loadlc(gLoccnt, 0, 1);
  1196.             loadv(gOpval, 0, 1);
  1197.             loadv(gValue, 1, 1);
  1198.             println();
  1199.         }
  1200.         gLoccnt += 2;
  1201.         return 0;
  1202.     case IND:        /* triple byte - class 3 */
  1203.         gOpval += 16;
  1204.     case ABSX:
  1205.     case ABSY2:
  1206.         gOpval += 4;
  1207.     case ABSY:
  1208.         gOpval += 12;
  1209.     case ABS:
  1210.         if (gPass == LAST_PASS) {
  1211.             gOpval += 12;
  1212.             loadlc(gLoccnt, 0, 1);
  1213.             loadv(gOpval, 0, 1);
  1214.             loadv(gValue, 1, 1);
  1215.             loadv(gValue >> 8, 2, 1);
  1216.             println();
  1217.         }
  1218.         gLoccnt += 3;
  1219.         return 0;
  1220.     default:
  1221.         error("Invalid addressing mode");
  1222.         return 0;
  1223.     }
  1224. }
  1225.  
  1226. /* pseudo operations processor */
  1227.  
  1228. int pseudo(int* ip)
  1229. {
  1230.     int    count;
  1231.     int    i;
  1232.     int    tvalue, index;
  1233.     FILE* saveFile;
  1234.     int saveLine;
  1235.     char tempstr[FILENAME_MAX];
  1236.  
  1237.     switch(gOpval) {
  1238.     case 0:                /* .byte pseudo */
  1239.         labldef(gLoccnt);
  1240.         loadlc(gLoccnt, 0, 1);
  1241.         while (gPrlnbuf[++(*ip)] == ' ')
  1242.             ;    /*    field    */
  1243.         count = 0;
  1244.         do {
  1245.             if (gPrlnbuf[*ip] == '"') {
  1246.                 while ((tvalue = gPrlnbuf[++(*ip)]) != '"') {
  1247.                     if (tvalue == 0) {
  1248.                         error("Unterminated ASCII string");
  1249.                         return 0;
  1250.                     }
  1251.                     if (tvalue == '\\')
  1252.                         switch(tvalue = gPrlnbuf[++(*ip)]) {
  1253.                         case 'n':
  1254.                             tvalue = EOL;
  1255.                             break;
  1256.                         case 't':
  1257.                             tvalue = '\t';
  1258.                             break;
  1259.                         }
  1260.                     gLoccnt++;
  1261.                     if (gPass == LAST_PASS) {
  1262.                         loadv(tvalue, count, 1);
  1263.                         if (++count >= 3) {
  1264.                             println();
  1265.                             for (i = 0; i < SFIELD; i++)
  1266.                                 gPrlnbuf[i] = ' ';
  1267.                             gPrlnbuf[i] = 0;
  1268.                             count = 0;
  1269.                             loadlc(gLoccnt, 0, 1);
  1270.                         }
  1271.                     }
  1272.                 }
  1273.                 ++(*ip);
  1274.             }
  1275.             else {
  1276.                 if (evaluate(ip) != 0) {
  1277.                     gLoccnt++;
  1278.                     return 0;
  1279.                 }
  1280.                 gLoccnt++;
  1281.                 if (gValue > 0xff) {
  1282.                     error("Operand field size error");
  1283.                     return 0;
  1284.                 }
  1285.                 else if (gPass == LAST_PASS) {
  1286.                     loadv(gValue, count, 1);
  1287.                     if (++count >= 3) {
  1288.                         println();
  1289.                         for (i = 0; i < SFIELD; i++)
  1290.                             gPrlnbuf[i] = ' ';
  1291.                         gPrlnbuf[i] = 0;
  1292.                         count = 0;
  1293.                         loadlc(gLoccnt, 0, 1);
  1294.                     }
  1295.                 }
  1296.             }
  1297.         } while (gPrlnbuf[(*ip)++] == ',');
  1298.         if ((gPass == LAST_PASS) && (count != 0))
  1299.             println();
  1300.         return 0;
  1301.     case 1:                /* = pseudo */
  1302.         while (gPrlnbuf[++(*ip)] == ' ')
  1303.             ;
  1304.         if (evaluate(ip) != 0)
  1305.             return 0;
  1306.         labldef(gValue);
  1307.         if (gPass == LAST_PASS) {
  1308.             loadlc(gValue, 1, 0);
  1309.             println();
  1310.         }
  1311.         return 0;
  1312.     case 2:                /* .word pseudo */
  1313.         labldef(gLoccnt);
  1314.         loadlc(gLoccnt, 0, 1);
  1315.         while (gPrlnbuf[++(*ip)] == ' ')
  1316.             ;
  1317.         do {
  1318.             if (evaluate(ip) != 0) {
  1319.                 gLoccnt += 2;
  1320.                 return 0;
  1321.             }
  1322.             gLoccnt += 2;
  1323.             if (gPass == LAST_PASS) {
  1324.                 loadv(gValue, 0, 1);
  1325.                 loadv(gValue>>8, 1, 1);
  1326.                 println();
  1327.                 for (i = 0; i < SFIELD; i++)
  1328.                     gPrlnbuf[i] = ' ';
  1329.                 gPrlnbuf[i] = 0;
  1330.                 loadlc(gLoccnt, 0, 1);
  1331.             }
  1332.         } while (gPrlnbuf[(*ip)++] == ',');
  1333.         return 0;
  1334.     case 3:                /* *= pseudo */
  1335.         while (gPrlnbuf[++(*ip)] == ' ')
  1336.             ;
  1337.         if (gPrlnbuf[*ip] == '*') {
  1338.             if (evaluate(ip) != 0)
  1339.                 return 0;
  1340.             if (gUndef != 0) {
  1341.                 error("Undefined symbol in operand field.");
  1342.                 return 0;
  1343.             }
  1344.             tvalue = gLoccnt;
  1345.         }
  1346.         else {
  1347.             if (evaluate(ip) != 0)
  1348.                 return 0;
  1349.             if (gUndef != 0) {
  1350.                 error("Undefined symbol in operand field.");
  1351.                 return 0;
  1352.             }
  1353.             tvalue = gValue;
  1354.         }
  1355.         gLoccnt = gValue;
  1356.         labldef(tvalue);
  1357.         if (gPass == LAST_PASS) {
  1358.             loadlc(tvalue, 1, 0);
  1359.             println();
  1360.         }
  1361.         return 0;
  1362.     case 4:                /* .list pseudo */
  1363.         if (gLflag >= 0)
  1364.             gLflag = 1;
  1365.         return 0;
  1366.     case 5:                /* .nlst pseudo */
  1367.         if (gLflag >= 0)
  1368.             gLflag = gIflag;
  1369.         return 0;
  1370.     case 6:                /* .dbyt pseudo */
  1371.         labldef(gLoccnt);
  1372.         loadlc(gLoccnt, 0, 1);
  1373.         while (gPrlnbuf[++(*ip)] == ' ')
  1374.             ;
  1375.         do {
  1376.             if (evaluate(ip) != 0) {
  1377.                 gLoccnt += 2;
  1378.                 return 0;
  1379.             }
  1380.             gLoccnt += 2;
  1381.             if (gPass == LAST_PASS) {
  1382.                 loadv(gValue>>8, 0, 1);
  1383.                 loadv(gValue, 1, 1);
  1384.                 println();
  1385.                 for (i = 0; i < SFIELD; i++)
  1386.                     gPrlnbuf[i] = ' ';
  1387.                 gPrlnbuf[i] = 0;
  1388.                 loadlc(gLoccnt, 0, 1);
  1389.             }
  1390.         } while (gPrlnbuf[(*ip)++] == ',');
  1391.         return 0;
  1392.  
  1393.     case 7:                /* .incl pseudo */
  1394.         while (gPrlnbuf[++(*ip)] == ' ')
  1395.             ;
  1396.         if (gPrlnbuf[*ip] == '"') {
  1397.             index = 0;
  1398.     
  1399.             while ((tvalue = gPrlnbuf[++(*ip)]) != '"') {
  1400.                 if (tvalue == 0) {
  1401.                     error("Unterminated ASCII string");
  1402.                     return 0;
  1403.                 }
  1404.                 if (tvalue == '\\') {
  1405.                     switch(tvalue = gPrlnbuf[++(*ip)]) {
  1406.                     case 'n':
  1407.                         tvalue = EOL;
  1408.                         break;
  1409.                     case 't':
  1410.                         tvalue = '\t';
  1411.                         break;
  1412.                     }
  1413.                 }
  1414.                 tempstr[index++] = tvalue;
  1415.             }
  1416.             ++(*ip);
  1417.             tempstr[index++] = 0x00;
  1418.             if (gPass == LAST_PASS)
  1419.                 println();
  1420.  
  1421.             saveFile = gIptr;
  1422.             saveLine = gSlnum;
  1423.             
  1424.             gSlnum = 0;
  1425.             initialize(tempstr);                        
  1426.             while (readline() != -1)
  1427.                 assemble();
  1428.             wrapup();
  1429.  
  1430.             gSlnum = saveLine;
  1431.             gIptr = saveFile;
  1432.  
  1433.         }
  1434.         else {
  1435.             error("Unspecified include file");
  1436.         }
  1437.         return 0;
  1438.     }
  1439.     return 0;
  1440. }
  1441.  
  1442. /* evaluate expression */
  1443.  
  1444. int evaluate(int* ip)
  1445. {
  1446.     int    tvalue;
  1447.     int    invalid;
  1448.     int    parflg, value2;
  1449.     char    ch;
  1450.     char    op;
  1451.     char    op2;
  1452.  
  1453.     op = '+';
  1454.     parflg = gZpref = gUndef = gValue = invalid = 0;
  1455. /* hcj: gZpref should reflect the value of the expression, not the value of
  1456.    the intermediate symbols
  1457. */
  1458.     while ((ch=gPrlnbuf[*ip]) != ' ' && ch != ')' && ch != ',' && ch != ';') {
  1459.         tvalue = 0;
  1460.         if (ch == '$' || ch == '@' || ch == '%')
  1461.             tvalue = colnum(ip);
  1462.         else if (ch >= '0' && ch <= '9')
  1463.             tvalue = colnum(ip);
  1464.         else if (ch >= 'a' && ch <= 'z')
  1465.             tvalue = symval(ip);
  1466.         else if (ch >= 'A' && ch <= 'Z')
  1467.             tvalue = symval(ip);
  1468.         else if ((ch == '_') /* || (ch == '.') */)
  1469.             tvalue = symval(ip);
  1470.         else if ((ch == '*') || (ch == '.')) {
  1471.             tvalue = gLoccnt;
  1472.             ++(*ip);
  1473.         }
  1474.         else if (ch == '\'') {
  1475.             ++(*ip);
  1476.             tvalue = gPrlnbuf[*ip] & 0xff;
  1477.             ++(*ip);
  1478.         }
  1479.         else if (ch == '[') {
  1480.             if (parflg == 1) {
  1481.                 error("Too many ['s in expression");
  1482.                 invalid++;
  1483.             }
  1484.             else {
  1485.                 value2 = gValue;
  1486.                 op2 = op;
  1487.                 gValue = tvalue = 0;
  1488.                 op = '+';
  1489.                 parflg = 1;
  1490.             }
  1491.             goto next;
  1492.         }
  1493.         else if (ch == ']') {
  1494.             if (parflg == 0) {
  1495.                 error("No matching [ for ] in expression");
  1496.                 invalid++;
  1497.             }
  1498.             else {
  1499.                 parflg = 0;
  1500.                 tvalue = gValue;
  1501.                 gValue = value2;
  1502.                 op = op2;
  1503.             }
  1504.             ++(*ip);
  1505.         }
  1506.         switch(op) {
  1507.         case '+':
  1508.             gValue += tvalue;
  1509.             break;
  1510.         case '-':
  1511.             gValue -= tvalue;
  1512.             break;
  1513.         case '/':
  1514.             gValue = (unsigned) gValue/tvalue;
  1515.             break;
  1516.         case '*':
  1517.             gValue *= tvalue;
  1518.             break;
  1519.         case '%':
  1520.             gValue = (unsigned) gValue%tvalue;
  1521.             break;
  1522.         case '^':
  1523.             gValue ^= tvalue;
  1524.             break;
  1525.         case '~':
  1526.             gValue = ~tvalue;
  1527.             break;
  1528.         case '&':
  1529.             gValue &= tvalue;
  1530.             break;
  1531.         case '|':
  1532.             gValue |= tvalue;
  1533.             break;
  1534.         case '>':
  1535.             tvalue >>= 8;        /* fall through to '<' */
  1536.         case '<':
  1537.             if (gValue != 0) {
  1538.                 error("High or low byte operator not first in operand field");
  1539.             }
  1540.             gValue = tvalue & 0xff;
  1541.             gZpref = 0;
  1542.             break;
  1543.         default:
  1544.             invalid++;
  1545.         }
  1546.         if ((op=gPrlnbuf[*ip]) == ' '
  1547.                 || op == ')'
  1548.                 || op == ','
  1549.                 || op == ';')
  1550.             break;
  1551.         else if (op != ']')
  1552. next:            ++(*ip);
  1553.     }
  1554.     if (parflg == 1) {
  1555.         error("Missing ] in expression");
  1556.         return(1);
  1557.     }
  1558.     if (gValue < 0 || gValue >= 256) {
  1559.         gZpref = 1;
  1560.     }
  1561.     if (gUndef != 0) {
  1562.         if (gPass != FIRST_PASS) {
  1563.             error("Undefined symbol in operand field");
  1564.             invalid++;
  1565.         }
  1566.         gValue = 0;
  1567.     }
  1568.     else if (invalid != 0)
  1569.     {
  1570.         error("Invalid operand field");
  1571.     }
  1572.     else {
  1573. /*
  1574.  This is the only way out that may not signal error
  1575. */
  1576.         if (gValue < 0 || gValue >= 256) {
  1577.             gZpref = 1;
  1578.         }
  1579.         else {
  1580.             gZpref = 0;
  1581.         }
  1582.     }
  1583.     return(invalid);
  1584. }
  1585.  
  1586. /* collect number operand        */
  1587.  
  1588. int colnum(int* ip)
  1589. {
  1590.     int    mul;
  1591.     int    nval;
  1592.     char    ch;
  1593.  
  1594.     nval = 0;
  1595.     if ((ch = gPrlnbuf[*ip]) == '$')
  1596.         mul = 16;
  1597.     else if (ch >= '1' && ch <= '9') {
  1598.         mul = 10;
  1599.         nval = ch - '0';
  1600.     }
  1601.     else if (ch == '@' || ch == '0')
  1602.         mul = 8;
  1603.     else if (ch == '%')
  1604.         mul = 2;
  1605.     while ((ch = gPrlnbuf[++(*ip)] - '0') >= 0) {
  1606.         if (ch > 9) {
  1607.             ch -= ('A' - '9' - 1);
  1608.             if (ch > 15)
  1609.                 ch -= ('a' - 'A');
  1610.             if (ch > 15)
  1611.                 break;
  1612.             if (ch < 10)
  1613.                 break;
  1614.         }
  1615.         if (ch >= mul)
  1616.             break;
  1617.         nval = (nval * mul) + ch;
  1618.     }
  1619.     return(nval);
  1620. }
  1621.  
  1622. /* parse the arguments */
  1623.  
  1624. void parseArgs( int argc, char *argv[]) 
  1625. {
  1626.     int filecount = 0;
  1627.     int argindex, opIndex, len, found;
  1628.     char tempstr[FILENAME_MAX];
  1629.     
  1630.     for (argindex = 1; argindex < argc; argindex++) {
  1631.  
  1632.         strcpy(tempstr, argv[argindex]);
  1633.         for (len = 0; tempstr[len]; len--) 
  1634.             tempstr[len] = tolower(tempstr[len]);
  1635.         
  1636.         found = 0;
  1637.         for (opIndex = 0; opIndex < kNumOptions; opIndex++) {
  1638.             if (strcmp(gOptions[opIndex].option, tempstr) == 0) {
  1639.                 (*(gOptions[opIndex].fun))(gOptions[opIndex].variable);
  1640.                 found = 1;
  1641.                 break;
  1642.             }
  1643.         }
  1644.         if (!found) {
  1645.             gFiles[filecount++] = argv[argindex];
  1646.         }
  1647.     }
  1648.     gLastInputFile = filecount;
  1649. }
  1650.  
  1651. /* set a compile option to on */
  1652. void DefaultOption(int* var)
  1653. {
  1654.     *var = 1;
  1655. }
  1656.  
  1657. /* set a compile option to off */
  1658. void NoOutputOption(int* var)
  1659. {
  1660.     *var = 0;
  1661. }
  1662.  
  1663. /* Display version */
  1664. void VersionOption(int* var)
  1665. {
  1666.     *var = 1;
  1667.     
  1668.     if (gPass == FIRST_PASS) {
  1669.         fprintf(stdout, "\nas6502 - %s %s\n", __DATE__, __TIME__);
  1670.     }
  1671.  
  1672. }
  1673.  
  1674. /* Display FileName */
  1675. void ListingOption(int* var)
  1676. {
  1677.     *var = 1;
  1678.     if (gPass == LAST_PASS) {
  1679.         fprintf(stdout, "\n\t%s\n\n", gFiles[gNextInputFile]);
  1680.     }
  1681. }
  1682.  
  1683.  
  1684. #define PRINTOPVAL(n,x)    if (((n) & ##x) == ##x)    { printf(#x " "); op &= ~##x; }
  1685.  
  1686. void PrintOpTable(int* val)
  1687. {
  1688.     int* curOp = gOptab, op, temp;
  1689.     char curbyte, outbyte[10], count, x;
  1690.     *val = 1;
  1691.     if (gPass == FIRST_PASS) {
  1692.         do {
  1693.             op = *curOp++;
  1694.             temp = op;
  1695.             count = 0;
  1696.             do {
  1697.                 curbyte = temp % 0x20;
  1698.                 if (curbyte <= 26) {
  1699.                     outbyte[count] = curbyte + ('A' -1);
  1700.                 }
  1701.                 else {
  1702.                     switch (curbyte) {
  1703.                         case 0x1d:
  1704.                             outbyte[count] = '=';
  1705.                             break;
  1706.                             
  1707.                         case 0x1e:
  1708.                             outbyte[count] = '*';
  1709.                             break;
  1710.  
  1711.                         case 0x1f:
  1712.                         default:
  1713.                             outbyte[count] = '.';
  1714.                             break;
  1715.                     }
  1716.                 }
  1717.                 count++;
  1718.                 temp /= 0x20;
  1719.             } while (temp);
  1720.             outbyte[count] = 0;
  1721.             count--;
  1722.             for (temp = 0; temp < (count >> 1) + 1; temp++) {
  1723.                 x = outbyte[temp];
  1724.                 outbyte[temp] = outbyte[count - temp];                 
  1725.                 outbyte[count - temp] = x;
  1726.             }
  1727.             if (outbyte[0] == '.') {
  1728.                 printf(".????");
  1729.             }
  1730.             else {
  1731.                 printf("%5.5s",outbyte);
  1732.             }
  1733.             printf(" 0x%-4.4x ", op);
  1734.  
  1735.             op = *curOp++;
  1736.             PRINTOPVAL(op,PSEUDO);
  1737.             PRINTOPVAL(op,CLASS1);
  1738.             PRINTOPVAL(op,CLASS2);
  1739.             PRINTOPVAL(op,IMM3);
  1740.             PRINTOPVAL(op,IMM1);
  1741.             PRINTOPVAL(op,IMM2);
  1742.             PRINTOPVAL(op,ABS);
  1743.             PRINTOPVAL(op,ZER);
  1744.             PRINTOPVAL(op,INDX);
  1745.             PRINTOPVAL(op,ABSY2);
  1746.             PRINTOPVAL(op,INDY);
  1747.             PRINTOPVAL(op,ZERX);
  1748.             PRINTOPVAL(op,ABSX);
  1749.             PRINTOPVAL(op,ABSY);
  1750.             PRINTOPVAL(op,ACC);
  1751.             PRINTOPVAL(op,IND);
  1752.             PRINTOPVAL(op,ZERY);
  1753.             
  1754.             op = *curOp++;
  1755.             printf("0x%-2.2x\n", op);
  1756.             
  1757.         } while (*curOp != 0x7fff);
  1758.     }
  1759. }
  1760.  
  1761. void FixUpAPP(void)
  1762. {
  1763.     FSSpec myFSSpec;
  1764.     OSErr err;
  1765.     FInfo fndrInfo;
  1766.     SInt16 refNum;
  1767.     SInt32 curEOF;
  1768.     Handle myHandle, codeZero;
  1769.  
  1770.     err = FSMakeFSSpec(0,0,"\p6502.bin",&myFSSpec);
  1771.     if (err) return;
  1772.  
  1773.     err = FSpGetFInfo(&myFSSpec,&fndrInfo);
  1774.     fndrInfo.fdType = 'APPL';
  1775.     err = FSpSetFInfo(&myFSSpec,&fndrInfo);
  1776.     
  1777.     err = FSpOpenDF(&myFSSpec,fsRdWrPerm,&refNum);
  1778.     err = GetEOF(refNum,&curEOF);
  1779.     myHandle = NewHandle(curEOF);
  1780.     
  1781.     err = FSRead(refNum, &curEOF, *myHandle);
  1782.     FSClose(refNum);
  1783.  
  1784.     codeZero = GetResource('COde', 0);
  1785.     DetachResource(codeZero);
  1786.     
  1787.     HCreateResFile(myFSSpec.vRefNum, myFSSpec.parID, myFSSpec.name);
  1788.     refNum = HOpenResFile(myFSSpec.vRefNum, myFSSpec.parID, myFSSpec.name,  fsRdWrPerm);
  1789.     err = ResError();
  1790.     
  1791.     if (!err) {
  1792.         UseResFile(refNum);
  1793.         AddResource(myHandle, 'CODE', 1, "\p");
  1794.         ChangedResource(myHandle);
  1795.         WriteResource(myHandle);
  1796.  
  1797.         AddResource(codeZero, 'CODE', 0, "\p");
  1798.         ChangedResource(codeZero);
  1799.         WriteResource(codeZero);
  1800.  
  1801.         CloseResFile(refNum);
  1802.     }
  1803.     
  1804. }