home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsa / 6502_xass / !6502-XAss / c / XAss < prev   
Encoding:
Text File  |  1995-12-31  |  24.8 KB  |  936 lines

  1.  
  2. #include "CodeTable.c"
  3. #include "TextTable.c"
  4.  
  5. #define FULL 0xffffffff
  6.  
  7. FILE *error_file, *out_file, *in_file;
  8.  
  9. void status(char*);
  10.  
  11. // contains line of sourcetext
  12. char textline[256] = "";
  13. int  line_nr,
  14.      error_counter,
  15.      transfer_enabled = 1,
  16.      last_error_file;
  17.  
  18. // structure for symbols and their addresses
  19. struct symbolstruct
  20. {
  21.   char name[40];
  22.   int  address;
  23.   int  number_of_reads;
  24. };
  25.  
  26. // number of defined symbols and room for 1000 symbol structures
  27. int nr_of_symbols=0;
  28. struct symbolstruct symbol[1000];
  29.  
  30. // program counter (points to next free byte)
  31. int pc, base, base_defined;
  32.  
  33. //-------------------------------------------------------------
  34. void put_error(int number, int mode)
  35. {
  36.   if (mode)
  37.   {
  38.     error_counter++;
  39.     if ( last_error_file != *(line_list + (line_nr << 1) + 1) )
  40.     {
  41.       last_error_file = *(line_list + (line_nr << 1) + 1);
  42.       fprintf(error_file, "\nFile %s\n",
  43.               file_list[ *(line_list + (line_nr << 1) + 1) ] );
  44.     }
  45.     fprintf(error_file, "  Line %04d - ",
  46.             *(line_list + (line_nr << 1)) );
  47.     switch (number)
  48.     {
  49.       case  0:
  50.        fprintf(error_file, "Error: Illegal address mode\n"); break;
  51.       case  1:
  52.        fprintf(error_file, "Error: Unknown mnemonic\n"); break;
  53.       case  2:
  54.        fprintf(error_file, "Error: Higher than &ff\n"); break;
  55.       case  3:
  56.        fprintf(error_file, "Error: Branch out of range\n"); break;
  57.       case  4:
  58.        fprintf(error_file, "Error: Overflow in expression\n"); break;
  59.       case  5:
  60.        fprintf(error_file, "Error: Missing \')\'\n"); break;
  61.       case  6:
  62.        fprintf(error_file, "Error: Cannot calculate expression\n"); break;
  63.       case  7:
  64.        fprintf(error_file, "Error: Undefined Symbol found\n"); break;
  65.       case  8:
  66.        fprintf(error_file, "Error: Illegal use of '.\' or \'!\'\n"); break;
  67.       case  9:
  68.        fprintf(error_file, "Error: Too many symbols\n"); break;
  69.       case 10:
  70.        fprintf(error_file, "Error: Illegal chars found in symbol\n"); break;
  71.       case 11:
  72.        fprintf(error_file, "Error: Symbol defined twice\n"); break;
  73.       case 12:
  74.        fprintf(error_file, "Error: Extern symbols must be defined\n"); break;
  75.       case 13:
  76.        fprintf(error_file, "Error: No base defined\n"); break;
  77.       case 14:
  78.        fprintf(error_file, "Error: Labels must not be defined\n"); break;
  79.       case 15:
  80.        fprintf(error_file, "Warning: Overflow\n"); break;
  81.       case 16:
  82.        fprintf(error_file, "Error: Illegal mnemonic\n"); break;
  83.       case 17:
  84.        fprintf(error_file, "Warning: Program counter overflow\n"); break;
  85.       case 18:
  86.        fprintf(error_file, "Error: Missing parameters\n"); break;
  87.       case 19:
  88.        fprintf(error_file, "Error: Missing \'\"\'"); break;
  89.       default:
  90.        fprintf(error_file, "Unexpected error\n"); break;
  91.  
  92.     }
  93.   }
  94. }
  95.  
  96. //-------------------------------------------------------------
  97. int getline(FILE *infile)
  98. {
  99.   // == NULL if EOF
  100.   char *textpos;
  101.   int  length, pos;
  102.  
  103.   // don't return empty lines
  104.   do
  105.   {
  106.     // read line from file
  107.     textpos = fgets(textline, 256, infile);
  108.  
  109.     // end if EOF
  110.     if (textpos == NULL)
  111.       return 0;
  112.  
  113.     line_nr++;
  114.  
  115.     // remove silly things like tabs
  116.     length = strlen(textline);
  117.     for (pos = 0; pos < length; pos++)
  118.       if ( textline[pos] < 32 )
  119.         textline[pos] = 32;
  120.  
  121.     // remove spaces from left side
  122.     pos = 0;
  123.     length = strlen(textline) + 1;
  124.     while (textline[pos] == 32)
  125.       pos++;
  126.     memcpy(textline, textline+pos, length);
  127.  
  128.     length = strlen(textline);
  129.  
  130.     // look for comments
  131.     for (pos = 0; pos < length; pos++)
  132.     {
  133.       if ( textline[pos] == ';' )
  134.       {
  135.         textline[pos] = 0;
  136.         length = strlen(textline);
  137.       }
  138.     }
  139.  
  140.     // remove spaces from right side
  141.     length = strlen(textline);
  142.     while ( ((textline[length-1] == ' ') || (textline[length-1] == '\n'))
  143.             && (length > 0) )
  144.     {
  145.       textline[strlen(textline) - 1] = 0;
  146.       length -= 1;
  147.     }
  148.   }
  149.   while (textline[0] == 0);
  150.  
  151.   return 1;
  152. }
  153.  
  154. //-------------------------------------------------------------
  155. int symbol_value(char *name, int mode)
  156. // gets the value of an label, 0xffff if not defined
  157. // if mode == 0 no "Undefind symbol" error
  158. {
  159.   int  loop, ret = FULL;
  160.   char cut_name[40];
  161.  
  162.   memcpy(cut_name, name, 40);                // copy name in my workspace
  163.   cut_name[39] = 0;                          // and cut it
  164.   if ( (cut_name[0] == '.') || (cut_name[0] == '!') )
  165.   {                                          // mustn't start with '.' or '!'
  166.     put_error(8, mode);
  167.     ret = FULL;
  168.   }
  169.   else
  170.   {
  171.     for (loop = 0; loop < nr_of_symbols; loop++)
  172.       if ( !strcmp(cut_name, symbol[loop].name) )
  173.       {
  174.         ret = symbol[loop].address;
  175.         symbol[loop].number_of_reads++;
  176.         loop = nr_of_symbols + 1;
  177.       }
  178.   }
  179.   if (ret == FULL)
  180.     put_error(7, mode);
  181.   return ret;
  182. }
  183.  
  184. //-------------------------------------------------------------
  185. int calc(char *source, int mode)
  186. // calculates an expression
  187. // mode == 0 no Unefined symbol error
  188. {
  189.   os_regset r;
  190.   os_error *err;
  191.   int  pos, source_len, dest_len=0, name_len, found, part = 0;
  192.   char c1, dest[200]="", name[40];
  193.  
  194.   source_len = strlen(source) + 1;
  195.   while (*source == 32)                 // I dislike spaces
  196.     memcpy(source, source + 1, source_len--);
  197.   source_len--;
  198.  
  199.   for (pos = 0; pos < source_len; pos+= 0)
  200.   {
  201.     c1 = *(source + pos);
  202.     found = 0;
  203.  
  204.     if (pos == 0 && c1 == '<')
  205.     {
  206.       part = 1;                         // return lowbyte
  207.       found = 1;
  208.       pos++;
  209.     }
  210.     if (pos == 0 && c1 == '>')
  211.     {
  212.       part = 2;                         // return highbyte
  213.       found = 1;
  214.       pos++;
  215.     }
  216.  
  217.     if ( (isalpha(c1)) || (c1 == '.') || (c1 == '!') || (c1 == '_') )
  218.     {                                   // found symbol
  219.       name_len = 0;
  220.       *name = 0;
  221.       name[name_len++] = *(source+pos++);
  222.       while ( (isalnum(*(source + pos)) || *(source + pos) == '_') )
  223.       {
  224.         if (name_len < 39)
  225.           name[name_len++] = *(source + pos);
  226.         pos++;
  227.       }
  228.       name[name_len] = 0;
  229.       r.r[0] = symbol_value(name, mode);
  230.       r.r[1] = name;
  231.       r.r[2] = 5;
  232.       os_swi(OS_ConvertHex4,&r);
  233.       dest[dest_len++] = '&';
  234.       memcpy(dest + dest_len,name,4);
  235.       dest_len += 4;
  236.       found = 1;
  237.     }
  238.  
  239.     if ( (c1 == '$') || (c1 == '&') )   // found hex number
  240.     {
  241.       dest[dest_len++]='&';
  242.       pos++;
  243.       while (isxdigit(*(source+pos)))
  244.         dest[dest_len++]=*(source+pos++);
  245.       found = 1;
  246.     }
  247.     if ( isdigit(c1) )                  // found decimal number
  248.     {
  249.       while (isdigit(*(source+pos)))
  250.         dest[dest_len++]=*(source+pos++);
  251.       found = 1;
  252.     }
  253.     if ( !found )                       // found another char
  254.     {
  255.       dest[dest_len++] = *(source+pos++);
  256.     }
  257.   }
  258.   r.r[0]=dest;
  259.   r.r[1]=0;
  260.   err = os_swix(OS_EvaluateExpression, &r);
  261.   if (err)
  262.   {
  263.     put_error(6, mode);
  264.     r.r[2] = pc;
  265.   }
  266.   if ( r.r[2] > 0xffff )
  267.   {
  268.     put_error(15, mode);
  269.     r.r[2] = r.r[2] & 0xffff;
  270.   }
  271.  
  272.   if (part)                             // low or highbyte
  273.   {
  274.     if (part == 1)
  275.       r.r[2] = r.r[2] & 0xff;
  276.     else
  277.       r.r[2] = r.r[2] / 0x100;
  278.   }
  279.   return r.r[2];
  280. }
  281.  
  282. //-------------------------------------------------------------
  283. int good_name(char *name)
  284. // tests if an name is good enough to become a symbol
  285. {
  286.   int pos, length, ret = 1;
  287.   length = strlen(name);
  288.   for (pos = 0; pos < length; pos++)
  289.    if ( !isalnum(*(name + pos)) && *(name+pos) != '_' ) ret = 0;
  290.   if (isdigit(*name)) ret = 0;
  291.   *(name + 39) = 0;
  292.   if (ret == 0)
  293.     put_error(10, 1);
  294.   return ret;
  295. }
  296.  
  297.  
  298. //-------------------------------------------------------------
  299. void set_symbol_value(char *symbol_name, int value)
  300. {
  301.   if (good_name(symbol_name))
  302.   {
  303.     if (nr_of_symbols > 998)
  304.       put_error(9, 1);
  305.     else
  306.     {
  307.       if ( symbol_value(symbol_name,0) == FULL )
  308.       {
  309.         memcpy(symbol[nr_of_symbols].name, symbol_name, 40);
  310.  
  311.         symbol[nr_of_symbols++].address = value;
  312.  
  313.         if ( !strcmp(symbol_name,"base") )
  314.         {
  315.           base_defined=1;
  316.           pc = base = value;
  317.         }
  318.       }
  319.       else
  320.         put_error(11, 1);                             //defined twice error
  321.     }
  322.   }
  323. }
  324.  
  325. //-------------------------------------------------------------
  326. void def_symbol(int loc)
  327. // analyses a symbol definition
  328. // else extern
  329. {
  330.   char *right_side,*left_side;
  331.   int  right_val;
  332.  
  333.   left_side = textline + 1;
  334.  
  335.   // .symbol=expression ?
  336.   right_side = strchr(textline,'=');
  337.  
  338.   if (right_side == NULL)
  339.   {
  340.     if (loc)
  341.       put_error(12, 1);
  342.     else
  343.       // a normal label like ".fred"
  344.       set_symbol_value(left_side, pc);
  345.   }
  346.   else
  347.   {
  348.     if (!loc)
  349.       put_error(14, 1);
  350.     else
  351.     {
  352.       *right_side=0;                                  // mark end of left side
  353.       right_side++;                                   // to start of right side
  354.  
  355.       while ( left_side[strlen(left_side)-1] == ' ' ) // remove spaces from the
  356.         left_side[strlen(left_side)-1] = 0;           // end of symbol name
  357.  
  358.       // now we'll try to interpret the right side
  359.       right_val=calc(right_side,1);
  360.       set_symbol_value(left_side, right_val);
  361.     }
  362.   }
  363. }
  364.  
  365. //-------------------------------------------------------------
  366. int search_mnemonic(char *mnemonic,int mode)
  367. // search for an instruction and returns array index
  368. // or 0xff if not found
  369. // if mode == 0 no "Illegal mode" error
  370. {
  371.   int mnemo_int,
  372.       array_index = 0,
  373.       ret = 0xff;
  374.   mnemo_int = ((mnemonic[0] << 16) + (mnemonic[1] << 8) + mnemonic[2])
  375.         & 0xffdfdfdf;
  376.   while ( (array_index < 80) && (ret == 0xff) )
  377.   {
  378.     if (mnemo_int == instruction[array_index].mnemonic)
  379.       ret = array_index;
  380.     else
  381.       array_index++;
  382.   }
  383.   if (ret == 0xff)
  384.     put_error(16, mode);
  385.   return ret;
  386. }
  387.  
  388. //-------------------------------------------------------------
  389. void translate(char *out_pointer, char *line, int mode)
  390. // translates a single instruction
  391. // if mode == 0 => no errors
  392. {
  393.   int length,
  394.       x_outside = 0,
  395.       y_outside = 0,
  396.       y_inside = 0,
  397.       zeropage = 0,
  398.       number,
  399.       instruct_nr;
  400.   signed int
  401.       branch;
  402.  
  403.   *out_pointer = 0;
  404.  
  405.   instruct_nr = search_mnemonic(line, mode);
  406.   memcpy(line, line + 3, strlen(line) - 2);
  407.  
  408.   if (instruct_nr != 0xff)
  409.   {
  410.     // remove spaces from the left side
  411.     branch = strlen(line);
  412.     while (*line == ' ')
  413.       memcpy(line, line + 1, branch--);
  414.  
  415.     length = strlen(line) + 1;
  416.     // no parameter ?
  417.     if (1 == length--)                        // akku or single
  418.       if (instruction[instruct_nr].code[0] != 0xff)
  419.       {
  420.         *out_pointer = 1;
  421.         *(out_pointer+1) = instruction[instruct_nr].code[0];
  422.       }
  423.       else
  424.         put_error(0, mode);                   // illegal address mode error
  425.     else
  426.     {
  427.       // analyse parameters
  428.  
  429.       // starts with '#' ?
  430.       if (*line == '#')
  431.       {                                       // direct
  432.         memcpy(line, line+1, length--);       // remove '#'
  433.  
  434.         // the rest must be a number
  435.         number = calc(line, mode);
  436.         if (number > 0xff)
  437.         {
  438.           put_error(2, mode);                 // higher than 0xff error
  439.           number &= 0xff;
  440.         }
  441.  
  442.         *out_pointer = 2;
  443.         *(out_pointer+1) = instruction[instruct_nr].code[1];
  444.         *(out_pointer+2) = number;
  445.  
  446.         if (*(out_pointer+1) == 0xff)
  447.           put_error(0, mode);                 // illegal address mode error
  448.  
  449.         length = 0;                           // done
  450.       }
  451.  
  452.       if (length > 1)
  453.       {                                       // "Z," is mark for zeropage mode
  454.         if ( toupper(*line) == 'Z'
  455.              && *(line + 1) == ',' )
  456.         {
  457.           zeropage = 1;
  458.           memcpy(line, line + 2, length);     // remove "Z,"
  459.           length -= 2;
  460.         }
  461.       }
  462.  
  463.       if (instruction[instruct_nr].code[8] != 0xff)
  464.       {
  465.         // branch...
  466.         if (length && !zeropage)
  467.         {
  468.           branch = calc(line, mode);
  469.           branch = branch - pc - 2;
  470.           if (branch > 0x7d || branch < -0x80)
  471.           {
  472.             put_error(3, mode);               // out of range error
  473.             branch = 0;
  474.           }
  475.           length = 0;                         // done
  476.           *out_pointer = 2;
  477.           *(out_pointer+1) = instruction[instruct_nr].code[8];
  478.           *(out_pointer+2) = branch;
  479.         }
  480.         else
  481.           put_error(0, mode);                 // illegal address mode error
  482.       }
  483.  
  484.       if (length > 1)
  485.       {
  486.         // end == ",x" ?
  487.         if ( toupper(*(line + length - 1)) == 'X'
  488.              && *(line + length - 2) == ',' )
  489.         {
  490.            x_outside = 1;                     // something,X
  491.            *(line + (length -= 2)) = 0;       // remove ",X"
  492.         }
  493.       }
  494.  
  495.       if (length > 1)
  496.       {
  497.         // end == ",y" ?
  498.         if ( toupper(*(line + length - 1)) == 'Y'
  499.              && *(line + length - 2) == ',' )
  500.         {
  501.            y_outside = 1;                     // something,Y
  502.            *(line + (length -= 2)) = 0;       // remove ",Y"
  503.         }
  504.       }
  505.  
  506.       // line could contain:
  507.       // case 1: "(expression)" for <absolute indirect> or <(indirect),y>
  508.       // case 2: "expression" for <zeropage [,x|,y]> or <absolute [,x|,y]>
  509.       // case 3: "(expression,x)" for <(indirect,x)>
  510.       if (length > 0)
  511.       {
  512.         if (*line == '(')
  513.         {
  514.            if (line[length-1] == ')')
  515.            {
  516.              // remove brackets
  517.              line[--length] = 0;
  518.              memcpy(line, line + 1, length--);
  519.  
  520.              if ( toupper(*(line + length - 1)) == 'X'
  521.                  && *(line + length - 2) == ',' )
  522.              {
  523.                // case 3: e.g. ADC ($02,X)
  524.                *(line + (length -= 2)) = 0;       // remove ",X"
  525.                number = calc(line, mode);
  526.  
  527.                if (number < 0x100
  528.                    && instruction[instruct_nr].code[9] != 0xff)
  529.                {
  530.                  length = 0;
  531.                  *out_pointer = 2;
  532.                  *(out_pointer+1) = instruction[instruct_nr].code[9];
  533.                  *(out_pointer+2) = number;
  534.                }
  535.              }
  536.              else
  537.              {
  538.                // case 1
  539.                number = calc(line, mode);
  540.                if (y_outside && number < 0x100
  541.                    && instruction[instruct_nr].code[10] != 0xff)
  542.                {
  543.                  // e.g. ADC ($02),Y
  544.                  length = 0;
  545.                  *out_pointer = 2;
  546.                  *(out_pointer+1) = instruction[instruct_nr].code[10];
  547.                  *(out_pointer+2) = number;
  548.                }
  549.                else
  550.                  if (!y_outside && !zeropage
  551.                      && instruction[instruct_nr].code[11] != 0xff)
  552.                  {
  553.                    // e.g. JMP ($1000)
  554.                    length = 0;
  555.                    *out_pointer = 3;
  556.                    *(out_pointer+1) = instruction[instruct_nr].code[11];
  557.                    *(out_pointer+2) = number & 0xff;
  558.                    *(out_pointer+3) = number >> 8;
  559.                  }
  560.              }
  561.  
  562.              if (*out_pointer == 0)
  563.              {
  564.                length = 0;
  565.                put_error(0, mode);            // illegal address mode error
  566.              }
  567.            }
  568.            else
  569.            {
  570.              put_error(5, mode);              // missing ')' error
  571.              length = 0;
  572.              *out_pointer = 0;
  573.            }
  574.         }
  575.         else
  576.         // case 2...
  577.         {
  578.           number = calc(line, mode);
  579.  
  580.           if (number > 0xffff)
  581.           {
  582.             put_error(4, mode);               // overflow error
  583.             number &= 0xffff;
  584.           }
  585.           if (number > 0xff && zeropage)
  586.           {
  587.             put_error(2, mode);
  588.             number &= 0xff;
  589.           }
  590.  
  591.           // all possibilities of case 2 are tested...
  592.           if (zeropage && !y_outside && !x_outside
  593.               && instruction[instruct_nr].code[2] != 0xff)
  594.           {
  595.             // e.g. "LDA $02"
  596.             length = 0;                       // done
  597.             *out_pointer = 2;
  598.             *(out_pointer+1) = instruction[instruct_nr].code[2];
  599.             *(out_pointer+2) = number;
  600.           }
  601.           else
  602.             if (zeropage && !y_outside && x_outside
  603.                 && instruction[instruct_nr].code[3] != 0xff)
  604.             {
  605.               // e.g. "LDA $02,X"
  606.               length = 0;                     // done
  607.               *out_pointer = 2;
  608.               *(out_pointer+1) = instruction[instruct_nr].code[3];
  609.               *(out_pointer+2) = number;
  610.             }
  611.             else
  612.               if (zeropage && y_outside && !x_outside
  613.                   && instruction[instruct_nr].code[4] != 0xff)
  614.               {
  615.                 // e.g. "LDX $02,Y"
  616.                 length = 0;
  617.                 *out_pointer = 2;
  618.                 *(out_pointer+1) = instruction[instruct_nr].code[4];
  619.                 *(out_pointer+2) = number;
  620.               };
  621.  
  622.           // if length > 0 => no zeropage mode is possible
  623.           if (length > 0)
  624.           {
  625.             if (!y_outside && !x_outside
  626.                 && instruction[instruct_nr].code[5] != 0xff)
  627.             {
  628.               // e.g. "LDA $1000"
  629.               length = 0;
  630.               *out_pointer = 3;
  631.               *(out_pointer+1) = instruction[instruct_nr].code[5];
  632.               *(out_pointer+2) = number & 0xff;
  633.               *(out_pointer+3) = number >> 8;
  634.             }
  635.             else
  636.               if (!y_outside && x_outside
  637.                   && instruction[instruct_nr].code[6] != 0xff)
  638.               {
  639.                 // e.g. "LDA $1000,X"
  640.                 length = 0;
  641.                 *out_pointer = 3;
  642.                 *(out_pointer+1) = instruction[instruct_nr].code[6];
  643.                 *(out_pointer+2) = number & 0xff;
  644.                 *(out_pointer+3) = number >> 8;
  645.               }
  646.               else
  647.                 if (y_outside && !x_outside
  648.                     && instruction[instruct_nr].code[7] != 0xff)
  649.                 {
  650.                   // e.g. "LDA $1000,Y"
  651.                   length = 0;
  652.                   *out_pointer = 3;
  653.                   *(out_pointer+1) = instruction[instruct_nr].code[7];
  654.                   *(out_pointer+2) = number & 0xff;
  655.                   *(out_pointer+3) = number >> 8;
  656.                 }
  657.           }
  658.  
  659.           // Something left?
  660.           if (length > 0)
  661.           {
  662.             *out_pointer = 0;
  663.             put_error(0, mode);               // illegal address mode error
  664.           }
  665.         }
  666.       }
  667.     }
  668.   }
  669. }          // brackets rule :-)
  670.  
  671. //-------------------------------------------------------------
  672. void assemble(FILE *in_file, char* in_filename)
  673. {
  674.   int  found,
  675.        type,
  676.        len,
  677.        count;
  678.   char mem_dump[4]; // [0] contains length of translated instruction
  679.                     // [1]..[3] instruction
  680.   nr_of_symbols = 0;
  681.   pc = 0;
  682.   base_defined = 0;
  683.   base = 0;
  684.   last_error_file = -1;
  685.  
  686.   /****************************************/
  687.   /*               pass 1                 */
  688.   /****************************************/
  689.   fprintf(error_file, "\nSource file: %s\n\n", in_filename);
  690.  
  691.   error_counter = 0;
  692.   status("Assembling: Pass 1");
  693.  
  694.   line_nr = 0;
  695.   while (getline(in_file))
  696.   {
  697.     pc &= 0xffff;
  698.  
  699.     found = 0;
  700.     if (textline[0] == '.')
  701.     {
  702.       def_symbol(0);                   // intern symbols
  703.       found = 1;
  704.     }
  705.     if (textline[0] == '!')
  706.     {
  707.       def_symbol(1);                   // extern symbols
  708.       found = 1;
  709.     }
  710.  
  711.     if (*textline == '/')              // assembler commands
  712.     {
  713.       if (!strcmp(textline+1,"align"))
  714.       {
  715.         if (pc & 0xff)
  716.           pc = (pc & FULL-0xff) + 0x100; // calculate aligned address
  717.         found = 1;
  718.       }
  719.       else
  720.       {
  721.         if (textline[1] == 'b' && textline[2] == 'y'
  722.             && textline[3] == 32)
  723.         {
  724.           found = strtok(textline+3, ",");
  725.           do
  726.           {
  727.             pc++;
  728.             found = strtok(NULL, ",");
  729.           }
  730.           while (found != NULL);
  731.           found = 1;
  732.         }
  733.         else
  734.         {
  735.           if ( (textline[1] == 's' && textline[2] == 'c')
  736.               || (textline[1] == 't' && textline[2] == 'x') )
  737.           {                                   // found "/tx" or "/sc"
  738.             len = strlen(textline);
  739.             if (textline[len - 1] == '\"')
  740.             {
  741.               for (count = 3; count < len; count++)
  742.                 if (textline[count] == '\"')
  743.                 {
  744.                   found = count;
  745.                   count = 256;
  746.                 }
  747.               if (len != found + 1)
  748.                 pc += (len - found - 2);
  749.             }
  750.             found = 1;
  751.           }
  752.         }
  753.       }
  754.     }
  755.  
  756.     // anything else must be an mnemonic
  757.     if (!found)
  758.     {
  759.       translate(mem_dump, textline, 0);
  760.       pc += mem_dump[0];
  761.     }
  762.   }
  763.  
  764.   /****************************************/
  765.   /*               pass 2                 */
  766.   /****************************************/
  767.   fseek (in_file, 0, SEEK_SET);                // back to start
  768.  
  769.   status("Assembling: Pass 2");
  770.  
  771.   if (base_defined)
  772.   {
  773.     if (transfer_enabled)
  774.     {
  775.       fputc(0, out_file);
  776.       fputc(255, out_file);
  777.     }
  778.  
  779.     fputc(base & 0xff, out_file);
  780.     fputc(base >> 8, out_file);
  781.  
  782.     if (transfer_enabled)
  783.     {
  784.       fputc(pc & 0xff, out_file);
  785.       fputc(pc >> 8, out_file);
  786.       fputc(base & 0xff, out_file);
  787.       fputc(base >> 8, out_file);
  788.       fputc(pc & 0xff, out_file);
  789.       fputc(pc >> 8, out_file);
  790.     }
  791.  
  792.     line_nr = 0;
  793.     pc = base;
  794.     while (getline(in_file))
  795.     {
  796.       found = 0;
  797.       if (textline[0] == '.' || textline[0] == '!')
  798.         found = 1;
  799.  
  800.       if (*textline == '/')                    // assembler commands
  801.       {
  802.         if (!strcmp(textline+1,"align"))
  803.         {
  804.           while (pc & 0xff)
  805.           {
  806.             fputc(0xEA, out_file);
  807.             pc++;
  808.           }
  809.           found = 1;
  810.         }
  811.         else
  812.         {                                      // "/by ..." found
  813.           if (textline[1] == 'b' && textline[2] == 'y'
  814.               && textline[3] == 32)
  815.           {
  816.             found = strtok(textline+3, ",");
  817.             do
  818.             {
  819.               count = calc( (char *)found, 1);
  820.               if (count < 0x100)
  821.               {
  822.                 pc++;
  823.                 fputc(count, out_file);
  824.               }
  825.               else
  826.                 put_error(2, 1);
  827.               found = strtok(NULL, ",");
  828.             }
  829.             while (found != NULL);
  830.             found = 1;
  831.           }
  832.           else
  833.           {                                    // "/by" without parameters
  834.             if (textline[1] == 'b' && textline[2] == 'y')
  835.             {
  836.               put_error(18, 1);
  837.               found = 1;
  838.             }
  839.             else
  840.             {                                  // "/sc" or "/tx" found
  841.               if ( (textline[1] == 's' && textline[2] == 'c')
  842.                   || (textline[1] == 't' && textline[2] == 'x') )
  843.               {
  844.                 len = strlen(textline);
  845.                 if (textline[len - 1] == '\"')
  846.                 {
  847.                   for (count = 3; count < len; count++)
  848.                     if (textline[count] == '\"')
  849.                     {
  850.                       found = count;
  851.                       count = 256;
  852.                     }
  853.                   if (len != found + 1)
  854.                     pc += (strlen(textline) - found - 2);
  855.                   else
  856.                     put_error (19, 1);        // case: »/tx "«
  857.  
  858.                   if (textline[1] == 't')
  859.                     type = 0;                 // "/tx" => type = 1;
  860.                   else
  861.                     type = 1;
  862.                                               // send text
  863.                   len -= 1;
  864.                   for (count = found + 1; count < len; count++)
  865.                     fputc ( chr [textline[count]] [type], out_file);
  866.                 }
  867.                 else
  868.                   put_error(19, 1);
  869.                 found = 1;
  870.               }
  871.             }
  872.           }
  873.         }
  874.       }
  875.  
  876.       if (!found)
  877.       {
  878.         // it's a mnemonic line :-)
  879.         translate(mem_dump, textline, 1);
  880.         pc += mem_dump[0];
  881.         for (count = 0; count < mem_dump[0]; count++)
  882.           fputc(mem_dump[count+1], out_file);
  883.         if (pc > 0xffff)
  884.         {
  885.           put_error(17, 1);                   // pc overflow error
  886.           pc &= 0xffff;
  887.         }
  888.       }
  889.     }
  890.     fprintf(error_file, "\nEntries: %d\n", error_counter);
  891.     fprintf(error_file, "\n%d lines assembled.\n", line_nr);
  892.   }
  893.   else
  894.     put_error(13, 1);
  895.   status("Assembling: Pass 2");
  896. }
  897.  
  898. //-------------------------------------------------------------
  899. void transfer_file(void)
  900. {
  901.   int count, obj_length;
  902.   char *buffer;
  903.   os_filestr p;
  904.  
  905.   p.action = 17;
  906.   p.objname = "<6502-XAss$Dir>.Scrap.Object";
  907.   os_file(&p);
  908.  
  909.   if (p.action == 1 && p.startaddr > 0)
  910.   {
  911.      obj_length = p.startaddr;
  912.      buffer = (char *) malloc(obj_length);
  913.      if (buffer)
  914.      {
  915.        p.action = 16;
  916.        p.loadaddr = buffer;
  917.        p.execaddr = 0;
  918.        os_file(&p);
  919.  
  920.        os_vdu(2);
  921.        for (count = 0; count < obj_length; count++)
  922.        {
  923.          os_vdu(1);
  924.          os_vdu( *(buffer + count) );
  925.        }
  926.        os_vdu(3);
  927.      }
  928.      else
  929.        status("Out of memory");
  930.      free(buffer);
  931.   }
  932.   else
  933.     status("Transfer file error");
  934. }
  935.  
  936.