home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK3 / DFUE_100 / FAMISRC.ZIP / SASMSRC.ZIP / SNESASM.PAS
Pascal/Delphi Source File  |  1993-11-07  |  49KB  |  2,078 lines

  1. {$M 49152, 0, 655360}
  2. program SNES_Cross_Assembler;
  3.  
  4. const
  5.   max_labels=8192;
  6.   label_name_size=18;
  7.   mne_count=109;
  8.   mne_word: array [0..mne_count-1] of string [3]=(
  9.     'BRK','CLC','CLD','CLI','CLV','DEX','DEY','INX',
  10.     'INY','NOP','PHA','PHB','PHD','PHK','PHP','PHX',
  11.     'PHY','PLA','PLB','PLD','PLP','PLX','PLY','RTI',
  12.     'RTL','RTS','SEC','SED','SEI','STP','SWA','TAD',
  13.     'TAS','TAX','TAY','TCD','TCS','TDA','TDC','TSA',
  14.     'TSC','TSX','TXA','TXS','TXY','TYA','TYX','WAI',
  15.     'XBA','XCE','ADC','AND','CMP','EOR','LDA','ORA',
  16.     'SBC','STA','STX','STY','ASL','LSR','ROL','ROR',
  17.     'DEC','INC','CPX','CPY','LDX','LDY','JMP','JML',
  18.     'JSR','JSL','BIT','BCC','BCS','BEQ','BMI','BNE',
  19.     'BPL','BRA','BVC','BVS','BRL','MVN','MVP','PEA',
  20.     'PEI','PER','REP','SEP','STZ','TRB','TSB','ORG',
  21.     'INT','BIN','PAD','EQU','DCB','DCW','DSB','DSW',
  22.     'DB','DW','NAM','COU','VER');
  23.   mne_type: array [0..mne_count-1] of byte=(
  24.     $00,$00,$00,$00,$00,$00,$00,$00,
  25.     $00,$00,$00,$00,$00,$00,$00,$00,
  26.     $00,$00,$00,$00,$00,$00,$00,$00,
  27.     $00,$00,$00,$00,$00,$00,$00,$00,
  28.     $00,$00,$00,$00,$00,$00,$00,$00,
  29.     $00,$00,$00,$00,$00,$00,$00,$00,
  30.     $00,$00,$01,$01,$01,$01,$01,$01,
  31.     $01,$01,$02,$02,$03,$03,$03,$03,
  32.     $04,$04,$05,$05,$06,$06,$07,$08,
  33.     $09,$0A,$0B,$0C,$0C,$0C,$0C,$0C,
  34.     $0C,$0C,$0C,$0C,$0D,$0E,$0E,$0F,
  35.     $10,$11,$11,$11,$12,$13,$13,$FF,
  36.     $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,
  37.     $FF,$FF,$FF,$FF,$FF);
  38.   mne_opcode: array [0..mne_count-1] of byte=(
  39.     $00,$18,$D8,$58,$B8,$CA,$88,$E8,
  40.     $C8,$EA,$48,$8B,$0B,$4B,$08,$DA,
  41.     $5A,$68,$AB,$2B,$28,$FA,$7A,$40,
  42.     $6B,$60,$38,$F8,$78,$DB,$EB,$5B,
  43.     $1B,$AA,$A8,$5B,$1B,$7B,$7B,$3B,
  44.     $3B,$BA,$8A,$9A,$9B,$98,$BB,$CB,
  45.     $EB,$FB,$61,$21,$C1,$41,$A1,$01,
  46.     $E1,$81,$86,$84,$06,$46,$26,$66,
  47.     $C6,$E6,$E0,$C0,$A2,$A0,$4C,$DC,
  48.     $20,$22,$24,$90,$B0,$F0,$30,$D0,
  49.     $10,$80,$50,$70,$82,$54,$44,$F4,
  50.     $D4,$62,$C2,$E2,$64,$14,$04,$00,
  51.     $00,$00,$00,$00,$00,$00,$00,$00,
  52.     $00,$00,$00,$00,$00);
  53.  
  54. type
  55.   label_rec = record
  56.     name: string [label_name_size];
  57.     address: longint;
  58.     pass: byte;
  59.   end;
  60.  
  61. var
  62.   src_name: string;
  63.   src_file: text;
  64.   obj_name: string;
  65.   obj_file: file;
  66.   smc_name: string;
  67.   smc_file: file;
  68.   err_name: string;
  69.   err_file: text;
  70.   lst_name: string;
  71.   lst_file: text;
  72.   lab_name: string;
  73.   lab_file: text;
  74.  
  75.   label_index: longint;
  76.   label_list: array [0..max_labels] of ^label_rec;
  77.   label_: label_rec;
  78.   last_label: longint;
  79.  
  80.   no_byte: byte;
  81.   no_long: byte;
  82.   no_word: byte;
  83.   err_flag: byte;
  84.   write_op: byte;
  85.  
  86.   pass: byte;
  87.   name: string;
  88.   country: byte;
  89.   version: byte;
  90.   line_index: longint;
  91.   start_address: longint;
  92.   address_index: longint;
  93.   error_index: longint;
  94.   opcode_list: string;
  95.   opcode_count: longint;
  96.   f1, f2, f3, f4: string;
  97.   _label, operator, operand, comment: string;
  98.  
  99.   show_listings: byte;
  100.   save_lab: byte;
  101.   save_lst: byte;
  102.   show_lines: byte;
  103.  
  104. function upper (s: string): string;
  105. var b: byte;
  106. begin
  107.   for b:=1 to length (s) do
  108.     s [b]:=upcase (s [b]);
  109.   upper:=s;
  110. end;
  111.  
  112. function inttostr (l: longint): string;
  113. var s: string;
  114. begin
  115.   str (l, s);
  116.   inttostr:=s;
  117. end;
  118.  
  119. function dectohex (l: longint; w: byte): string;
  120. const hextable: string=('0123456789ABCDEF');
  121. var s: string;
  122.     b: byte;
  123. begin
  124.   s:='';
  125.   for b:=(w-1) downto 0 do
  126.     s:=s+hextable [1+(l shr (b*4)) and 15];
  127.   dectohex:=s;
  128. end;
  129.  
  130. function hextodec (s: string): longint;
  131. const hextable='0123456789ABCDEF';
  132. var l, m: longint;
  133.     b: byte;
  134. begin
  135.   l:=0;
  136.   m:=1;
  137.   for b:=length (s) downto 1 do
  138.   begin
  139.     l:=l+(pos (upper (s [b]), hextable)-1)*m;
  140.     m:=m*16;
  141.   end;
  142.   hextodec:=l;
  143. end;
  144.  
  145. function bintodec (s: string): longint;
  146. const bintable='01';
  147. var l,m: longint;
  148.     b: byte;
  149. begin
  150.   l:=0;
  151.   m:=1;
  152.   for b:=length (s) downto 1 do
  153.   begin
  154.     l:=l+(pos (s [b], bintable)-1)*m;
  155.     m:=m*2;
  156.   end;
  157.   bintodec:=l;
  158. end;
  159.  
  160. procedure kill_leadspace (var s: string);
  161. var b: byte;
  162. begin
  163.   b:=1;
  164.   while (s [b]=' ') do inc (b);
  165.   delete (s, 1, b-1);
  166. end;
  167.  
  168. procedure kill_followspace (var s: string);
  169. var b: byte;
  170. begin
  171.   b:=length (s);
  172.   while (s [b]=' ') do dec (b);
  173.   delete (s, b+1, length (s)-b);
  174. end;
  175.  
  176. function adj_left (s: string; l: byte; c: char): string;
  177. begin
  178.   while (length (s) < l) do
  179.     s:=s+c;
  180.   adj_left:=s;
  181. end;
  182.  
  183. function adj_right (s: string; l: byte; c: char): string;
  184. begin
  185.   while (length (s) < l) do
  186.     s:=c+s;
  187.   adj_right:=s;
  188. end;
  189.  
  190. procedure show_error (e: string);
  191. begin
  192.   writeln ('ERROR in line ', line_index,': ', e);
  193.   writeln (err_file, 'ERROR in line ', line_index,': ', e);
  194.   inc (error_index);
  195. end;
  196.  
  197. procedure get_label_mem;
  198. var w: word;
  199.     l: label_rec;
  200. begin
  201.   l.name:='';
  202.   l.address:=0;
  203.   l.pass:=0;
  204.   for w:=0 to max_labels do
  205.   begin
  206.     getmem (label_list [w], sizeof (label_rec));
  207.     label_list [w]^:=l;
  208.   end;
  209.   label_index:=0;
  210. end;
  211.  
  212. procedure free_label_mem;
  213. var w: word;
  214. begin
  215.   for w:=0 to max_labels do
  216.     freemem (label_list [w], sizeof (label_rec));
  217.   label_index:=0;
  218. end;
  219.  
  220. procedure save_label (name: string; address: longint; pass: byte; w: word);
  221. var l: label_rec;
  222. begin
  223.   l.name:=name;
  224.   l.address:=address;
  225.   l.pass:=pass;
  226.   label_list [w]^:=l;
  227. end;
  228.  
  229. procedure save_new_label (name: string; address: longint; pass: byte);
  230. var l: label_rec;
  231. begin
  232.   save_label (name, address, pass, label_index);
  233.   inc (label_index);
  234. end;
  235.  
  236. function find_label (s: string): word;
  237. var w: word;
  238.     l: label_rec;
  239. begin
  240.   s:=upper (copy (s, 1, label_name_size));
  241.   w:=0;
  242.   repeat
  243.     l:=label_list [w]^;
  244.     inc (w);
  245.   until (w >= label_index) or (l.name = s);
  246.   if (l.name = s) then
  247.   begin
  248.     dec (w);
  249.     find_label:=w;
  250.   end else find_label:=$ffff;
  251. end;
  252.  
  253. procedure parse_line (l: string; var f1, f2, f3, f4: string);
  254. var b: byte;
  255.     s, t: string;
  256.     quote: byte;
  257. begin
  258.   f1:='';
  259.   f2:='';
  260.   f3:='';
  261.   f4:='';
  262.   s:=l;
  263.   while (pos (#9, s) > 0) do
  264.   begin
  265.     b:=pos (#9, s);
  266.     delete (s, b, 1);
  267.     insert ('        ', s, b);
  268.   end;
  269.  
  270.   kill_leadspace (s);
  271.   kill_followspace (s);
  272.  
  273.   t:='';
  274.   b:=1;
  275.   quote:=0;
  276.   repeat
  277.     if (s [b] = #39) or (s = '"') then quote:=quote xor 1;
  278.     if (s [b] = ';') and (quote = 0) then t:=';';
  279.     inc (b);
  280.   until (b > length (s)) or (t = ';');
  281.   if (t = ';') then dec (b);
  282.   if (b = 1) then
  283.   begin
  284.     f4:=s;
  285.     delete (f4, 1, 1);
  286.     kill_leadspace (f4);
  287.     exit;
  288.   end;
  289.   if (b > 0) and (b <= length (s)) then
  290.   begin
  291.     f4:=s;
  292.     delete (f4, 1, b);
  293.     delete (s, b, length (s)-b+1);
  294.   end;
  295.  
  296.   b:=pos (' ', s);
  297.   if (b = 0) then
  298.   begin
  299.     f1:=s;
  300.     s:='';
  301.   end else
  302.   begin
  303.     f1:=copy (s, 1, b-1);
  304.     delete (s, 1, b);
  305.     kill_leadspace (s);
  306.   end;
  307.  
  308.   t:='';
  309.   quote:=0;
  310.   b:=1;
  311.   repeat
  312.     if (s [b] = #39) or (s [b] = '"') then quote:=quote xor 1;
  313.     if (s [b] = ' ') and (quote = 0) then t:=' ';
  314.     inc (b);
  315.   until (b > length (s)) or (t = ' ');
  316.   if (t = ' ') then dec (b);
  317.   if (b = 0) then
  318.   begin
  319.     f2:=s;
  320.     s:='';
  321.   end else
  322.   begin
  323.     f2:=copy (s, 1, b-1);
  324.     delete (s, 1, b);
  325.     kill_leadspace (s);
  326.   end;
  327.  
  328.   f3:=s;
  329.  
  330.   kill_followspace (f1);
  331.   kill_followspace (f2);
  332.   kill_followspace (f3);
  333.  
  334.   if (length (f1) = 3) or
  335.      ((length (f1) = 5) and (f1 [4] = '.')) then
  336.      begin
  337.        t:=upper (copy (f1, 1, 3));
  338.        b:=0;
  339.        repeat
  340.          inc (b);
  341.        until (b = mne_count) or (t = mne_word [b]);
  342.        if (b < mne_count) then
  343.        begin
  344.          f3:=f2+f3;
  345.          f2:=f1;
  346.          f1:='';
  347.        end;
  348.      end;
  349.   if ((length (f1) = 2) and ((upper (f1) = 'DC') OR (upper (f1) = 'DS'))) or
  350.      ((length (f1) = 4) and ((upper (copy (f1, 1, 3)) = 'DC.') or (upper (copy (f1, 1, 3)) = 'DC.'))) then
  351.   begin
  352.     f3:=f2+' '+f3;
  353.     f2:=f1;
  354.     f1:='';
  355.   end;
  356. end;
  357.  
  358. procedure convert_negatives (var equ: string);
  359. var b: byte;
  360.     s: string;
  361. begin
  362.   b:=length (equ);
  363.   while (b > 0) do
  364.   begin
  365.     if (equ [b] = '-') then insert ('+', equ, b);
  366.     dec (b);
  367.   end;     
  368. end;
  369.  
  370. procedure convert_hex (var equ: string);
  371. var b, b1, b2: byte;
  372.     n: longint;
  373.     s: string;
  374.     e: integer;
  375. begin
  376.   while (pos ('$', equ) > 0) do
  377.   begin
  378.     b:=pos ('$', equ);
  379.     b1:=b;
  380.     b2:=b;
  381.     repeat
  382.       inc (b2);
  383.     until (b2 > length (equ)) or (equ [b2] in ['+','*','/']);
  384.     s:=copy (equ, b1+1, b2-b1-1);
  385.     n:=hextodec (s);
  386.     delete (equ, b1, b2-b1);
  387.     str (n, s);
  388.     insert (s, equ, b1);
  389.   end;
  390. end;
  391.  
  392. procedure convert_bin (var equ: string);
  393. var b, b1, b2: byte;
  394.     n: longint;
  395.     s: string;
  396.     e: integer;
  397. begin
  398.   while (pos ('%', equ) > 0) do
  399.   begin
  400.     b:=pos ('%', equ);
  401.     b1:=b;
  402.     b2:=b;
  403.     repeat
  404.       inc (b2);
  405.     until (b2 > length (equ)) or not (equ [b2] in ['0','1']);
  406.     s:=copy (equ, b1+1, b2-b1-1);
  407.     n:=bintodec (s);
  408.     delete (equ, b1, b2-b1);
  409.     str (n, s);
  410.     insert (s, equ, b1);
  411.   end;
  412. end;
  413.  
  414. procedure convert_asterisk (var equ: string);
  415. var b: byte;
  416.     s: string;
  417.     e: integer;
  418. begin
  419.   b:=length (equ);
  420.   while (b > 0) do
  421.   begin
  422.     if (equ [b] = '*') then
  423.     begin
  424.       if (equ [b-1] in ['+','*','/']) or
  425.          (equ [b+1] in ['+','*','/']) then
  426.       begin
  427.         delete (equ, b, 1);
  428.         str (address_index, s);
  429.         insert (s, equ, b);
  430.       end;
  431.     end;
  432.     dec (b);
  433.   end;
  434. end;
  435.  
  436. procedure convert_labels (var equ: string);
  437. var b, b1, b2, e: byte;
  438.     n: longint;
  439.     s: string;
  440. begin
  441.   b:=length (equ);
  442.   while (b > 0) do
  443.   begin
  444.     if (equ [b] = '_') or
  445.        ((equ [b] >= 'A') and (equ [b] <= 'Z')) or
  446.        ((equ [b] >= 'a') and (equ [b] <= 'z')) then
  447.     begin
  448.       b1:=b;
  449.       repeat
  450.         dec (b1);
  451.       until (b1 = 0) or (equ [b1] in ['+','*','/','<','>']);
  452.       inc (b1);
  453.       if (equ [b1] = '_') or
  454.        ((equ [b1] >= 'A') and (equ [b1] <= 'Z')) or
  455.        ((equ [b1] >= 'a') and (equ [b1] <= 'z')) then
  456.       begin
  457.         b2:=b1;
  458.         repeat
  459.           inc (b2);
  460.         until (b2 > length (equ)) or (equ [b2] in ['+','*','/','<','>']);
  461.         s:=copy (equ, b1, b2-b1);
  462.         e:=0;
  463.         delete (equ, b1, b2-b1);
  464.         n:=find_label (s);
  465.         if (n < $ffff) then n:=label_list [n]^.address else
  466.         begin
  467.           n:=0;
  468.           inc (err_flag);
  469.           if (pass = 2) then show_error ('Undefined label in '+s);
  470.         end;
  471.         str (n, s);
  472.         insert (s, equ, b1);
  473.       end;
  474.       b:=b1;
  475.     end;
  476.     dec (b);
  477.   end;     
  478. end;
  479.  
  480. procedure find_multiply (var equ: string);
  481. var b, b1, b2: byte;
  482.     n, n1, n2: longint;
  483.     s: string;
  484.     e: integer;
  485. begin
  486.   while (pos ('*', equ) > 0) do
  487.   begin
  488.     b:=pos ('*', equ);
  489.     b1:=b;
  490.     repeat
  491.       dec (b1);
  492.     until (b1 = 0) or (equ [b1] in ['+','*','/']);
  493.     b2:=b;
  494.     repeat
  495.       inc (b2);
  496.     until (b2 > length (equ)) or (equ [b2] in ['+','*','/']);
  497.     s:=copy (equ, b1+1, b-b1-1);
  498.     val (s, n1, e);
  499.     s:=copy (equ, b+1, b2-b-1);
  500.     val (s, n2, e);
  501.     delete (equ, b1+1, b2-b1-1);
  502.     n:=n1*n2;
  503.     str (n, s);
  504.     insert (s, equ, b1+1);
  505.   end;
  506. end;
  507.  
  508. procedure find_divide (var equ: string);
  509. var b, b1, b2: byte;
  510.     n, n1, n2: longint;
  511.     s: string;
  512.     e: integer;
  513. begin
  514.   while (pos ('/', equ) > 0) do
  515.   begin
  516.     b:=pos ('/', equ);
  517.     b1:=b;
  518.     repeat
  519.       dec (b1);
  520.     until (b1 = 0) or (equ [b1] in ['+','*','/']);
  521.     b2:=b;
  522.     repeat
  523.       inc (b2);
  524.     until (b2 > length (equ)) or (equ [b2] in ['+','*','/']);
  525.     s:=copy (equ, b1+1, b-b1-1);
  526.     val (s, n1, e);
  527.     s:=copy (equ, b+1, b2-b-1);
  528.     val (s, n2, e);
  529.     delete (equ, b1+1, b2-b1-1);
  530.     n:=n1 div n2;
  531.     str (n, s);
  532.     insert (s, equ, b1+1);
  533.   end;
  534. end;
  535.  
  536. procedure find_add (var equ: string);
  537. var b, b1, b2: byte;
  538.     n, n1, n2: longint;
  539.     s: string;
  540.     e: integer;
  541. begin
  542.   while (pos ('+', equ) > 0) do
  543.   begin
  544.     b:=pos ('+', equ);
  545.     b1:=b;
  546.     repeat
  547.       dec (b1);
  548.     until (b1 = 0) or (equ [b1] in ['+','*','/']);
  549.     b2:=b;
  550.     repeat
  551.       inc (b2);
  552.     until (b2 > length (equ)) or (equ [b2] in ['+','*','/']);
  553.     s:=copy (equ, b1+1, b-b1-1);
  554.     val (s, n1, e);
  555.     s:=copy (equ, b+1, b2-b-1);
  556.     val (s, n2, e);
  557.     delete (equ, b1+1, b2-b1-1);
  558.     n:=n1+n2;
  559.     str (n, s);
  560.     insert (s, equ, b1+1);
  561.   end;
  562. end;
  563.  
  564. function eval (equ: string): longint;
  565. var l: longint;
  566.     e: integer;
  567.     lobyte,hibyte: byte;
  568. begin
  569.   err_flag:=0;
  570.   if (equ = '-') then
  571.   begin
  572.     eval:=last_label;
  573.     exit;
  574.   end;
  575.   if (equ [1] = '<') then
  576.   begin
  577.     lobyte:=1;
  578.     delete (equ, 1, 1);
  579.   end else lobyte:=0;
  580.   if (equ [1] = '>') then
  581.   begin
  582.     hibyte:=1;
  583.     delete (equ, 1, 1);
  584.   end else hibyte:=0;
  585.   convert_negatives (equ);
  586.   convert_hex (equ);
  587.   convert_bin (equ);
  588.   convert_asterisk (equ);
  589.   convert_labels (equ);
  590.   find_multiply (equ);
  591.   find_divide (equ);
  592.   find_add (equ);
  593.   val (equ, l, e);
  594.   if (lobyte = 1) then eval:=lo(l) else
  595.     if (hibyte = 1) then eval:=hi(l) else
  596.       eval:=l;
  597. end;
  598.  
  599. procedure addr_immediate (mne_op: byte);
  600. var s: string;
  601.     l: longint;
  602. begin
  603.   opcode_list:=dectohex (mne_op, 2)+' ';
  604.   s:=copy (f3, 2, length (f3)-1);
  605.   l:=eval (s);
  606.   s:=copy (f2, 4, 2);
  607.   if ((s = '.L') or (s = '.W') or (s = '.V')) and (l > -32768) and (l < 65536) then
  608.   begin
  609.     opcode_count:=3;
  610.     opcode_list:=opcode_list+
  611.                  dectohex (l and 255, 2)+' '+
  612.                  dectohex ((l shr 8) and 255, 2);
  613.     exit;
  614.   end;
  615.   if (l > -128) and (l < 256) then
  616.   begin
  617.     opcode_count:=2;
  618.     opcode_list:=opcode_list+
  619.                  dectohex (l, 2);
  620.     exit;
  621.   end;
  622.   if (l > -32768) and (l < 65536) then
  623.   begin
  624.     opcode_count:=3;
  625.     opcode_list:=opcode_list+
  626.                  dectohex (l and 255, 2)+' '+
  627.                  dectohex ((l shr 8) and 255, 2);
  628.     exit;
  629.   end;
  630.   show_error ('Operand out of range '+operand);
  631.   opcode_list:=opcode_list+'00';
  632.   opcode_count:=2;
  633. end;
  634.  
  635. procedure addr_absolute (mne_op: byte);
  636. var s: string;
  637.     l: longint;
  638.     b: byte;
  639. begin
  640.   l:=eval (f3);
  641.   s:=copy (f2, 4, 2);
  642.   if (s = '.L') then
  643.   begin
  644.     opcode_count:=4;
  645.     opcode_list:='00 00 00 00';
  646.     if (no_long = 1) then
  647.     begin
  648.       show_error ('Absolute long addressing not valid for '+operator);
  649.       exit;
  650.     end;
  651.     if (l > -8388608) and (l < 16777216) then
  652.     begin
  653.       opcode_list:=dectohex (mne_op+$02, 2)+' '+
  654.                    dectohex (l and 255, 2)+' '+
  655.                    dectohex ((l shr 8) and 255, 2)+' '+
  656.                    dectohex ((l shr 16) and 255, 2);
  657.       exit;
  658.     end;
  659.     show_error ('Operand out of range '+operand+', requires $000000-$FFFFFF');
  660.     exit;
  661.   end;
  662.   if (s = '.W') then
  663.   begin
  664.     opcode_count:=3;
  665.     opcode_list:='00 00 00';
  666.     if (no_word = 1) then
  667.     begin
  668.       show_error ('Absolute addressing not valid for '+operator);
  669.       exit;
  670.     end;
  671.     if (l > -32768) and (l < 65536) then
  672.     begin
  673.       opcode_list:=dectohex (mne_op, 2)+' '+
  674.                    dectohex (l and 255, 2)+' '+
  675.                    dectohex ((l shr 8) and 255, 2);
  676.       exit;
  677.     end;
  678.     show_error ('Operand out of range '+operand+', requires $0000-$FFFF');
  679.     exit;
  680.   end;
  681.   if (s = '.B') then
  682.   begin
  683.     opcode_count:=2;
  684.     opcode_list:='00 00';
  685.     if (no_byte = 1) then
  686.     begin
  687.       show_error ('Direct addressing not valid for '+operator);
  688.       exit;
  689.     end;
  690.     if (l > -128) and (l < 256) then
  691.     begin
  692.       opcode_list:=dectohex (mne_op-$08, 2)+' '+
  693.                    dectohex (l and 255, 2);
  694.       exit;
  695.     end;
  696.     show_error ('Operand out of range '+operand+', requires $00-$FF');
  697.     exit;
  698.   end;
  699.  
  700.   if (l and $ff0000 = address_index and $ff0000) then l:=l and $00ffff;
  701.   opcode_count:=3;
  702.   opcode_list:='00 00 00';
  703.   if (err_flag > 0) then exit;
  704.   if (l > -128) and (l < 256) and (no_byte = 0) then
  705.   begin
  706.     opcode_count:=2;
  707.     opcode_list:=dectohex (mne_op-$08, 2)+' '+
  708.                  dectohex (l and 255, 2);
  709.     exit;
  710.   end;
  711.   if (l > -32768) and (l < 65536) and (no_word = 0) then
  712.   begin
  713.     opcode_count:=3;
  714.     opcode_list:=dectohex (mne_op, 2)+' '+
  715.                  dectohex (l and 255, 2)+' '+
  716.                  dectohex ((l shr 8) and 255, 2);
  717.     exit;
  718.   end;
  719.   if (l > -8388608) and (l < 16777216) and (no_long = 0) then
  720.   begin
  721.     opcode_count:=4;
  722.     opcode_list:=dectohex (mne_op+$02, 2)+' '+
  723.                  dectohex (l and 255, 2)+' '+
  724.                  dectohex ((l shr 8) and 255, 2)+' '+
  725.                  dectohex ((l shr 16) and 255, 2);
  726.     exit;
  727.   end;
  728.   show_error ('Operand out of range '+operand);
  729. end;
  730.  
  731. procedure addr_indirect (mne_op: byte);
  732. var s: string;
  733.     l: longint;
  734.     b: byte;
  735. begin
  736.   l:=eval (f3);
  737.   s:=copy (f2, 4, 2);
  738.   if (s = '.L') then
  739.   begin
  740.     opcode_count:=4;
  741.     opcode_list:='00 00 00 00';
  742.     if (no_long = 1) then
  743.     begin
  744.       show_error ('Direct indirect long addressing not valid for '+operator);
  745.       exit;
  746.     end;
  747.     if (l > -8388608) and (l < 16777216) then
  748.     begin
  749.       opcode_list:=dectohex (mne_op+$02, 2)+' '+
  750.                    dectohex (l and 255, 2)+' '+
  751.                    dectohex ((l shr 8) and 255, 2)+' '+
  752.                    dectohex ((l shr 16) and 255, 2);
  753.       exit;
  754.     end;
  755.     show_error ('Operand out of range '+operand+', requires $000000-$FFFFFF');
  756.     exit;
  757.   end;
  758.   if (s = '.W') then
  759.   begin
  760.     opcode_count:=3;
  761.     opcode_list:='00 00 00';
  762.     if (no_word = 1) then
  763.     begin
  764.       show_error ('Direct indirect addressing not valid for '+operator);
  765.       exit;
  766.     end;
  767.     if (l > -32768) and (l < 65536) then
  768.     begin
  769.       opcode_list:=dectohex (mne_op, 2)+' '+
  770.                    dectohex (l and 255, 2)+' '+
  771.                    dectohex ((l shr 8) and 255, 2);
  772.       exit;
  773.     end;
  774.     show_error ('Operand out of range '+operand+', requires $0000-$FFFF');
  775.     exit;
  776.   end;
  777.   if (s = '.B') then
  778.   begin
  779.     opcode_count:=2;
  780.     opcode_list:='00 00';
  781.     if (no_byte = 1) then
  782.     begin
  783.       show_error ('Direct indirect addressing not valid for '+operator);
  784.       exit;
  785.     end;
  786.     if (l > -128) and (l < 256) then
  787.     begin
  788.       opcode_list:=dectohex (mne_op-$08, 2)+' '+
  789.                    dectohex (l and 255, 2);
  790.       exit;
  791.     end;
  792.     show_error ('Operand out of range '+operand+', requires $00-$FF');
  793.     exit;
  794.   end;
  795.  
  796.   if (l > -128) and (l < 256) and (no_byte = 0) then
  797.   begin
  798.     opcode_count:=2;
  799.     opcode_list:=dectohex (mne_op-$08, 2)+' '+
  800.                  dectohex (l and 255, 2);
  801.     exit;
  802.   end;
  803.   if (l > -32768) and (l < 65536) and (no_word = 0) then
  804.   begin
  805.     opcode_count:=3;
  806.     opcode_list:=dectohex (mne_op, 2)+' '+
  807.                  dectohex (l and 255, 2)+' '+
  808.                  dectohex ((l shr 8) and 255, 2);
  809.     exit;
  810.   end;
  811.   if (l > -8388608) and (l < 16777216) and (no_long = 0) then
  812.   begin
  813.     opcode_count:=4;
  814.     opcode_list:=dectohex (mne_op+$02, 2)+' '+
  815.                  dectohex (l and 255, 2)+' '+
  816.                  dectohex ((l shr 8) and 255, 2)+' '+
  817.                  dectohex ((l shr 16) and 255, 2);
  818.     exit;
  819.   end;
  820.   show_error ('Operand out of range '+operand);
  821.   opcode_count:=2;
  822.   opcode_list:='00 00';
  823. end;
  824.  
  825. function find_addressing_mode (s: string): byte;
  826. begin
  827.   find_addressing_mode:=0;
  828.   if (s [1] = '#') then
  829.   begin
  830.     find_addressing_mode:=1;
  831.     exit;
  832.   end;
  833.   if (pos ('(', s) > 0) and (pos (')', s) > 0) then
  834.   begin
  835.     if (pos (',S),Y', s) > 0) then find_addressing_mode:=23 else
  836.       if (pos (',X)', s) > 0) then find_addressing_mode:=21 else
  837.         if (pos ('),Y', s) > 0) then find_addressing_mode:=22 else
  838.           if (pos (',', s) = 0) then find_addressing_mode:=20;
  839.     exit;
  840.   end;
  841.   if (pos ('[', s) > 0) and (pos (']', s) > 0) then
  842.   begin
  843.     if (pos (',S', s) > 0) or (pos (',X', s) > 0) then exit else
  844.       if (pos ('],Y', s) > 0) then find_addressing_mode:=32 else
  845.         if (pos (',Y', s) = 0) then find_addressing_mode:=30;
  846.     exit;
  847.   end;
  848.   if (pos (',X', s) > 0) then find_addressing_mode:=11 else
  849.     if (pos (',Y', s) > 0) then find_addressing_mode:=12 else
  850.       if (pos (',S', s) > 0) then find_addressing_mode:=13 else
  851.         if (pos (',', s) = 0) then find_addressing_mode:=10;
  852. end;
  853.  
  854. procedure type00 (mne_op: byte);
  855. begin
  856.   if (operand <> '') then show_error ('Ignoring unexpected operand '+operand);
  857.   opcode_count:=1;
  858.   opcode_list:=dectohex (mne_op, 2);
  859. end;
  860.  
  861. procedure type01 (mne_op: byte);
  862. var b: byte;
  863. begin
  864.   if (operand = '') then show_error ('No operand') else
  865.   begin
  866.     b:=find_addressing_mode (f3);
  867.     case b of
  868.       1:
  869.       begin
  870.         addr_immediate (mne_op+$08);
  871.         exit;
  872.       end;
  873.       10:
  874.       begin
  875.         addr_absolute (mne_op+$0c);
  876.         exit;
  877.       end;
  878.       11:
  879.       begin
  880.         delete (f3, pos (',X', f3), 2);
  881.         addr_absolute (mne_op+$1c);
  882.         exit;
  883.       end;
  884.       12:
  885.       begin
  886.         no_byte:=1;
  887.         no_long:=1;
  888.         delete (f3, pos (',Y', f3), 2);
  889.         addr_absolute (mne_op+$18);
  890.         exit;
  891.       end;
  892.       13:
  893.       begin
  894.         no_word:=1;
  895.         no_long:=1;
  896.         delete (f3, pos (',S', f3), 2);
  897.         addr_absolute (mne_op+$0a);
  898.         exit;
  899.       end;
  900.       20:
  901.       begin
  902.         no_word:=1;
  903.         no_long:=1;
  904.         delete (f3, pos ('(', f3), 1);
  905.         delete (f3, pos (')', f3), 1);
  906.         addr_indirect (mne_op+$19);
  907.         exit;
  908.       end;
  909.       21:
  910.       begin
  911.         no_word:=1;
  912.         no_long:=1;
  913.         delete (f3, pos ('(', f3), 1);
  914.         delete (f3, pos (',X)', f3), 3);
  915.         addr_indirect (mne_op+$08);
  916.         exit;
  917.       end;
  918.       22:
  919.       begin
  920.         no_word:=1;
  921.         no_long:=1;
  922.         delete (f3, pos ('(', f3), 1);
  923.         delete (f3, pos ('),Y', f3), 3);
  924.         addr_indirect (mne_op+$18);
  925.         exit;
  926.       end;
  927.       23:
  928.       begin
  929.         no_word:=1;
  930.         no_long:=1;
  931.         delete (f3, pos ('(', f3), 1);
  932.         delete (f3, pos (',S),Y', f3), 5);
  933.         addr_indirect (mne_op+$1a);
  934.         exit;
  935.       end;
  936.       30:
  937.       begin
  938.         no_word:=1;
  939.         no_long:=1;
  940.         delete (f3, pos ('[', f3), 1);
  941.         delete (f3, pos (']', f3), 1);
  942.         addr_indirect (mne_op+$0e);
  943.         exit;
  944.       end;
  945.       32:
  946.       begin
  947.         no_word:=1;
  948.         no_long:=1;
  949.         delete (f3, pos ('[', f3), 1);
  950.         delete (f3, pos ('],Y', f3), 3);
  951.         addr_indirect (mne_op+$1e);
  952.         exit;
  953.       end;
  954.     end;
  955.   end;
  956.   show_error ('Illegal addressing mode');
  957. end;
  958.  
  959. procedure type02 (mne_op: byte);
  960. var b: byte;
  961. begin
  962.   if (operand = '') then show_error ('No operand') else
  963.   begin
  964.     b:=find_addressing_mode (f3);
  965.     case b of
  966.       10:
  967.       begin
  968.         no_long:=1;
  969.         addr_absolute (mne_op+$08);
  970.         exit;
  971.       end;
  972.       11:
  973.       begin
  974.         if (pos ('STX', f2) = 0) then
  975.         begin
  976.           no_word:=1;
  977.           no_long:=1;
  978.           delete (f3, pos (',X', f3), 2);
  979.           addr_absolute (mne_op+$18);
  980.           exit;
  981.         end;
  982.       end;
  983.       12:
  984.       begin
  985.         no_word:=1;
  986.         no_long:=1;
  987.         if (pos ('STY', f2) = 0) then
  988.         begin
  989.           delete (f3, pos (',Y', f3), 2);
  990.           addr_absolute (mne_op+$18);
  991.           exit;
  992.         end;
  993.       end;
  994.     end;
  995.   end;
  996.   show_error ('Illegal addressing mode');
  997. end;
  998.  
  999. procedure type03 (mne_op: byte);
  1000. var b: byte;
  1001. begin
  1002.   if (operand = '') then
  1003.   begin
  1004.     opcode_count:=1;
  1005.     opcode_list:=dectohex (mne_op+$04, 2);
  1006.     exit;
  1007.   end else
  1008.   begin
  1009.     no_long:=1;
  1010.     b:=find_addressing_mode (f3);
  1011.     case b of
  1012.       10:
  1013.       begin
  1014.         addr_absolute (mne_op+$08);
  1015.         exit;
  1016.       end;
  1017.       11:
  1018.       begin
  1019.         delete (f3, pos (',X', f3), 2);
  1020.         addr_absolute (mne_op+$18);
  1021.         exit;
  1022.       end;
  1023.     end;
  1024.   end;
  1025.   show_error ('Illegal addressing mode');
  1026. end;
  1027.  
  1028. procedure type04 (mne_op: byte);
  1029. var b: byte;
  1030. begin
  1031.   if (operand = '') then
  1032.   begin
  1033.     opcode_count:=1;
  1034.     if (f2 = 'DEC') then opcode_list:=dectohex ($3a, 2);
  1035.     if (f2 = 'INC') then opcode_list:=dectohex ($1a, 2);
  1036.     exit;
  1037.   end else
  1038.   begin
  1039.     no_long:=1;
  1040.     b:=find_addressing_mode (f3);
  1041.     case b of
  1042.       10:
  1043.       begin
  1044.         addr_absolute (mne_op+$08);
  1045.         exit;
  1046.       end;
  1047.       11:
  1048.       begin
  1049.         delete (f3, pos (',X', f3), 2);
  1050.         addr_absolute (mne_op+$18);
  1051.         exit;
  1052.       end;
  1053.     end;
  1054.   end;
  1055.   show_error ('Illegal addressing mode');
  1056. end;
  1057.  
  1058. procedure type05 (mne_op: byte);
  1059. var b: byte;
  1060. begin
  1061.   if (operand = '') then show_error ('No operand') else
  1062.   begin
  1063.     b:=find_addressing_mode (f3);
  1064.     case b of
  1065.       1:
  1066.       begin
  1067.         addr_immediate (mne_op);
  1068.         exit;
  1069.       end;
  1070.       10:
  1071.       begin
  1072.         no_long:=1;
  1073.         addr_absolute (mne_op+$0c);
  1074.         exit;
  1075.       end;
  1076.     end;
  1077.   end;
  1078.   show_error ('Illegal addressing mode');
  1079. end;
  1080.  
  1081. procedure type06 (mne_op: byte);
  1082. var b: byte;
  1083. begin
  1084.   if (operand = '') then show_error ('No operand') else
  1085.   begin
  1086.     b:=find_addressing_mode (f3);
  1087.     case b of
  1088.       1:
  1089.       begin
  1090.         addr_immediate (mne_op);
  1091.         exit;
  1092.       end;
  1093.       10:
  1094.       begin
  1095.         no_long:=1;
  1096.         addr_absolute (mne_op+$0c);
  1097.         exit;
  1098.       end;
  1099.       11:
  1100.       begin
  1101.         if (pos ('LDX', f2) = 0) then
  1102.         begin
  1103.           no_long:=1;
  1104.           delete (f3, pos (',X', f3), 2);
  1105.           addr_absolute (mne_op+$1c);
  1106.           exit;
  1107.         end;
  1108.       end;
  1109.       12:
  1110.       begin
  1111.         if (pos ('LDY', f2) = 0) then
  1112.         begin
  1113.           no_long:=1;
  1114.           delete (f3, pos (',Y', f3), 2);
  1115.           addr_absolute (mne_op+$1c);
  1116.           exit;
  1117.         end;
  1118.       end;
  1119.     end;
  1120.   end;
  1121.   show_error ('Illegal addressing mode');
  1122. end;
  1123.  
  1124. procedure type07 (mne_op: byte);
  1125. var b: byte;
  1126.     l: longint;
  1127. begin
  1128.   if (operand = '') then show_error ('No operand') else
  1129.   begin
  1130.     b:=find_addressing_mode (f3);
  1131.     case b of
  1132.       10:
  1133.       begin
  1134.         no_byte:=1;
  1135.         addr_absolute (mne_op);
  1136.         if (opcode_count = 4) then
  1137.         begin
  1138.           no_word:=1;
  1139.           addr_absolute (mne_op+$0e);
  1140.         end;
  1141.         exit;
  1142.       end;
  1143.       20:
  1144.       begin
  1145.         no_byte:=1;
  1146.         no_long:=1;
  1147.         delete (f3, pos ('(', f3), 1);
  1148.         delete (f3, pos (')', f3), 1);
  1149.         addr_indirect (mne_op+$20);
  1150.         exit;
  1151.       end;
  1152.       21:
  1153.       begin
  1154.         no_byte:=1;
  1155.         no_long:=1;
  1156.         delete (f3, pos ('(', f3), 1);
  1157.         delete (f3, pos (',X)', f3), 3);
  1158.         addr_indirect (mne_op+$30);
  1159.         exit;
  1160.       end;
  1161.     end;
  1162.   end;
  1163.   show_error ('Illegal addressing mode');
  1164. end;
  1165.  
  1166. procedure type08 (mne_op: byte);
  1167. var b: byte;
  1168.     l: longint;
  1169. begin
  1170.   if (operand = '') then show_error ('No operand') else
  1171.   begin
  1172.     b:=find_addressing_mode (f3);
  1173.     case b of
  1174.       10:
  1175.       begin
  1176.         no_byte:=0;
  1177.         no_word:=0;
  1178.         f2:=f2+'.L';
  1179.         addr_absolute (mne_op-$82);
  1180.         exit;
  1181.       end;
  1182.       20:
  1183.       begin
  1184.         no_byte:=1;
  1185.         no_long:=1;
  1186.         delete (f3, pos ('(', f3), 1);
  1187.         delete (f3, pos (')', f3), 1);
  1188.         addr_indirect (mne_op);
  1189.         exit;
  1190.       end;
  1191.     end;
  1192.   end;
  1193.   show_error ('Illegal addressing mode');
  1194. end;
  1195.  
  1196. procedure type09 (mne_op: byte);
  1197. var b: byte;
  1198.     l: longint;
  1199. begin
  1200.   if (operand = '') then show_error ('No operand') else
  1201.   begin
  1202.     b:=find_addressing_mode (f3);
  1203.     case b of
  1204.       10:
  1205.       begin
  1206.         no_byte:=1;
  1207.         addr_absolute (mne_op);
  1208.         exit;
  1209.       end;
  1210.       21:
  1211.       begin
  1212.         no_byte:=1;
  1213.         no_long:=1;
  1214.         delete (f3, pos ('(', f3), 1);
  1215.         delete (f3, pos (',X)', f3), 3);
  1216.         addr_indirect (mne_op+$dc);
  1217.         exit;
  1218.       end;
  1219.     end;
  1220.   end;
  1221.   show_error ('Illegal addressing mode');
  1222. end;
  1223.  
  1224. procedure type0a (mne_op: byte);
  1225. var b: byte;
  1226.     l: longint;
  1227. begin
  1228.   if (operand = '') then show_error ('No operand') else
  1229.   begin
  1230.     b:=find_addressing_mode (f3);
  1231.     case b of
  1232.       10:
  1233.       begin
  1234.         no_byte:=1;
  1235.         no_word:=1;
  1236.         addr_absolute (mne_op-$02);
  1237.         exit;
  1238.       end;
  1239.     end;
  1240.   end;
  1241.   show_error ('Illegal addressing mode');
  1242. end;
  1243.  
  1244. procedure type0b (mne_op: byte);
  1245. var b: byte;
  1246. begin
  1247.   if (operand = '') then show_error ('No operand') else
  1248.   begin
  1249.     no_long:=1;
  1250.     b:=find_addressing_mode (f3);
  1251.     case b of
  1252.       1:
  1253.       begin
  1254.         addr_immediate ($89);
  1255.         exit;
  1256.       end;
  1257.       10:
  1258.       begin
  1259.         addr_absolute (mne_op+$08);
  1260.         exit;
  1261.       end;
  1262.       11:
  1263.       begin
  1264.         delete (f3, pos (',X', f3), 2);
  1265.         addr_absolute (mne_op+$18);
  1266.         exit;
  1267.       end;
  1268.     end;
  1269.   end;
  1270.   show_error ('Illegal addressing mode');
  1271. end;
  1272.  
  1273. procedure type0c (mne_op: byte);
  1274. var b: byte;
  1275.     l1, l2: longint;
  1276. begin
  1277.   b:=0;
  1278.   if (operand = '') then show_error ('No operand') else
  1279.   begin
  1280.     if (pass = 2) then
  1281.     begin
  1282.       l2:=eval (f3);
  1283.       if (err_flag = 0) then
  1284.       begin
  1285.         l1:=l2-(address_index+2);
  1286.         if (l1 < -128) or (l1 > 127) then show_error ('Branch out of range') else
  1287.           b:=l1;
  1288.       end;
  1289.     end;
  1290.   end;
  1291.   opcode_count:=2;
  1292.   if (pass = 2) then opcode_list:=dectohex (mne_op, 2)+' '+dectohex (b, 2);
  1293. end;
  1294.  
  1295. procedure type0d (mne_op: byte);
  1296. var w: byte;
  1297.     l: longint;
  1298. begin
  1299.   w:=0;
  1300.   if (operand = '') then show_error ('No operand') else
  1301.   begin
  1302.     if (pass = 2) then
  1303.     begin
  1304.       l:=eval (f3)-(address_index+3);
  1305.       if (err_flag = 0) then
  1306.       begin
  1307.         if (l < -32768) or (l > 32767) then show_error ('Branch out of range') else
  1308.           w:=l;
  1309.       end;
  1310.     end;
  1311.   end;
  1312.   opcode_count:=2;
  1313.   if (pass = 2) then opcode_list:=dectohex (mne_op, 2)+' '+
  1314.                                   dectohex (w and 255, 2)+' '+
  1315.                                   dectohex ((w shr 8) and 255, 2);
  1316. end;
  1317.  
  1318. procedure type0e (mne_op: byte);
  1319. var b: byte;
  1320.     l1, l2: longint;
  1321.     s: string;
  1322. begin
  1323.   if (operand = '') then show_error ('No operand') else
  1324.   begin
  1325.     b:=pos (',', f3);
  1326.     if (b > 0) then
  1327.     begin
  1328.       s:=copy (f3, 1, b-1);
  1329.       l1:=eval (s);
  1330.       s:=copy (f3, b+1, length (f3)-b+1);
  1331.       l2:=eval (s);
  1332.       if (l1 < -80) or (l1 > 255) or
  1333.          (l2 < -80) or (l2 > 255) then show_error ('Operand out of range '+operand) else
  1334.         begin
  1335.           opcode_count:=2;
  1336.           opcode_list:=dectohex (mne_op, 2)+' '+
  1337.                        dectohex (l2, 2)+' '+
  1338.                        dectohex (l1, 2)+' ';
  1339.           exit;
  1340.         end;
  1341.     end;
  1342.     show_error ('Illegal addressing mode');
  1343.   end;
  1344. end;
  1345.      
  1346. procedure type0f (mne_op: byte);
  1347. var b: byte;
  1348. begin
  1349.   if (operand = '') then show_error ('No operand') else
  1350.   begin
  1351.     b:=find_addressing_mode (f3);
  1352.     case b of
  1353.       10:
  1354.       begin
  1355.         no_byte:=1;
  1356.         no_long:=1;
  1357.         addr_absolute (mne_op);
  1358.         exit;
  1359.       end;
  1360.     end;
  1361.   end;
  1362.   show_error ('Illegal addressing mode');
  1363. end;
  1364.  
  1365. procedure type10 (mne_op: byte);
  1366. var b: byte;
  1367. begin
  1368.   if (operand = '') then show_error ('No operand') else
  1369.   begin
  1370.     b:=find_addressing_mode (f3);
  1371.     case b of
  1372.       20:
  1373.       begin
  1374.         no_word:=1;
  1375.         no_long:=1;
  1376.         delete (f3, pos ('(', f3), 1);
  1377.         delete (f3, pos (')', f3), 1);
  1378.         addr_indirect (mne_op+$08);
  1379.         exit;
  1380.       end;
  1381.     end;
  1382.   end;
  1383.   show_error ('Illegal addressing mode');
  1384. end;
  1385.  
  1386. procedure type11 (mne_op: byte);
  1387. var b: byte;
  1388. begin
  1389.   if (operand = '') then show_error ('No operand') else
  1390.   begin
  1391.     b:=find_addressing_mode (f3);
  1392.     case b of
  1393.       1:
  1394.       begin
  1395.         no_word:=1;
  1396.         no_long:=1;
  1397.         addr_immediate (mne_op);
  1398.         exit;
  1399.       end;
  1400.     end;
  1401.   end;
  1402.   show_error ('Illegal addressing mode');
  1403. end;
  1404.  
  1405. procedure type12 (mne_op: byte);
  1406. var b: byte;
  1407. begin
  1408.   if (operand = '') then show_error ('No operand') else
  1409.   begin
  1410.     no_long:=1;
  1411.     b:=find_addressing_mode (f3);
  1412.     case b of
  1413.       10:
  1414.       begin
  1415.         addr_absolute (mne_op+$38);
  1416.         if (opcode_count = 2) then
  1417.         begin
  1418.           no_word:=1;
  1419.           addr_absolute (mne_op+$08);
  1420.         end;
  1421.         exit;
  1422.       end;
  1423.       11:
  1424.       begin
  1425.         delete (f3, pos (',X', f3), 2);
  1426.         addr_absolute (mne_op+$3a);
  1427.         if (opcode_count = 2) then
  1428.         begin
  1429.           no_word:=1;
  1430.           addr_absolute (mne_op+$18);
  1431.         end;
  1432.         exit;
  1433.       end;
  1434.     end;
  1435.   end;
  1436.   show_error ('Illegal addressing mode');
  1437. end;
  1438.  
  1439. procedure type13 (mne_op: byte);
  1440. var b: byte;
  1441. begin
  1442.   if (operand = '') then show_error ('No operand') else
  1443.   begin
  1444.     no_long:=1;
  1445.     b:=find_addressing_mode (f3);
  1446.     case b of
  1447.       10:
  1448.       begin
  1449.         addr_absolute (mne_op+$08);
  1450.         exit;
  1451.       end;
  1452.     end;
  1453.   end;
  1454.   show_error ('Illegal addressing mode');
  1455. end;
  1456.  
  1457. function find_mnemonic (s: string): word;
  1458. var b: byte;
  1459. begin
  1460.   b:=0;
  1461.   repeat
  1462.     inc (b);
  1463.   until (b = mne_count) or (mne_word [b] = s);
  1464.   if (b < mne_count) then find_mnemonic:=b else
  1465.     find_mnemonic:=$ffff;
  1466. end;
  1467.  
  1468. procedure binary_load;
  1469. var l: longint;
  1470.     f: file;
  1471.     w, c: word;
  1472.     buf: array [0..1023] of byte;
  1473. begin
  1474.   assign (f, f3);
  1475.   {$I-}
  1476.   reset (f, 1);
  1477.   if (ioresult = 0) then
  1478.   begin
  1479.     l:=filesize (f);
  1480.     if (l > 32768) then l:=(l div 32768)*65536;
  1481.     opcode_count:=l;
  1482.     write_op:=0;
  1483.     if (pass = 2) then
  1484.     begin
  1485.       repeat
  1486.         blockread (f, buf, sizeof (buf), w);
  1487.         blockwrite (obj_file, buf, w);
  1488.       until (w = 0);
  1489.     end;
  1490.     close (f);
  1491.   end else show_error ('Error reading binary file '+f3);
  1492.   {$I+}
  1493. end;
  1494.  
  1495. procedure pad_file;
  1496. var l, c: longint;
  1497.     buf: array [0..32767] of byte;
  1498. begin
  1499.   fillchar (buf, 32768, 0);
  1500.   if (f3 <> '') then
  1501.   begin
  1502.     l:=eval (f3);
  1503.     if (l >= $8000) and (l <= $ffff) then
  1504.     begin
  1505.       l:=l+(address_index and $ff0000);
  1506.       if (l < address_index) then
  1507.       begin
  1508.         l:=l+$010000;
  1509.         if (pass = 2) then
  1510.         begin
  1511.           c:=$8000-(address_index and $7fff);
  1512.           blockwrite (obj_file, buf [start_address and $7fff], c);
  1513.           inc (address_index, c);
  1514.         end;
  1515.       end;
  1516.       if (pass = 2) then
  1517.       begin
  1518.         c:=(l and $7fff)-(address_index and $7fff);
  1519.         blockwrite (obj_file, buf [address_index and $7fff], c);
  1520.       end;
  1521.       address_index:=l;
  1522.     end else
  1523.     begin
  1524.       show_error ('Illegal PAD operand '+f3+', padding to next bank.');
  1525.       f3:='';
  1526.     end;
  1527.   end;
  1528.   if (f3 = '') then
  1529.   begin
  1530.     write_op:=0;
  1531.     l:=((address_index+65536) and $ff0000) or $8000;
  1532.     opcode_count:=l-address_index;
  1533.     if (pass = 2) then
  1534.     begin
  1535.       c:=$8000-(address_index and $7fff);
  1536.       blockwrite (obj_file, buf [address_index and $7fff], c);
  1537.     end;
  1538.   end;
  1539. end;
  1540.  
  1541. procedure data_string_byte;
  1542. var b, b1, b2: byte;
  1543.     s, t: string;
  1544.     l: longint;
  1545.     quote1, quote2: byte;
  1546. begin
  1547.   opcode_count:=0;
  1548.   opcode_list:='';
  1549.   b:=1;
  1550.   f3:=f3+',';
  1551.   quote1:=0;
  1552.   repeat
  1553.     if (f3 [b] = '"') then quote1:=quote1 xor 1;
  1554.     if (f3 [b] = ',') and (quote1 = 0) then
  1555.     begin
  1556.       t:='';
  1557.       quote2:=0;
  1558.       b1:=b;
  1559.       b2:=b;
  1560.       repeat
  1561.         dec (b1);
  1562.         if (f3 [b1] = '"') then quote2:=quote2 xor 1;
  1563.         if (f3 [b1] = ',') and (quote2 = 0) then t:=',';
  1564.       until (b1 <= 0) or (t = ',');
  1565.       if (t = ',') then inc (b1) else dec (b2);
  1566.       s:=copy (operand, b1, b2-b1);
  1567.       kill_leadspace (s);
  1568.       kill_followspace (s);
  1569.       if (s [1] = '"') then
  1570.       begin
  1571.         b1:=1+1;
  1572.         while (b1 <= length (s)) and (s [b1] <> s [1]) do
  1573.         begin
  1574.           if (pass = 2) then opcode_list:=opcode_list+dectohex (ord (s [b1]), 2)+' ';
  1575.           inc (opcode_count);
  1576.           inc (b1);
  1577.         end;
  1578.       end else
  1579.       begin
  1580.         l:=eval (upper (s));
  1581.         if (l <-128) or (l > 255) then show_error ('Data size too large, truncating');
  1582.         if (pass = 2) then opcode_list:=opcode_list+dectohex (l and 255, 2)+' ';
  1583.         inc (opcode_count);
  1584.       end;
  1585.     end;
  1586.     inc (b);
  1587.   until (b > length (f3));
  1588.   delete (f3, length (f3), 1);
  1589. end;
  1590.  
  1591. procedure data_string_word;
  1592. var b, b1, b2: byte;
  1593.     s, t: string;
  1594.     l: longint;
  1595.     quote1, quote2: byte;
  1596. begin
  1597.   opcode_count:=0;
  1598.   opcode_list:='';
  1599.   b:=1;
  1600.   f3:=f3+',';
  1601.   quote1:=0;
  1602.   repeat
  1603.     if (f3 [b] = '"') then quote1:=quote1 xor 1;
  1604.     if (f3 [b] = ',') and (quote1 = 0) then
  1605.     begin
  1606.       t:='';
  1607.       quote2:=0;
  1608.       b1:=b;
  1609.       b2:=b;
  1610.       repeat
  1611.         dec (b1);
  1612.         if (f3 [b1] = '"') then quote2:=quote2 xor 1;
  1613.         if (f3 [b1] = ',') and (quote2 = 0) then t:=',';
  1614.       until (b1 <= 0) or (t = ',');
  1615.       if (t = ',') then inc (b1) else dec (b2);
  1616.       s:=copy (operand, b1, b2-b1);
  1617.       kill_leadspace (s);
  1618.       kill_followspace (s);
  1619.       if (s [1] = '"') then
  1620.       begin
  1621.         b1:=1+1;
  1622.         while (b1 <= length (s)) and (s [b1] <> s [1]) do
  1623.         begin
  1624.           if (pass = 2) then opcode_list:=opcode_list+dectohex (ord (s [b1]), 2)+' ';
  1625.           inc (opcode_count);
  1626.           inc (b1);
  1627.         end;
  1628.       end else
  1629.       begin
  1630.         l:=eval (upper (s));
  1631.         if (l <-32768) or (l > 65535) then show_error ('Data size too large, truncating');
  1632.         if (pass = 2) then opcode_list:=opcode_list+dectohex (l and 255, 2)+' '+
  1633.                                                     dectohex ((l shr 8) and 255, 2)+' ';
  1634.         inc (opcode_count,2);
  1635.       end;
  1636.     end;
  1637.     inc (b);
  1638.   until (b > length (f3));
  1639.   delete (f3, length (f3), 1);
  1640. end;
  1641.  
  1642. procedure data_buffer_byte;
  1643. var l: longint;
  1644.     buf: array [0..32767] of byte;
  1645. begin
  1646.   fillchar (buf, 32768, 0);
  1647.   l:=eval (f3);
  1648.   if (l < 0) or (l > 32768) then show_error ('Data buffer area cannot exceed 32768 bytes') else
  1649.   begin
  1650.     address_index:=address_index+l;
  1651.     if (pass = 2) then blockwrite (obj_file, buf, l);
  1652.   end;
  1653. end;
  1654.  
  1655. procedure data_buffer_word;
  1656. var l: longint;
  1657.     buf: array [0..32767] of byte;
  1658. begin
  1659.   fillchar (buf, 32768, 0);
  1660.   l:=eval (f3);
  1661.   if (l < 0) or (l > 32768) then show_error ('Data buffer area cannot exceed 32768 words') else
  1662.   begin
  1663.     address_index:=address_index+l;
  1664.     if (pass = 2) then
  1665.     begin
  1666.       blockwrite (obj_file, buf, l);
  1667.       blockwrite (obj_file, buf, l);
  1668.     end;
  1669.   end;
  1670. end;
  1671.  
  1672. procedure assemble_line;
  1673. var s: string;
  1674.     l: longint;
  1675.     w: word;
  1676.     b: byte;
  1677.     mne_index, mne_op: byte;
  1678.     lab: label_rec;
  1679. begin
  1680.   s:=copy (f2, 1, 3);
  1681.   if (s = 'ORG') or (s = 'NAM') or (s = 'COU') or (s = 'VER') then exit;
  1682.  
  1683.   if (s = 'INT') then
  1684.   begin
  1685.     exit
  1686.   end;
  1687.  
  1688.   if (s = 'BIN') then
  1689.   begin
  1690.     binary_load;
  1691.     exit;
  1692.   end;
  1693.  
  1694.   if (s = 'PAD') then
  1695.   begin
  1696.     pad_file;
  1697.     exit;
  1698.   end;
  1699.  
  1700.   if (s = 'EQU') or (s = '=') then
  1701.   begin
  1702.     l:=eval (f3);
  1703.     w:=find_label (f1);
  1704.     if (pass = 1) then
  1705.     begin
  1706.       if (w = $ffff) then
  1707.       begin
  1708.         if (err_flag > 0) then save_new_label (f1, l, 129) else
  1709.           save_new_label (f1, l, 1);
  1710.       end else show_error ('Duplicate label '+_label);
  1711.       exit;
  1712.     end;
  1713.     if (pass = 2) then
  1714.     begin
  1715.       lab:=label_list [w]^;
  1716.       if (lab.pass = 129) then
  1717.       begin
  1718.         lab.pass:=2;
  1719.         lab.address:=l;
  1720.         label_list [w]^:=lab;
  1721.         exit;
  1722.       end;
  1723.       if (lab.pass = 1) then
  1724.       begin
  1725.         lab.pass:=2;
  1726.         lab.address:=l;
  1727.         label_list [w]^:=lab;
  1728.         exit;
  1729.       end;
  1730.       show_error ('Duplicate label '+_label);
  1731.       exit;
  1732.     end;
  1733.   end;
  1734.  
  1735.   if (f1 <> '') and (pass = 1) then
  1736.   begin
  1737.     if (f1 = '-') then
  1738.     begin
  1739.       last_label:=address_index;
  1740.     end else
  1741.     begin
  1742.       w:=find_label (f1);
  1743.       if (w = $ffff) then
  1744.       begin
  1745.         save_new_label (f1, address_index, 1);
  1746.       end else show_error ('Duplicate label '+_label);
  1747.     end;
  1748.   end;
  1749.  
  1750.   if (f1 <> '') and (pass = 2) then
  1751.   begin
  1752.     if (f1 = '-') then
  1753.     begin
  1754.       last_label:=address_index
  1755.     end else
  1756.     begin
  1757.       w:=find_label (f1);
  1758.       lab:=label_list [w]^;
  1759.       if (lab.pass = 1) then
  1760.       begin
  1761.         lab.address:=address_index;
  1762.         lab.pass:=2;
  1763.         label_list [w]^:=lab;
  1764.       end else show_error ('Duplicate label '+_label);
  1765.     end;
  1766.   end;
  1767.  
  1768.   if (f2 = '') and (f3 = '') then exit;
  1769.  
  1770.   if (f2 = 'DCB') or (f2 = 'DC.B') or (f2 = 'DB') or (f2 = 'DC') then
  1771.   begin
  1772.     data_string_byte;
  1773.     exit;
  1774.   end;
  1775.   if (f2 = 'DCW') or (f2 = 'DC.W') or (f2 = 'DW') then
  1776.   begin
  1777.     data_string_word;
  1778.     exit;
  1779.   end;
  1780.  
  1781.   if (f2 = 'DSB') or (f2 = 'DS.B') or (f2 = 'DS') then
  1782.   begin
  1783.     data_buffer_byte;
  1784.     exit;
  1785.   end;
  1786.   if (f2 = 'DSW') or (f2 = 'DS.W') then
  1787.   begin
  1788.     data_buffer_word;
  1789.     exit;
  1790.   end;
  1791.  
  1792.   if (length (f2) = 3) or
  1793.      ((length (f2) = 5) and (f2 [4] = '.')) then
  1794.   begin
  1795.     opcode_count:=1;
  1796.     opcode_list:='00';
  1797.     no_byte:=0;
  1798.     no_long:=0;
  1799.     no_word:=0;
  1800.     mne_index:=find_mnemonic (s);
  1801.     mne_op:=mne_opcode [mne_index];
  1802.     if (mne_index >= 0) and (mne_index <= 255) then
  1803.     begin
  1804.       case mne_type [mne_index] of
  1805.         $00: type00 (mne_op);
  1806.         $01: type01 (mne_op);
  1807.         $02: type02 (mne_op);
  1808.         $03: type03 (mne_op);
  1809.         $04: type04 (mne_op);
  1810.         $05: type05 (mne_op);
  1811.         $06: type06 (mne_op);
  1812.         $07: type07 (mne_op);
  1813.         $08: type08 (mne_op);
  1814.         $09: type09 (mne_op);
  1815.         $0a: type0a (mne_op);
  1816.         $0b: type0b (mne_op);
  1817.         $0c: type0c (mne_op);
  1818.         $0d: type0d (mne_op);
  1819.         $0f: type0f (mne_op);
  1820.         $0e: type0e (mne_op);
  1821.         $10: type10 (mne_op);
  1822.         $11: type11 (mne_op);
  1823.         $12: type12 (mne_op);
  1824.         $13: type13 (mne_op);
  1825.       end;
  1826.     end else
  1827.     show_error ('Unknown operator');
  1828.   end;
  1829. end;
  1830.  
  1831. procedure do_pass0;
  1832. begin
  1833.   if (f2 = 'ORG') then start_address:=eval (f3);
  1834.   if (f2 = 'NAM') then name:=operand;
  1835.   if (f2 = 'COU') then country:=eval (f3);
  1836.   if (f2 = 'VER') then version:=eval (f3);
  1837. end;
  1838.  
  1839. procedure do_pass1;
  1840. var w: word;
  1841.     b: byte;
  1842. begin
  1843.   write_op:=1;
  1844.   opcode_count:=0;
  1845.   opcode_list:='';
  1846.   if (f1 <> '') or (f2 <> '') or (f3 <> '') then
  1847.   begin
  1848.     assemble_line;
  1849.   end;
  1850.   if (pass = 2) then
  1851.   begin
  1852.     if (save_lst > 0) then
  1853.     begin
  1854.       write (lst_file, adj_right (inttostr (line_index), 6, ' '), ' ',
  1855.                        dectohex (address_index, 6), '  ',
  1856.                        adj_left (opcode_list, 12, ' '), '  ',
  1857.                        adj_left (_label, 16, ' '),
  1858.                        adj_left (operator, 7, ' '),
  1859.                        adj_left (operand, 16, ' '));
  1860.       if (comment = '') then writeln (lst_file) else
  1861.         writeln (lst_file, '; ',comment);
  1862.     end;
  1863.     if (show_listings > 0) then
  1864.     begin
  1865.       write (adj_right (inttostr (line_index), 6, ' '), ' ',
  1866.              dectohex (address_index, 6), '  ',
  1867.              adj_left (opcode_list, 12, ' '), '  ',
  1868.              adj_left (_label, 16, ' '),
  1869.              adj_left (operator, 7, ' '),
  1870.              adj_left (operand, 16, ' '));
  1871.       if (comment = '') then writeln else
  1872.         writeln ('; ',comment);
  1873.     end;
  1874.     if (show_lines > 0) and (show_listings = 0) then
  1875.     begin
  1876.       writeln (adj_right (inttostr (line_index), 6, ' '), ' ',
  1877.                dectohex (address_index, 6));
  1878.     end;
  1879.     if (opcode_count > 0) and (write_op > 0) then
  1880.     begin
  1881.       for w:=0 to (opcode_count-1) do
  1882.       begin
  1883.         b:=hextodec (copy (opcode_list, (w*3)+1, 2));
  1884.         blockwrite (obj_file, b, 1);
  1885.       end;
  1886.     end;
  1887.   end;
  1888.   inc (address_index, opcode_count);
  1889.   address_index:=address_index or $8000;
  1890. end;
  1891.  
  1892. procedure process_pass;
  1893. var l: string;
  1894. begin
  1895.   assign (src_file, src_name);
  1896.   reset (src_file);
  1897.   if (ioresult = 0) then
  1898.   begin
  1899.     line_index:=0;
  1900.     address_index:=start_address;
  1901.     while not eof (src_file) do
  1902.     begin
  1903.       inc (line_index);
  1904.       readln (src_file, l);
  1905.       parse_line (l, _label, operator, operand, comment);
  1906.       f1:=upper (_label);
  1907.       f2:=upper (operator);
  1908.       f3:=upper (operand);
  1909.       f4:=comment;
  1910.       if (f1 [length (f1)] = ':') then
  1911.       begin
  1912.         delete (f1, length (f1), 1);
  1913.         kill_followspace (f1);
  1914.       end;
  1915.       if (pass = 0) then do_pass0;
  1916.       if (pass = 1) then do_pass1;
  1917.       if (pass = 2) then do_pass1;
  1918.     end;
  1919.     close (src_file);
  1920.   end else
  1921.   begin
  1922.     show_error ('Unable to read source file');
  1923.     close (err_file);
  1924.     if (save_lst > 0) then close (lst_file);
  1925.     halt (1);
  1926.   end;
  1927. end;
  1928.  
  1929. procedure pad_obj_file;
  1930. var l:longint;
  1931.     w:word;
  1932.     buf:array [0..32767] of byte;
  1933. begin
  1934.   fillchar (buf, 32768,0);
  1935.   buf [$7ffd]:=$80;
  1936.   assign (obj_file, obj_name);
  1937.   reset (obj_file, 1);
  1938.   l:=filesize (obj_file);
  1939.   seek (obj_file, l);
  1940.   blockwrite (obj_file, buf [l mod 32768], 32768-(l mod 32768));
  1941.   while (length (name) < 20) do name:=name+' ';
  1942.   name:=name+'0';
  1943.   seek (obj_file, $7fc0);
  1944.   blockwrite (obj_file, name [1], 21);
  1945.   name:=chr ($0b);
  1946.   seek (obj_file, $7fd7);
  1947.   blockwrite (obj_file, name [1], 1);
  1948.   name:=chr (country);
  1949.   seek (obj_file, $7fd9);
  1950.   blockwrite (obj_file, name [1], 1);
  1951.   name:=chr (version-1);
  1952.   seek (obj_file, $7fdb);
  1953.   blockwrite (obj_file, name [1], 1);
  1954.   name:=chr (start_address and 255)+
  1955.         chr ((start_address shr 8) and 255)+
  1956.         chr ((start_address shr 16) and 255);
  1957.   seek (obj_file, $7ffc);
  1958.   blockwrite (obj_file, name [1], 3);
  1959.   close (obj_file);
  1960.  
  1961.   reset (obj_file, 1);
  1962.   l:=filesize (obj_file);
  1963.  
  1964.   assign (smc_file, smc_name);
  1965.   rewrite (smc_file, 1);
  1966.   l:=l*8;
  1967.   buf[0]:=(l shr 16) and 255;
  1968.   buf[1]:=(l shr 8) and 255;
  1969.   buf[2]:=l and 255;
  1970.   blockwrite (smc_file, buf, 512);
  1971.   repeat
  1972.     blockread (obj_file, buf, 32768, w);
  1973.     blockwrite (smc_file, buf, w);
  1974.   until (w=0);
  1975.   close (obj_file);
  1976.   close (smc_file);
  1977. end;
  1978.  
  1979. procedure save_labels;
  1980. var w: word;
  1981.     l: label_rec;
  1982. begin
  1983.   if (label_index = 0) then exit;
  1984.   if (save_lab > 0) then
  1985.   begin
  1986.     assign (lab_file, lab_name);
  1987.     rewrite (lab_file);
  1988.     for w:=0 to (label_index-1) do
  1989.     begin
  1990.       l:=label_list [w]^;
  1991.       writeln (lab_file, adj_left (l.name, 16, ' '), ' = ', dectohex (l.address, 7));
  1992.     end;
  1993.     close (lab_file);
  1994.   end;
  1995. end;
  1996.  
  1997. begin
  1998.   writeln;
  1999.   writeln;
  2000.   writeln ('65c816 SNES Cross Assembler Version 1.05');
  2001.   writeln ('Coded by Norman Yen');
  2002.   writeln ('Released 04-29-93, Updated 11-06-93');
  2003.   writeln;
  2004.   if (paramcount = 0) then
  2005.   begin
  2006.     writeln ('Usage: SNESASM -<options> <source code>');
  2007.     writeln;
  2008.     writeln ('Options:');
  2009.     writeln ('   S.. Show listings to screen       L.. Save LST file');
  2010.     writeln ('   $.. Save LAB file                 #.. Show line numbers');
  2011.     writeln;
  2012.     writeln ('If no extension is given a default of .ASM will be used.');
  2013.     exit;
  2014.   end;
  2015.  
  2016.   show_listings:=0;
  2017.   save_lab:=0;
  2018.   save_lst:=0;
  2019.   show_lines:=0;
  2020.  
  2021.   if (copy (paramstr (1), 1, 1) = '-') or
  2022.      (copy (paramstr (1), 1, 1) = '/') then
  2023.   begin
  2024.     if (pos ('S', upper (paramstr (1))) > 0) then show_listings:=1;
  2025.     if (pos ('L', upper (paramstr (1))) > 0) then save_lst:=1;
  2026.     if (pos ('$', upper (paramstr (1))) > 0) then save_lab:=1;
  2027.     if (pos ('#', upper (paramstr (1))) > 0) then show_lines:=1;
  2028.     src_name:=paramstr (2);
  2029.   end else src_name:=paramstr (1);
  2030.  
  2031.   if (pos ('.', src_name) = 0) then src_name:=src_name+'.asm';
  2032.   obj_name:=copy (src_name,1, pos ('.', src_name))+'obj';
  2033.   smc_name:=copy (src_name,1, pos ('.', src_name))+'smc';
  2034.   err_name:=copy (src_name,1, pos ('.', src_name))+'err';
  2035.   lab_name:=copy (src_name,1, pos ('.', src_name))+'lab';
  2036.   lst_name:=copy (src_name,1, pos ('.', src_name))+'lst';
  2037.  
  2038.   assign (err_file, err_name);
  2039.   rewrite (err_file);
  2040.   if (save_lst > 0) then
  2041.   begin
  2042.     assign (lst_file, lst_name);
  2043.     rewrite (lst_file);
  2044.   end;
  2045.  
  2046.   start_address:=$008000;
  2047.   version:=1;
  2048.   country:=1;
  2049.   name:='(C) 1993 Norman Yen';
  2050.   get_label_mem;
  2051.   for pass:=0 to 2 do
  2052.   begin
  2053.     error_index:=0;
  2054.     write ('Pass ', pass);
  2055.     write (err_file, 'Pass ', pass);
  2056.     if (pass = 2) then
  2057.     begin
  2058.       assign (obj_file, obj_name);
  2059.       rewrite (obj_file, 1);
  2060.     end;
  2061.     process_pass;
  2062.     if (pass = 2) then
  2063.     begin
  2064.       close (obj_file);
  2065.       pad_obj_file;
  2066.     end;
  2067.     writeln (': ',line_index,' Lines, ',error_index, ' Errors, ',label_index, ' Labels');
  2068.     writeln (err_file,': ',line_index,' Lines, ',error_index, ' Errors, ',label_index, ' Labels');
  2069.   end;
  2070.   writeln (dectohex (start_address, 6),'-', dectohex (address_index, 6));
  2071.   writeln (err_file, dectohex (start_address, 6),'-', dectohex (address_index, 6));
  2072.   writeln;
  2073.   close (err_file);
  2074.   if (save_lst > 0) then close (lst_file);
  2075.   save_labels;
  2076.   free_label_mem;
  2077. end.
  2078.