home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / emulator / appleonamiga / txt / apple.mod < prev    next >
Text File  |  1995-02-27  |  46KB  |  1,882 lines

  1. MODULE Apple;
  2. (*
  3.  Apple 2 emulator, written and put into the public domain 1993 by Claudio Nieder.
  4.  
  5.  Current emulation: Apple 2 with RAM, ROM, text screen and floppy.
  6. *)
  7.  
  8. (*$
  9.  DEFINE Debug:=TRUE
  10.  DEFINE Track:=TRUE
  11.  DEFINE Commands:=FALSE
  12. *)
  13.  
  14. (*$
  15.  OverflowChk:=FALSE
  16.  RangeChk:=FALSE
  17.  StackChk:=FALSE
  18.  EntryClear:=FALSE
  19.  Volatile:=FALSE
  20.  StackParms:=FALSE
  21.  NilChk:=FALSE
  22. *)
  23.  
  24. FROM SYSTEM IMPORT ADR,CAST,LONGSET,TAG;
  25.  
  26. FROM Base37 IMPORT A,B,N;
  27.  
  28. IMPORT
  29.  AS:AppleScreen,d:DosD,D:DosL,e:ExecD,E:ExecL,Heap,R;
  30.  
  31. (*$ IF Debug *)
  32.  
  33. IMPORT
  34.  Break,T:Terminal;
  35.  
  36. (*$ ENDIF *)
  37.  
  38. CONST
  39.  basicRomFile="PROGDIR:BASIC";
  40.  diskPromFile="PROGDIR:DISK";
  41.  errNoBasic=basicRomFile+" not found";
  42.  errReadBasic="Error reading "+basicRomFile;
  43.  errNoDisk=diskPromFile+" not found";
  44.  errReadDisk="Error reading "+diskPromFile;
  45.  errNoDiskBuffer="Not enough memory for disk";
  46.  
  47. TYPE
  48.  Byte=[0..255]; Set=SET OF [0..7]; SignedByte=[-128..127];
  49.  Word=[0..65535];
  50.  Address=Word;
  51. (*
  52.  StatusBits=(carry,zero,irqDisable,decimal,break,unused,overflow,negative);
  53.  Status=SET OF StatusBits;
  54. *)
  55.  Register=RECORD
  56.   pc:Address;
  57.   a,x,y,sp:Byte;
  58. (*  p:Status; *)
  59.  END;
  60.  
  61. (*
  62.  The following contain information related to
  63.  the disk drives. They currently do not accuratly
  64.  reproduce the reald drives.
  65. *)
  66. CONST
  67.  minTrack=0; maxTrack=34;
  68.  
  69. TYPE
  70.  DataIndex=[0..250*1024-1];
  71.  DiskState=(noDisk,normalDisk,protectedDisk);
  72.  
  73.  DiskBuffer=ARRAY DataIndex OF Byte;
  74.  
  75.  DiskInfo=RECORD
  76.   state:DiskState;
  77.   motorOn,q6,q7:BOOLEAN;
  78.   latch:SHORTCARD;
  79.   step:[0..3];
  80.   currentTrack:[minTrack..maxTrack];
  81.   trackStart,trackEnd,trackPos:DataIndex;
  82.   data:POINTER TO DiskBuffer;
  83.   lock:e.SignalSemaphore;
  84.  END;
  85.  
  86.  ControllerInfo=RECORD
  87.   currentDrive:[1..2];
  88.   disk:ARRAY [1..2] OF DiskInfo;
  89.  END;
  90.  
  91. CONST
  92.  hi=0100H;
  93.  
  94. (*
  95.  Some special memory locations:
  96. *)
  97. CONST
  98.  ramStart=0; ramLength=0C000H; ramEnd=ramStart+ramLength-1;
  99.  stackBase=0100H;
  100.  
  101.  text1Start=0400H; text1Length=0400H; text1End=text1Start+text1Length-1;
  102.  
  103.  io0Start=0C000H; io0Page=io0Start DIV hi;
  104.  
  105.  promStart=0C600H; promLength=00100H; promEnd=promStart+promLength-1;
  106.  
  107.  romStart=0D000H; romLength=03000H; romEnd=romStart+romLength-1;
  108.  nmiVector=0FFFAH;
  109.  resetVector=0FFFCH;
  110.  irqVector=0FFFEH;
  111.  
  112. VAR
  113.  reg:Register; (* The 6502 registers *)
  114.  carry,zero,irqDisable,decimal,break(*,unused*),overflow,negative:BOOLEAN;
  115.  operand:Byte; (* Memory operand *)
  116.  jumpAddr:Address; (* Jump address *)
  117.  memAddr:Address; (* Address of memory reference *)
  118.  nextPC,nextPC2:PROC;
  119.  clockCount:LONGCARD;
  120.  controller:ControllerInfo;
  121.  doReset,quit:BOOLEAN;
  122.  ram:ARRAY [ramStart..ramEnd] OF Byte; (* The apple's ram *)
  123.  rom:ARRAY [romStart..romEnd] OF Byte; (* The apple's rom *)
  124.  prom:ARRAY [promStart..promEnd] OF Byte; (* Disk prom *)
  125.  
  126. (*
  127.  Initialise processor state.
  128. *)
  129.  
  130. PROCEDURE SetRST;
  131. BEGIN
  132.  doReset:=TRUE;
  133. END SetRST;
  134.  
  135. PROCEDURE SetQuit;
  136. BEGIN
  137.  quit:=TRUE;
  138. END SetQuit;
  139.  
  140. PROCEDURE DiskUnload(num:AS.DiskNum);
  141. BEGIN
  142. (*
  143.  I usually don't like WITH statements, but here they help
  144.  reduce typing, and are not so dangerous.
  145. *)
  146.  WITH controller.disk[num] DO
  147.  
  148. (* Critical section *)
  149. (*!!  E.ObtainSemaphore(ADR(lock)); !!*)
  150.   state:=noDisk;
  151.   trackStart:=0; trackEnd:=0; trackPos:=0;
  152.   IF data#NIL THEN Heap.Deallocate(data); data:=NIL; END;
  153. (*!!  E.ReleaseSemaphore(ADR(lock)); !!*)
  154.  
  155.  END;
  156. END DiskUnload;
  157.  
  158. PROCEDURE DiskLoad(num:AS.DiskNum);
  159. VAR
  160.  dummy:LONGINT;
  161.  f:d.FileHandlePtr;
  162.  i:[0..34];
  163.  name:ARRAY [0..99] OF CHAR;
  164.  trackLength:LONGCARD;
  165. BEGIN
  166. (*
  167.  I usually don't like WITH statements, but here they help
  168.  reduce typing, and are not so dangerous.
  169. *)
  170.  IF AS.RequestDisk(num,name) THEN
  171.   WITH controller.disk[num] DO
  172.  
  173.  (* Critical section *)
  174. (*!!   E.ObtainSemaphore(ADR(lock)); !!*)
  175.    state:=noDisk;
  176.    trackStart:=0; trackEnd:=0; trackPos:=0;
  177.    IF data=NIL THEN
  178.     Heap.Allocate(data,SIZE(DiskBuffer));
  179.     N(data,errNoDiskBuffer);
  180.    END;
  181. (*!!   E.ReleaseSemaphore(ADR(lock)); !!*)
  182.  
  183.    f:=D.Open(ADR(name),d.oldFile);
  184.    IF f#NIL THEN
  185.     dummy:=D.Read(f,data,SIZE(DiskBuffer));
  186.     FOR i:=1 TO currentTrack DO
  187.      trackLength:=data^[trackStart]+hi*data^[trackStart+1];
  188.      INC(trackStart,trackLength+4);
  189.     END;
  190.     trackLength:=data^[trackStart]+hi*data^[trackStart+1];
  191.     INC(trackStart,2);
  192.     trackEnd:=trackStart+trackLength;
  193.     trackPos:=trackStart;
  194.     state:=normalDisk;
  195.    ELSE
  196.     Heap.Deallocate(data); data:=NIL;
  197.    END;
  198.   END;
  199.  END;
  200. END DiskLoad;
  201.  
  202. PROCEDURE DiskProtect(num:AS.DiskNum; protect:AS.Protected);
  203. BEGIN
  204. (*
  205.  I usually don't like WITH statements, but here they help
  206.  reduce typing, and are not so dangerous.
  207. *)
  208.  WITH controller.disk[num] DO
  209.   CASE state OF
  210.   | noDisk: (* no change *)
  211.   | normalDisk: IF protect THEN state:=protectedDisk; END;
  212.   | protectedDisk: IF ~protect THEN state:=normalDisk; END;
  213.   END;
  214.  END;
  215. END DiskProtect;
  216.  
  217. PROCEDURE RST;
  218. BEGIN
  219. (*
  220.  Stack pointer is (mysteriously) decremented by three, but
  221.  the stack content is not changed.
  222.  
  223.  No other registers are modified by a reset.
  224. *)
  225. (*$ OverflowChk:=FALSE *)
  226.  DEC(reg.sp,3);
  227. (*$ POP OverflowChk *)
  228.  
  229.  reg.pc:=Address(rom[resetVector])+hi*rom[resetVector+1]-1;
  230.  (* will be incremented when processor starts. *)
  231.  doReset:=FALSE;
  232. END RST;
  233.  
  234. PROCEDURE InitProcessor;
  235. BEGIN
  236.  reg.a:=0; reg.x:=0; reg.y:=0;
  237.  reg.sp:=0;
  238.  
  239.  carry:=FALSE; zero:=TRUE; irqDisable:=TRUE; decimal:=FALSE;
  240.  break:=TRUE;(* unused:=TRUE;*) overflow:=FALSE; negative:=FALSE;
  241.  
  242.  RST;
  243. END InitProcessor;
  244.  
  245. (*
  246.  Initialise Apple related stuff.
  247. *)
  248.  
  249. PROCEDURE InitDisk;
  250. BEGIN
  251.  controller.currentDrive:=1;
  252.  controller.disk[1].state:=noDisk;
  253.  controller.disk[1].step:=0;
  254.  controller.disk[1].currentTrack:=0;
  255.  controller.disk[1].trackStart:=0;
  256.  controller.disk[1].trackEnd:=0;
  257.  controller.disk[1].trackPos:=0;
  258.  controller.disk[1].data:=NIL;
  259.  E.InitSemaphore(ADR(controller.disk[1].lock));
  260.  controller.disk[2].state:=noDisk;
  261.  controller.disk[2].step:=0;
  262.  controller.disk[2].currentTrack:=0;
  263.  controller.disk[2].trackStart:=0;
  264.  controller.disk[2].trackEnd:=0;
  265.  controller.disk[2].trackPos:=0;
  266.  controller.disk[2].data:=NIL;
  267.  E.InitSemaphore(ADR(controller.disk[2].lock));
  268.  DiskLoad(1);
  269. END InitDisk;
  270.  
  271. PROCEDURE InitApple(VAR err:BOOLEAN);
  272. VAR
  273.  addr:Address;
  274.  col,line:[0..23];
  275.  f:d.FileHandlePtr;
  276. BEGIN
  277.  err:=FALSE;
  278.  FOR line:=0 TO 23 DO
  279.   addr:=text1Start+(Address(line) MOD 8)*080H+(line DIV 8)*028H;
  280.   AS.PutText(line,0,ADR(ram[addr]),40);
  281.  END;
  282.  f:=D.Open(ADR(basicRomFile),d.oldFile);
  283.  IF f=NIL THEN A(FALSE,errNoBasic); err:=TRUE;
  284.  ELSE
  285.   IF D.Read(f,ADR(rom[romStart]),romLength)#romLength THEN
  286.    A(FALSE,errReadBasic); err:=TRUE;
  287.   END;
  288.   D.Close(f);
  289.  END;
  290.  f:=D.Open(ADR(diskPromFile),d.oldFile);
  291.  IF f=NIL THEN A(FALSE,errNoDisk); err:=TRUE;
  292.  ELSE
  293.   IF D.Read(f,ADR(prom[promStart]),promLength)#promLength THEN
  294.    A(FALSE,errReadDisk); err:=TRUE;
  295.   END;
  296.   D.Close(f);
  297.  END;
  298. (*
  299.  Some patches to reduce boot time, especially during test phase.
  300. *)
  301.  rom[0FCA8H]:=0A9H; (* Patch LDA #0, RTS at start of WAIT *)
  302.  rom[0FCA9H]:=000H;
  303.  rom[0FCAAH]:=060H;
  304.  rom[0FBE3H]:=001H; (* Patch to shorten Bell duration to one cycle *)
  305.  clockCount:=0;
  306.  InitDisk;
  307. END InitApple;
  308.  
  309. PROCEDURE ADC;
  310. TYPE
  311.  XSet=SET OF [0..15];
  312. VAR
  313.  a{R.D2},b{R.D3},c:INTEGER;
  314.  x{R.D4},y{R.D5},z:INTEGER;
  315.  lo:INTEGER;
  316. BEGIN
  317.  a:=CAST(SignedByte,reg.a); b:=CAST(SignedByte,operand);
  318.  x:=reg.a; y:=operand;
  319.  IF carry THEN c:=1; z:=1; ELSE c:=0; z:=0; END;
  320.  a:=a+b+c;
  321.  overflow:=(a<-128) OR (a>127);
  322.  IF decimal THEN
  323.   lo:=(x MOD 16)+(y MOD 16)+z;
  324.   IF lo>10 THEN lo:=((lo-10) MOD 16)+16; END; (* last +16 is the carry. *)
  325.   x:=CAST(INTEGER,CAST(XSet,x)*XSet{4..7})+CAST(INTEGER,CAST(XSet,y)*XSet{4..7})+lo;
  326.   carry:=x>9*16+9;
  327.   IF carry THEN x:=x-10*16; END;
  328.  ELSE
  329.   x:=x+y+z;
  330.   carry:=x>255;
  331.  END;
  332. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  333.  reg.a:=Byte(x);
  334. (*$ POP OverflowChk POP RangeChk *)
  335.  zero:=(a MOD hi)=0;
  336.  negative:=ODD(a DIV 128);
  337. END ADC;
  338.  
  339. PROCEDURE CMP;
  340. VAR
  341.  a{R.D2},b{R.D3}:INTEGER;
  342.  x{R.D4},y{R.D5}:INTEGER;
  343.  lo:INTEGER;
  344. BEGIN
  345.  a:=CAST(SignedByte,reg.a); b:=CAST(SignedByte,operand);
  346.  x:=reg.a; y:=operand;
  347.  a:=a-b;
  348.  overflow:=(a<-128) OR (a>127);
  349.  x:=x-y;
  350.  carry:=x>=0;
  351. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  352.  a:=Byte(x);
  353. (*$ POP OverflowChk POP RangeChk *)
  354.  zero:=a=0;
  355.  negative:=a>=128;
  356. END CMP;
  357.  
  358. PROCEDURE SBC;
  359. TYPE
  360.  XSet=SET OF [0..15];
  361. VAR
  362.  a{R.D2},b{R.D3},c:INTEGER;
  363.  x{R.D4},y{R.D5},z:INTEGER;
  364.  lo:INTEGER;
  365. BEGIN
  366.  a:=CAST(SignedByte,reg.a); b:=CAST(SignedByte,operand);
  367.  x:=reg.a; y:=operand;
  368.  IF carry THEN c:=0; z:=0; ELSE c:=1; z:=1; END;
  369.  a:=a-b-c;
  370.  overflow:=(a<-128) OR (a>127);
  371.  IF decimal THEN
  372.   HALT;
  373.   lo:=(x MOD 16)+(y MOD 16)+z;
  374.   IF lo>10 THEN lo:=((lo-10) MOD 16)+16; END; (* last +16 is the carry. *)
  375.   x:=CAST(INTEGER,CAST(XSet,x)*XSet{4..7})+CAST(INTEGER,CAST(XSet,y)*XSet{4..7})+lo;
  376.   carry:=x>9*16+9;
  377.   IF carry THEN x:=x-10*16; END;
  378.  ELSE
  379.   x:=x-y-z;
  380.   carry:=x>=0;
  381.  END;
  382. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  383.  reg.a:=Byte(x);
  384. (*$ POP OverflowChk POP RangeChk *)
  385.  zero:=(a MOD hi)=0;
  386.  negative:=ODD(a DIV 128);
  387. END SBC;
  388.  
  389. PROCEDURE CPX;
  390. VAR
  391.  a{R.D2},b{R.D3}:INTEGER;
  392.  x{R.D4},y{R.D5}:INTEGER;
  393.  lo:INTEGER;
  394. BEGIN
  395.  a:=CAST(SignedByte,reg.x); b:=CAST(SignedByte,operand);
  396.  x:=reg.x; y:=operand;
  397.  a:=a-b;
  398.  overflow:=(a<-128) OR (a>127);
  399.  x:=x-y;
  400.  carry:=x>=0;
  401. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  402.  a:=Byte(x);
  403. (*$ POP OverflowChk POP RangeChk *)
  404.  zero:=a=0;
  405.  negative:=a>=128;
  406. END CPX;
  407.  
  408. PROCEDURE CPY;
  409. VAR
  410.  a{R.D2},b{R.D3}:INTEGER;
  411.  x{R.D4},y{R.D5}:INTEGER;
  412.  lo:INTEGER;
  413. BEGIN
  414.  a:=CAST(SignedByte,reg.y); b:=CAST(SignedByte,operand);
  415.  x:=reg.y; y:=operand;
  416.  a:=a-b;
  417.  overflow:=(a<-128) OR (a>127);
  418.  x:=x-y;
  419.  carry:=x>=0;
  420. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  421.  a:=Byte(x);
  422. (*$ POP OverflowChk POP RangeChk *)
  423.  zero:=a=0;
  424.  negative:=a>=128;
  425. END CPY;
  426.  
  427. PROCEDURE ROL;
  428. VAR
  429.  oldCarry{R.D2}:Byte;
  430. BEGIN
  431.  IF carry THEN oldCarry:=1; ELSE oldCarry:=0; END;
  432.  carry:=operand>=128;
  433. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  434.  operand:=2*operand+oldCarry;
  435. (*$ POP OverflowChk POP RangeChk *)
  436.  zero:=operand=0;
  437.  negative:=operand>=128;
  438. END ROL;
  439.  
  440. PROCEDURE ROR;
  441. VAR
  442.  oldCarry{R.D2}:Byte;
  443. BEGIN
  444.  IF carry THEN oldCarry:=128; ELSE oldCarry:=0; END;
  445.  carry:=ODD(operand);
  446.  operand:=(operand DIV 2)+oldCarry;
  447.  zero:=operand=0;
  448.  negative:=operand>=128;
  449. END ROR;
  450.  
  451. PROCEDURE ASL; BEGIN
  452.  carry:=operand>=128;
  453. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  454.  operand:=2*operand;
  455. (*$ POP OverflowChk POP RangeChk *)
  456.  zero:=operand=0;
  457.  negative:=operand>=128;
  458. END ASL;
  459.  
  460. PROCEDURE PHP;
  461. VAR
  462.  temp{R.D2}:Byte;
  463. BEGIN
  464.  temp:=20H; (* unused is always set *)
  465.  IF carry THEN INC(temp,1); END;
  466.  IF zero THEN INC(temp,2); END;
  467.  IF irqDisable THEN INC(temp,4); END;
  468.  IF decimal THEN INC(temp,8); END;
  469.  IF break THEN INC(temp,10H); END;
  470.  (* unused already set on temp initialization *)
  471.  IF overflow THEN INC(temp,40H); END;
  472.  IF negative THEN INC(temp,80H); END;
  473.  ram[stackBase+reg.sp]:=temp; DEC(reg.sp);
  474. END PHP;
  475.  
  476. PROCEDURE PLP;
  477. VAR
  478.  temp{R.D2}:Byte;
  479. BEGIN
  480.  INC(reg.sp); temp:=ram[stackBase+reg.sp];
  481.  carry:=ODD(temp);
  482.  zero:=ODD(temp DIV 2);
  483.  irqDisable:=ODD(temp DIV 4);
  484.  decimal:=ODD(temp DIV 8);
  485.  (* break and ununsed are not modified *)
  486.  overflow:=ODD(temp DIV 40H);
  487.  negative:=temp>=80H;
  488. END PLP;
  489.  
  490. PROCEDURE RTI;
  491. VAR
  492.  stack{R.D2}:Address;
  493.  temp{R.D3}:Address;
  494. BEGIN
  495. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  496.  INC(reg.sp); temp:=ram[stackBase+reg.sp];
  497.  carry:=ODD(temp);
  498.  zero:=ODD(temp DIV 2);
  499.  irqDisable:=ODD(temp DIV 4);
  500.  decimal:=ODD(temp DIV 8);
  501.  (* break and ununsed are not modified *)
  502.  overflow:=ODD(temp DIV 40H);
  503.  negative:=ODD(temp DIV 80H);
  504.  INC(reg.sp); temp:=ram[stackBase+reg.sp];
  505.  INC(reg.sp); reg.pc:=temp+hi*ram[stackBase+reg.sp];
  506. (*$ POP OverflowChk POP RangeChk *)
  507. END RTI;
  508.  
  509. PROCEDURE BRK;
  510. VAR
  511.  stack{R.D2}:Address;
  512.  temp{R.D3}:Byte;
  513. BEGIN
  514.  ram[stackBase+reg.sp]:=reg.pc DIV hi; DEC(reg.sp);
  515.  ram[stackBase+reg.sp]:=reg.pc MOD hi; DEC(reg.sp);
  516.  temp:=20H; (* unused is always set *)
  517.  IF carry THEN INC(temp,1); END;
  518.  IF zero THEN INC(temp,2); END;
  519.  IF irqDisable THEN INC(temp,4); END;
  520.  IF decimal THEN INC(temp,8); END;
  521.  IF break THEN INC(temp,10H); END;
  522.  (* unused already set on temp initialization *)
  523.  IF overflow THEN INC(temp,40H); END;
  524.  IF negative THEN INC(temp,80H); END;
  525.  ram[stackBase+reg.sp]:=temp; DEC(reg.sp);
  526.  reg.pc:=Address(rom[irqVector])+rom[irqVector+1]*hi-1;
  527.  (* -1 because it will be incremented before instruction fetch *)
  528.  irqDisable:=TRUE; break:=TRUE;
  529. END BRK;
  530.  
  531. (*
  532.  Memory access routines. They have to verify, if special
  533.  locations are accessed.
  534. *)
  535.  
  536. PROCEDURE IORead(addr{R.D7}:Address);
  537. VAR
  538.  trackLength:LONGCARD;
  539. BEGIN
  540.  CASE addr DIV hi OF
  541.  | io0Page:
  542.   CASE addr DIV 16 MOD 16 OF
  543.   | 00H: operand:=AS.lastKey;
  544.   | 01H: IF AS.lastKey>=080H THEN DEC(AS.lastKey,080H); END;
  545.   | 0EH: (* Disk *)
  546.    CASE addr MOD 16 OF
  547.    | 00H:
  548.     (*
  549.      I usually hate WITH statements, but this would have been too much
  550.      writing otherwise.
  551.     *)
  552.     WITH controller.disk[controller.currentDrive] DO
  553.      IF step=3 THEN
  554.  
  555. (* Critical section *)
  556. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  557.       IF currentTrack<maxTrack THEN
  558.        INC(currentTrack);
  559.        IF state#noDisk THEN
  560.         trackStart:=trackEnd+4;
  561.         trackLength:=data^[trackStart-2]+hi*data^[trackStart-1];
  562.         trackEnd:=trackStart+trackLength;
  563.         trackPos:=trackStart;
  564.        END;
  565.       END;
  566. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  567.  
  568.       step:=0;
  569.      ELSIF step=1 THEN
  570.  
  571. (* Critical section *)
  572. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  573.       IF minTrack<currentTrack THEN
  574.        DEC(currentTrack);
  575.        IF state#noDisk THEN
  576.         trackEnd:=trackStart-4;
  577.         trackLength:=data^[trackEnd]+hi*data^[trackEnd+1];
  578.         trackStart:=trackEnd-trackLength;
  579.         trackPos:=trackStart;
  580.        END;
  581.       END;
  582. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  583.  
  584.       step:=0;
  585.      END;
  586. (*$ IF Debug AND Track *)
  587.      T.FormatNr("DISK %ld",controller.currentDrive);
  588.      T.FormatNr("  T=%2ld",currentTrack);
  589.      T.FormatNr("(%ld)\n",step);
  590. (*$ ENDIF *)
  591.     END;
  592.    | 01H: (* ignore *)
  593.    | 02H:
  594.      (*
  595.       I usually hate WITH statements, but this would have been too much
  596.       writing otherwise.
  597.      *)
  598.      WITH controller.disk[controller.currentDrive] DO
  599.       IF (step=0) OR (step=2) THEN step:=1; END;
  600. (*$ IF Debug AND Track *)
  601.      T.FormatNr("DISK %ld",controller.currentDrive);
  602.      T.FormatNr("  T=%2ld",currentTrack);
  603.      T.FormatNr("(%ld)\n",step);
  604. (*$ ENDIF *)
  605.      END;
  606.    | 03H: (* ignore *)
  607.    | 04H:
  608.     (*
  609.      I usually hate WITH statements, but this would have been too much
  610.      writing otherwise.
  611.     *)
  612.     WITH controller.disk[controller.currentDrive] DO
  613.      IF step=1 THEN
  614.  
  615. (* Critical section *)
  616. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  617.       IF currentTrack<maxTrack THEN
  618.        INC(currentTrack);
  619.        IF state#noDisk THEN
  620.         trackStart:=trackEnd+4;
  621.         trackLength:=data^[trackStart-2]+hi*data^[trackStart-1];
  622.         trackEnd:=trackStart+trackLength;
  623.         trackPos:=trackStart;
  624.        END;
  625.       END;
  626. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  627.  
  628.       step:=2;
  629.      ELSIF step=3 THEN
  630.  
  631. (* Critical section *)
  632. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  633.       IF minTrack<currentTrack THEN
  634.        DEC(currentTrack);
  635.        IF state#noDisk THEN
  636.         trackEnd:=trackStart-4;
  637.         trackLength:=data^[trackEnd]+hi*data^[trackEnd+1];
  638.         trackStart:=trackEnd-trackLength;
  639.         trackPos:=trackStart;
  640.        END;
  641.       END;
  642. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  643.  
  644.       step:=2;
  645.      END;
  646. (*$ IF Debug AND Track *)
  647.      T.FormatNr("DISK %ld",controller.currentDrive);
  648.      T.FormatNr("  T=%2ld",currentTrack);
  649.      T.FormatNr("(%ld)\n",step);
  650. (*$ ENDIF *)
  651.     END;
  652.    | 05H: (* ignore *)
  653.    | 06H:
  654.      (*
  655.       I usually hate WITH statements, but this would have been too much
  656.       writing otherwise.
  657.      *)
  658.      WITH controller.disk[controller.currentDrive] DO
  659.       IF (step=2) OR (step=0) THEN step:=3; END;
  660. (*$ IF Debug AND Track *)
  661.      T.FormatNr("DISK %ld",controller.currentDrive);
  662.      T.FormatNr("  T=%2ld",currentTrack);
  663.      T.FormatNr("(%ld)\n",step);
  664. (*$ ENDIF *)
  665.      END;
  666.    | 07H: (* ignore *)
  667.    | 08H:
  668.     controller.disk[controller.currentDrive].motorOn:=FALSE;
  669.    | 09H:
  670.     controller.disk[controller.currentDrive].motorOn:=TRUE;
  671.    | 0AH:
  672.     IF controller.currentDrive#1 THEN
  673.      controller.disk[1].motorOn:=controller.disk[2].motorOn;
  674.      controller.disk[2].motorOn:=FALSE;
  675.      controller.currentDrive:=1;
  676.     END;
  677.    | 0BH:
  678.     IF controller.currentDrive#2 THEN
  679.      controller.disk[2].motorOn:=controller.disk[1].motorOn;
  680.      controller.disk[1].motorOn:=FALSE;
  681.      controller.currentDrive:=2;
  682.     END;
  683.    | 0CH:
  684.     (*
  685.      I usually hate WITH statements, but this would have been too much
  686.      writing otherwise.
  687.     *)
  688.     WITH controller.disk[controller.currentDrive] DO
  689.      q6:=FALSE;
  690.  
  691. (* Critical section *)
  692. (*!!     E.ObtainSemaphore(ADR(lock)); !!*)
  693.      IF motorOn & (state#noDisk) THEN
  694.       IF q7 THEN
  695.        IF state=normalDisk THEN data^[trackPos]:=latch; END;
  696.       ELSE
  697.        operand:=data^[trackPos];
  698.       END;
  699.       INC(trackPos);
  700.       IF trackPos=trackEnd THEN trackPos:=trackStart; END;
  701. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  702.  
  703.      ELSE
  704.       operand:=0;
  705.      END;
  706.     END;
  707.    | 0DH:
  708.     controller.disk[controller.currentDrive].q6:=TRUE;
  709.    | 0EH:
  710.     (*
  711.      I usually hate WITH statements, but this would have been too much
  712.      writing otherwise.
  713.     *)
  714.     WITH controller.disk[controller.currentDrive] DO
  715.      q7:=FALSE;
  716.      IF motorOn & q6 THEN
  717.       IF state=protectedDisk THEN operand:=255; ELSE operand:=0; END;
  718.      ELSE
  719.       operand:=0;
  720.      END;
  721.     END;
  722.    | 0FH:
  723.     controller.disk[controller.currentDrive].q7:=TRUE;
  724.    END;
  725.   ELSE (* temporarly ignore I/O access *)
  726.   END;
  727.  | 0C1H..0C5H: (* temporarly I/O access *)
  728.  | promStart DIV hi: (* Disk Prom *)
  729.   operand:=prom[addr];
  730.  | 0C7H..0CFH: (* temporarly I/O access *)
  731.  END;
  732. END IORead;
  733.  
  734. PROCEDURE ReadCheck;
  735. VAR
  736.  page{R.D2}:Address;
  737. BEGIN
  738.  CASE memAddr DIV hi OF
  739.  | (ramStart DIV hi)..(ramEnd DIV hi): operand:=ram[memAddr];
  740.  | 0C0H..0CFH: IORead(memAddr);
  741.  | (romStart DIV hi)..(romEnd DIV hi): operand:=rom[memAddr];
  742.  END;
  743. END ReadCheck;
  744.  
  745.  
  746. PROCEDURE NextPC; FORWARD;
  747.  
  748. PROCEDURE NextRamPC;
  749. VAR
  750.  temp{R.D2},page{R.D3}:Address;
  751. BEGIN
  752.  temp:=reg.pc+1;
  753.  page:=temp DIV hi;
  754.  IF ((ramStart DIV hi)<=page) & (page<=(ramEnd DIV hi)) THEN
  755.   operand:=ram[temp]; reg.pc:=temp;
  756.  ELSE
  757.   NextPC;
  758.  END;
  759. END NextRamPC;
  760.  
  761. PROCEDURE NextRomPC;
  762. VAR
  763.  temp{R.D2}:Address;
  764. BEGIN
  765.  temp:=reg.pc+1;
  766.  IF romStart<=temp THEN
  767.   operand:=rom[temp]; reg.pc:=temp;
  768.  ELSE
  769.   NextPC;
  770.  END;
  771. END NextRomPC;
  772.  
  773. PROCEDURE NextPC;
  774. VAR
  775.  temp{R.D2}:Address;
  776. BEGIN
  777.  temp:=reg.pc+1; reg.pc:=temp;
  778.  CASE temp DIV hi OF
  779.  | (ramStart DIV hi)..(ramEnd DIV hi): operand:=ram[temp]; nextPC:=NextRamPC;
  780.  | io0Page..0CFH: IORead(temp); nextPC:=NextPC;
  781.  | (romStart DIV hi)..(romEnd DIV hi): operand:=rom[temp]; nextPC:=NextRomPC;
  782.  END;
  783. END NextPC;
  784.  
  785. PROCEDURE NextPC2; FORWARD;
  786.  
  787. PROCEDURE NextRamPC2;
  788. VAR
  789.  temp{R.D2},page{R.D3},offset{R.D4}:Address;
  790. BEGIN
  791.  temp:=reg.pc+1;
  792.  offset:=temp MOD hi; page:=temp DIV hi;
  793.  IF (offset<0FFH) & ((ramStart DIV hi)<=page) & (page<=(ramEnd DIV hi)) THEN
  794.   memAddr:=ram[temp]+hi*ram[temp+1]; reg.pc:=temp+1;
  795.  ELSE (* handle the normal way *)
  796.   NextPC2;
  797.  END;
  798. END NextRamPC2;
  799.  
  800. PROCEDURE NextRomPC2;
  801. VAR
  802.  temp{R.D2},page{R.D3},offset{R.D4}:Address;
  803. BEGIN
  804.  temp:=reg.pc+1;
  805.  offset:=temp MOD hi; page:=temp DIV hi;
  806.  IF (offset<0FFH) & ((romStart DIV hi)<=page) & (page<=(romEnd DIV hi)) THEN
  807.    memAddr:=rom[temp]+hi*rom[temp+1]; reg.pc:=temp+1
  808.  ELSE (* handle the normal way *)
  809.   NextPC2;
  810.  END;
  811. END NextRomPC2;
  812.  
  813. PROCEDURE NextPC2;
  814. VAR
  815.  temp{R.D2},page{R.D3},offset{R.D4}:Address;
  816. BEGIN
  817.  temp:=reg.pc+1;
  818.  offset:=temp MOD hi;
  819.  IF offset<0FFH THEN
  820.   page:=temp DIV hi;
  821.   CASE page OF
  822.   | (ramStart DIV hi)..(ramEnd DIV hi):
  823.    memAddr:=ram[temp]+hi*ram[temp+1]; nextPC2:=NextRamPC2; reg.pc:=temp+1;
  824.   | io0Page..0CFH: (* handle the normal way *)
  825.    NextPC; memAddr:=operand;
  826.    NextPC; memAddr:=operand*hi+memAddr;
  827.    nextPC2:=NextPC2;
  828.   | (romStart DIV hi)..(romEnd DIV hi):
  829.    memAddr:=rom[temp]+hi*rom[temp+1]; nextPC2:=NextRomPC2; reg.pc:=temp+1;
  830.   END;
  831.  ELSE (* handle the normal way *)
  832.   NextPC; memAddr:=operand;
  833.   NextPC; memAddr:=operand*hi+memAddr;
  834.   nextPC2:=NextPC2;
  835.  END;
  836. END NextPC2;
  837.  
  838. (*
  839.  Memory modification routine. They have to verify if special
  840.  locations are addressed.
  841. *)
  842.  
  843. PROCEDURE WriteCheck;
  844. VAR
  845.  col{R.D2},line{R.D3}:Byte;
  846.  trackLength:LONGCARD;
  847. BEGIN
  848.  CASE memAddr DIV hi OF
  849.  | (ramStart DIV hi)..(text1Start DIV hi)-1: ram[memAddr]:=operand;
  850.  | (text1Start DIV hi)..(text1End DIV hi):
  851.   ram[memAddr]:=operand;
  852.   line:=((memAddr-text1Start) DIV 080H)+8*((memAddr-text1Start) MOD 080H DIV 028H);
  853.   IF line<24 THEN
  854.    col:=(memAddr-text1Start) MOD 080H MOD 028H;
  855.    AS.PutText(line,col,ADR(ram[memAddr]),1);
  856.   END;
  857.  | (text1End DIV hi)+1..(ramEnd DIV hi): ram[memAddr]:=operand;
  858.  | io0Page:
  859.   CASE memAddr DIV 16 MOD 16 OF
  860.   | 00H: (* NOP *)
  861.   | 01H: IF AS.lastKey>=080H THEN DEC(AS.lastKey,080H); END;
  862.   | 0EH: (* Disk *)
  863.    CASE memAddr MOD 16 OF
  864.    | 00H:
  865.     (*
  866.      I usually hate WITH statements, but this would have been too much
  867.      writing otherwise.
  868.     *)
  869.     WITH controller.disk[controller.currentDrive] DO
  870.      IF step=3 THEN
  871.  
  872. (* Critical section *)
  873. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  874.       IF currentTrack<maxTrack THEN
  875.        INC(currentTrack);
  876.        IF state#noDisk THEN
  877.         trackStart:=trackEnd+4;
  878.         trackLength:=data^[trackStart-2]+hi*data^[trackStart-1];
  879.         trackEnd:=trackStart+trackLength;
  880.         trackPos:=trackStart;
  881.        END;
  882.       END;
  883. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  884.  
  885.       step:=0;
  886.      ELSIF step=1 THEN
  887.  
  888. (* Critical section *)
  889. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  890.       IF minTrack<currentTrack THEN
  891.        DEC(currentTrack);
  892.        IF state#noDisk THEN
  893.         trackEnd:=trackStart-4;
  894.         trackLength:=data^[trackEnd]+hi*data^[trackEnd+1];
  895.         trackStart:=trackEnd-trackLength;
  896.         trackPos:=trackStart;
  897.        END;
  898.       END;
  899. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  900.  
  901.       step:=0;
  902.      END;
  903. (*$ IF Debug AND Track *)
  904.      T.FormatNr("DISK %ld",controller.currentDrive);
  905.      T.FormatNr("  T=%2ld",currentTrack);
  906.      T.FormatNr("(%ld)\n",step);
  907. (*$ ENDIF *)
  908.     END;
  909.    | 01H: (* ignore *)
  910.    | 02H:
  911.      (*
  912.       I usually hate WITH statements, but this would have been too much
  913.       writing otherwise.
  914.      *)
  915.      WITH controller.disk[controller.currentDrive] DO
  916.       IF (step=0) OR (step=2) THEN step:=1; END;
  917. (*$ IF Debug AND Track *)
  918.      T.FormatNr("DISK %ld",controller.currentDrive);
  919.      T.FormatNr("  T=%2ld",currentTrack);
  920.      T.FormatNr("(%ld)\n",step);
  921. (*$ ENDIF *)
  922.      END;
  923.    | 03H: (* ignore *)
  924.    | 04H:
  925.     (*
  926.      I usually hate WITH statements, but this would have been too much
  927.      writing otherwise.
  928.     *)
  929.     WITH controller.disk[controller.currentDrive] DO
  930.      IF step=1 THEN
  931.  
  932. (* Critical section *)
  933. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  934.       IF currentTrack<maxTrack THEN
  935.        INC(currentTrack);
  936.        IF state#noDisk THEN
  937.         trackStart:=trackEnd+4;
  938.         trackLength:=data^[trackStart-2]+hi*data^[trackStart-1];
  939.         trackEnd:=trackStart+trackLength;
  940.         trackPos:=trackStart;
  941.        END;
  942.       END;
  943. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  944.  
  945.       step:=2;
  946.      ELSIF step=3 THEN
  947.  
  948. (* Critical section *)
  949. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  950.       IF minTrack<currentTrack THEN
  951.        DEC(currentTrack);
  952.        IF state#noDisk THEN
  953.         trackEnd:=trackStart-4;
  954.         trackLength:=data^[trackEnd]+hi*data^[trackEnd+1];
  955.         trackStart:=trackEnd-trackLength;
  956.         trackPos:=trackStart;
  957.        END;
  958.       END;
  959. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  960.  
  961.       step:=2;
  962.      END;
  963. (*$ IF Debug AND Track *)
  964.      T.FormatNr("DISK %ld",controller.currentDrive);
  965.      T.FormatNr("  T=%2ld",currentTrack);
  966.      T.FormatNr("(%ld)\n",step);
  967. (*$ ENDIF *)
  968.     END;
  969.    | 05H: (* ignore *)
  970.    | 06H:
  971.      (*
  972.       I usually hate WITH statements, but this would have been too much
  973.       writing otherwise.
  974.      *)
  975.      WITH controller.disk[controller.currentDrive] DO
  976.       IF (step=2) OR (step=0) THEN step:=3; END;
  977. (*$ IF Debug AND Track *)
  978.      T.FormatNr("DISK %ld",controller.currentDrive);
  979.      T.FormatNr("  T=%2ld",currentTrack);
  980.      T.FormatNr("(%ld)\n",step);
  981. (*$ ENDIF *)
  982.      END;
  983.    | 07H: (* ignore *)
  984.    | 08H:
  985.     controller.disk[controller.currentDrive].motorOn:=FALSE;
  986.    | 09H:
  987.     controller.disk[controller.currentDrive].motorOn:=TRUE;
  988.    | 0AH:
  989.     IF controller.currentDrive#1 THEN
  990.      controller.disk[1].motorOn:=controller.disk[2].motorOn;
  991.      controller.disk[2].motorOn:=FALSE;
  992.      controller.currentDrive:=1;
  993.     END;
  994.    | 0BH:
  995.     IF controller.currentDrive#2 THEN
  996.      controller.disk[2].motorOn:=controller.disk[1].motorOn;
  997.      controller.disk[1].motorOn:=FALSE;
  998.      controller.currentDrive:=2;
  999.     END;
  1000.    | 0CH:
  1001.      (*
  1002.       I usually hate WITH statements, but this would have been too much
  1003.       writing otherwise.
  1004.      *)
  1005.      WITH controller.disk[controller.currentDrive] DO
  1006.       q6:=FALSE;
  1007.  
  1008. (* Critical section *)
  1009. (*!!      E.ObtainSemaphore(ADR(lock)); !!*)
  1010.       IF motorOn THEN
  1011.        IF q7 THEN
  1012.         data^[trackPos]:=latch; INC(trackPos);
  1013.         IF trackPos=trackEnd THEN trackPos:=trackStart; END;
  1014.        END;
  1015.       END;
  1016. (*!!      E.ReleaseSemaphore(ADR(lock)); !!*)
  1017.  
  1018.      END;
  1019.    | 0DH:
  1020.     controller.disk[controller.currentDrive].q6:=TRUE;
  1021.     controller.disk[controller.currentDrive].latch:=operand;
  1022.    | 0EH:
  1023.     controller.disk[controller.currentDrive].q7:=FALSE;
  1024.    | 0FH:
  1025.     controller.disk[controller.currentDrive].q7:=TRUE;
  1026.    END;
  1027.   END;
  1028.  | (romStart DIV hi)..(romEnd DIV hi): (* NOP *);
  1029.  END;
  1030. END WriteCheck;
  1031.  
  1032. (*
  1033.  The different addressing modes.
  1034. *)
  1035.  
  1036. PROCEDURE IndJmp;
  1037. VAR
  1038.  temp{R.D2}:Word;
  1039. BEGIN
  1040.  nextPC2;
  1041.  ReadCheck; jumpAddr:=operand;
  1042.  INC(memAddr);
  1043.  ReadCheck; jumpAddr:=jumpAddr+hi*operand;
  1044. END IndJmp;
  1045.  
  1046. PROCEDURE ZeroR; BEGIN
  1047.  nextPC;
  1048.  memAddr:=operand; (* needed by ROL,ROR,ASL,ASR *)
  1049.  operand:=ram[operand]; (* No ReadCheck needed for zero page *)
  1050. END ZeroR;
  1051.  
  1052. PROCEDURE IndX;
  1053. VAR
  1054.  temp{R.D2}:Byte;
  1055. BEGIN
  1056.  nextPC;
  1057.  temp:=(reg.x+operand) MOD hi;
  1058.  memAddr:=ram[temp]+hi*ram[(temp+1) MOD hi]; (* No ReadCheck needed for zero page *)
  1059.  (* memAddr has to be checked therefor operand is not modified here *)
  1060. END IndX;
  1061.  
  1062. PROCEDURE IndY;
  1063. VAR
  1064.  temp{R.D2}:Byte;
  1065. BEGIN
  1066.  nextPC; temp:=operand;
  1067.  memAddr:=ram[temp]+hi*ram[(temp+1) MOD hi]+reg.y; (* No ReadCheck needed for zero page *)
  1068.  (* memAddr has to be checked therefor operand is not modified here *)
  1069. END IndY;
  1070.  
  1071. PROCEDURE ZeroXR; BEGIN
  1072.  nextPC;
  1073.  memAddr:=(reg.x+operand) MOD hi; (* needed by DEC,INC,ROL,ROR,ASL,ASR *)
  1074.  operand:=ram[memAddr]; (* No ReadCheck needed for zero page *)
  1075. END ZeroXR;
  1076.  
  1077. (*$ OverflowChk:=FALSE RangeChk:=FALSE *)
  1078. PROCEDURE ProcessorLoop;
  1079. VAR
  1080.  temp{R.D2}:Byte;
  1081. (*$ IF Debug AND Commands *)
  1082.  tagbuf:ARRAY [0..19] OF LONGCARD;
  1083. (*$ ENDIF *)
  1084. BEGIN
  1085.  nextPC:=NextPC; nextPC2:=NextPC2; quit:=FALSE;
  1086.  LOOP
  1087.   IF quit THEN B; quit:=FALSE; END;
  1088.   IF doReset THEN RST; END;
  1089.   nextPC;
  1090. (*$ IF Debug AND Commands *)
  1091.   IF (clockCount MOD 020000H)<4 THEN (* Dump only a few commands *)
  1092.    T.Format(
  1093.     "P=%02lx-%02lx-%02lx-%02lx-%02lx-%02lx-%02lx-%02lx A=%02lx X=%02lx Y=%02lx S=1%02lx PC=%04lx(%02lx)\n",
  1094.     TAG(tagbuf
  1095.     ,negative,overflow,1,break,decimal,irqDisable,zero,carry,reg.a,reg.x,reg.y,reg.sp,reg.pc,operand
  1096.     )
  1097.    );
  1098.   END;
  1099.   IF Break.GetBreak()#LONGSET{} THEN B; END;
  1100. (*$ ENDIF *)
  1101.   IF operand<80H THEN
  1102.    CASE operand OF
  1103.    | 000H: (* BRK *)
  1104.     BRK;
  1105.     INC(clockCount,7);
  1106.  
  1107.    | 001H: (* ORA (Ind,X) *)
  1108.     IndX; ReadCheck;
  1109.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1110.     zero:=reg.a=0; negative:=reg.a>=128;
  1111.     INC(clockCount,6);
  1112.  
  1113.    | 005H: (* ORA Zero *)
  1114.     nextPC; operand:=ram[operand];
  1115.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1116.     zero:=reg.a=0; negative:=reg.a>=128;
  1117.     INC(clockCount,3);
  1118.  
  1119.    | 006H: (* ASL Zero *)
  1120.     ZeroR; ASL; ram[memAddr]:=operand;
  1121.     INC(clockCount,5);
  1122.  
  1123.    | 008H: (* PHP *)
  1124.     PHP;
  1125.     INC(clockCount,3);
  1126.  
  1127.    | 009H: (* ORA Imm *)
  1128.     nextPC;
  1129.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1130.     zero:=reg.a=0; negative:=reg.a>=128;
  1131.     INC(clockCount,2);
  1132.  
  1133.    | 00AH: (* ASL A *)
  1134.     operand:=reg.a; ASL; reg.a:=operand;
  1135.     INC(clockCount,2);
  1136.  
  1137.    | 00DH: (* ORA Abs *)
  1138.     nextPC2; ReadCheck;
  1139.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1140.     zero:=reg.a=0; negative:=reg.a>=128;
  1141.     INC(clockCount,4);
  1142.  
  1143.    | 00EH: (* ASL Abs *)
  1144.     nextPC2; ReadCheck; ASL; WriteCheck;
  1145.     INC(clockCount,6);
  1146.  
  1147.    | 010H: (* BPL Rel *)
  1148.     nextPC;
  1149.     IF ~negative THEN
  1150.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1151.      INC(clockCount,3);
  1152.     ELSE
  1153.      INC(clockCount,2);
  1154.     END;
  1155.  
  1156.    | 011H: (* ORA (Ind),Y *)
  1157.     IndY; ReadCheck;
  1158.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1159.     zero:=reg.a=0; negative:=reg.a>=128;
  1160.     INC(clockCount,5);
  1161.  
  1162.    | 015H: (* ORA Zero,X *)
  1163.     nextPC; operand:=ram[(reg.x+operand) MOD hi];
  1164.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1165.     zero:=reg.a=0; negative:=reg.a>=128;
  1166.     INC(clockCount,4);
  1167.  
  1168.    | 016H: (* ASL Zero,X *)
  1169.     ZeroXR; ASL; ram[memAddr]:=operand;
  1170.     INC(clockCount,6);
  1171.  
  1172.    | 018H: (* CLC *)
  1173.     carry:=FALSE;
  1174.     INC(clockCount,2);
  1175.  
  1176.    | 019H: (* ORA Abs,Y *)
  1177.     nextPC2; INC(memAddr,reg.y); ReadCheck;
  1178.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1179.     zero:=reg.a=0; negative:=reg.a>=128;
  1180.     INC(clockCount,4);
  1181.  
  1182.    | 01DH: (* ORA Abs,X *)
  1183.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1184.     reg.a:=CAST(Byte,CAST(Set,reg.a)+CAST(Set,operand));
  1185.     zero:=reg.a=0; negative:=reg.a>=128;
  1186.     INC(clockCount,4);
  1187.  
  1188.    | 01EH: (* ASL Abs,X *)
  1189.     nextPC2; INC(memAddr,reg.x); ReadCheck; ASL; WriteCheck;
  1190.     INC(clockCount,7);
  1191.  
  1192.    | 020H: (* JSR Abs *)
  1193.     nextPC2;
  1194.     ram[stackBase+reg.sp]:=reg.pc DIV hi; DEC(reg.sp);
  1195.     ram[stackBase+reg.sp]:=reg.pc MOD hi; DEC(reg.sp);
  1196.     reg.pc:=memAddr-1;
  1197.     INC(clockCount,6);
  1198.  
  1199.    | 021H: (* AND (Ind,X) *)
  1200.     IndX; ReadCheck;
  1201.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1202.     zero:=reg.a=0; negative:=reg.a>=128;
  1203.     INC(clockCount,6);
  1204.  
  1205.    | 024H: (* BIT Zero *)
  1206.     nextPC; operand:=ram[operand];
  1207.     temp:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1208.     zero:=temp=0; negative:=operand>=128; overflow:=ODD(operand DIV 64);
  1209.     INC(clockCount,3);
  1210.  
  1211.    | 025H: (* AND Zero *)
  1212.     nextPC; operand:=ram[operand];
  1213.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1214.     zero:=reg.a=0; negative:=reg.a>=128;
  1215.     INC(clockCount,3);
  1216.  
  1217.    | 026H: (* ROL Zero *)
  1218.     ZeroR; ROL; ram[memAddr]:=operand;
  1219.     INC(clockCount,5);
  1220.  
  1221.    | 028H: (* PLP *)
  1222.     PLP;
  1223.     INC(clockCount,3);
  1224.  
  1225.    | 029H: (* AND Imm *)
  1226.     nextPC;
  1227.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1228.     zero:=reg.a=0; negative:=reg.a>=128;
  1229.     INC(clockCount,2);
  1230.  
  1231.    | 02AH: (* ROL A *)
  1232.     operand:=reg.a; ROL; reg.a:=operand;
  1233.     INC(clockCount,2);
  1234.  
  1235.    | 02CH: (* BIT Abs *)
  1236.     nextPC2; ReadCheck;
  1237.     temp:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1238.     zero:=temp=0; negative:=operand>=128; overflow:=ODD(operand DIV 64);
  1239.     INC(clockCount,4);
  1240.  
  1241.    | 02DH: (* AND Abs *)
  1242.     nextPC2; ReadCheck;
  1243.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1244.     zero:=reg.a=0; negative:=reg.a>=128;
  1245.     INC(clockCount,4);
  1246.  
  1247.    | 02EH: (* ROL Abs *)
  1248.     nextPC2; ReadCheck; ROL; WriteCheck;
  1249.     INC(clockCount,6);
  1250.  
  1251.    | 030H: (* BMI Rel *)
  1252.     nextPC;
  1253.     IF negative THEN
  1254.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1255.      INC(clockCount,3);
  1256.     ELSE
  1257.      INC(clockCount,2);
  1258.     END;
  1259.  
  1260.    | 031H: (* AND (Ind),Y *)
  1261.     IndY; ReadCheck;
  1262.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1263.     zero:=reg.a=0; negative:=reg.a>=128;
  1264.     INC(clockCount,5);
  1265.  
  1266.    | 035H: (* AND Zero,X *)
  1267.     nextPC; operand:=ram[(reg.x+operand) MOD hi];
  1268.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1269.     zero:=reg.a=0; negative:=reg.a>=128;
  1270.     INC(clockCount,4);
  1271.  
  1272.    | 036H: (* ROL Zero,X *)
  1273.     ZeroXR; ROL; ram[memAddr]:=operand;
  1274.     INC(clockCount,6);
  1275.  
  1276.    | 038H: (* SEC *)
  1277.     carry:=TRUE;
  1278.     INC(clockCount,2);
  1279.  
  1280.    | 039H: (* AND Abs,Y *)
  1281.     nextPC2; INC(memAddr,reg.y); ReadCheck;
  1282.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1283.     zero:=reg.a=0; negative:=reg.a>=128;
  1284.     INC(clockCount,4);
  1285.  
  1286.    | 03DH: (* AND Abs,X *)
  1287.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1288.     reg.a:=CAST(Byte,CAST(Set,reg.a)*CAST(Set,operand));
  1289.     zero:=reg.a=0; negative:=reg.a>=128;
  1290.     INC(clockCount,4);
  1291.  
  1292.    | 03EH: (* ROL Abs,X *)
  1293.     nextPC2; INC(memAddr,reg.x); ReadCheck; ROL; WriteCheck;
  1294.     INC(clockCount,7);
  1295.  
  1296.    | 040H: (* RTI *)
  1297.     RTI;
  1298.     INC(clockCount,6);
  1299.  
  1300.    | 041H: (* EOR (Ind,X) *)
  1301.     IndX; ReadCheck;
  1302.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1303.     zero:=reg.a=0; negative:=reg.a>=128;
  1304.     INC(clockCount,6);
  1305.  
  1306.    | 045H: (* EOR Zero *)
  1307.     nextPC; operand:=ram[operand];
  1308.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1309.     zero:=reg.a=0; negative:=reg.a>=128;
  1310.     INC(clockCount,3);
  1311.  
  1312.    | 046H: (* LSR Zero *)
  1313.     nextPC;
  1314.     temp:=ram[operand];
  1315.     carry:=ODD(temp);
  1316.     temp:=temp DIV 2;
  1317.     zero:=temp=0; negative:=temp>=128;
  1318.     ram[operand]:=temp;
  1319.     INC(clockCount,5);
  1320.  
  1321.    | 048H: (* PHA *)
  1322.     ram[stackBase+reg.sp]:=reg.a; DEC(reg.sp);
  1323.     INC(clockCount,3);
  1324.  
  1325.    | 049H: (* EOR Imm *)
  1326.     nextPC;
  1327.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1328.     zero:=reg.a=0; negative:=reg.a>=128;
  1329.     INC(clockCount,2);
  1330.  
  1331.    | 04AH: (* LSR A *)
  1332.     carry:=ODD(reg.a);
  1333.     reg.a:=reg.a DIV 2;
  1334.     zero:=reg.a=0; negative:=reg.a>=128;
  1335.     INC(clockCount,2);
  1336.  
  1337.    | 04CH: (* JMP Abs *)
  1338.     nextPC2; reg.pc:=memAddr-1;
  1339.     INC(clockCount,3);
  1340.  
  1341.    | 04DH: (* EOR Abs *)
  1342.     nextPC2; ReadCheck;
  1343.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1344.     zero:=reg.a=0; negative:=reg.a>=128;
  1345.     INC(clockCount,4);
  1346.  
  1347.    | 04EH: (* LSR Abs *)
  1348.     nextPC2; ReadCheck;
  1349.     carry:=ODD(operand);
  1350.     operand:=operand DIV 2;
  1351.     zero:=operand=0; negative:=operand>=128;
  1352.     WriteCheck;
  1353.     INC(clockCount,6);
  1354.  
  1355.    | 050H: (* BVC Rel *)
  1356.     nextPC;
  1357.     IF ~overflow THEN
  1358.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1359.      INC(clockCount,3);
  1360.     ELSE
  1361.      INC(clockCount,2);
  1362.     END;
  1363.  
  1364.    | 051H: (* EOR (Ind),Y *)
  1365.     IndY; ReadCheck;
  1366.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1367.     zero:=reg.a=0; negative:=reg.a>=128;
  1368.     INC(clockCount,5);
  1369.  
  1370.    | 055H: (* EOR Zero,X *)
  1371.     nextPC; operand:=ram[(reg.x+operand) MOD hi];
  1372.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1373.     zero:=reg.a=0; negative:=reg.a>=128;
  1374.     INC(clockCount,4);
  1375.  
  1376.    | 056H: (* LSR Zero,X *)
  1377.     ZeroXR;
  1378.     carry:=ODD(operand);
  1379.     operand:=operand DIV 2;
  1380.     zero:=operand=0; negative:=operand>=128;
  1381.     ram[memAddr]:=operand;
  1382.     INC(clockCount,6);
  1383.  
  1384.    | 058H: (* CLI *)
  1385.     irqDisable:=FALSE;
  1386.     INC(clockCount,2);
  1387.  
  1388.    | 059H: (* EOR Abs,Y *)
  1389.     nextPC2; INC(memAddr,reg.y); ReadCheck;
  1390.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1391.     zero:=reg.a=0; negative:=reg.a>=128;
  1392.     INC(clockCount,4);
  1393.  
  1394.    | 05DH: (* EOR Abs,X *)
  1395.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1396.     reg.a:=CAST(Byte,CAST(Set,reg.a)/CAST(Set,operand));
  1397.     zero:=reg.a=0; negative:=reg.a>=128;
  1398.     INC(clockCount,4);
  1399.  
  1400.    | 05EH: (* LSR Abs,X *)
  1401.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1402.     carry:=ODD(operand);
  1403.     operand:=operand DIV 2;
  1404.     zero:=operand=0; negative:=operand>=128;
  1405.     WriteCheck;
  1406.     INC(clockCount,7);
  1407.  
  1408.    | 060H: (* RTS *)
  1409.     INC(reg.sp); temp:=ram[stackBase+reg.sp];
  1410.     INC(reg.sp); reg.pc:=temp+hi*ram[stackBase+reg.sp];
  1411.     INC(clockCount,6);
  1412.  
  1413.    | 061H: (* ADC (Ind,X) *)
  1414.     IndX; ReadCheck; ADC;
  1415.     INC(clockCount,6);
  1416.  
  1417.    | 065H: (* ADC Zero *)
  1418.     nextPC; operand:=ram[operand]; ADC;
  1419.     INC(clockCount,3);
  1420.  
  1421.    | 066H: (* ROR Zero *)
  1422.     ZeroR; ROR; ram[memAddr]:=operand;
  1423.     INC(clockCount,5);
  1424.  
  1425.    | 068H: (* PLA *)
  1426.     INC(reg.sp); reg.a:=ram[stackBase+reg.sp];
  1427.     zero:=reg.a=0; negative:=reg.a>=128;
  1428.     INC(clockCount,4);
  1429.  
  1430.    | 069H: (* ADC Imm *)
  1431.     nextPC; ADC;
  1432.     INC(clockCount,2);
  1433.  
  1434.    | 06AH: (* ROR A *)
  1435.     operand:=reg.a; ROR; reg.a:=operand;
  1436.     INC(clockCount,2);
  1437.  
  1438.    | 06CH: (* JMP (Ind) *)
  1439.     IndJmp; reg.pc:=jumpAddr-1;
  1440.     INC(clockCount,5);
  1441.  
  1442.    | 06DH: (* ADC Abs *)
  1443.     nextPC2; ReadCheck; ADC;
  1444.     INC(clockCount,4);
  1445.  
  1446.    | 06EH: (* ROR Abs *)
  1447.     nextPC2; ReadCheck; ROR; WriteCheck;
  1448.     INC(clockCount,6);
  1449.  
  1450.    | 070H: (* BVS Rel *)
  1451.     nextPC;
  1452.     IF overflow THEN
  1453.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1454.      INC(clockCount,3);
  1455.     ELSE
  1456.      INC(clockCount,2);
  1457.     END;
  1458.  
  1459.    | 071H: (* ADC (Ind),Y *)
  1460.     IndY; ReadCheck; ADC;
  1461.     INC(clockCount,5);
  1462.  
  1463.    | 075H: (* ADC Zero,X *)
  1464.     nextPC; operand:=ram[(reg.x+operand) MOD hi]; ADC;
  1465.     INC(clockCount,4);
  1466.  
  1467.    | 076H: (* ROR Zero,X *)
  1468.     ZeroXR; ROR; ram[memAddr]:=operand;
  1469.     INC(clockCount,6);
  1470.  
  1471.    | 078H: (* STI *)
  1472.     irqDisable:=TRUE;
  1473.     INC(clockCount,2);
  1474.  
  1475.    | 079H: (* ADC Abs,Y *)
  1476.     nextPC2; INC(memAddr,reg.y); ReadCheck; ADC;
  1477.     INC(clockCount,4);
  1478.  
  1479.    | 07DH: (* ADC Abs,X *)
  1480.     nextPC2; INC(memAddr,reg.x); ReadCheck; ADC;
  1481.     INC(clockCount,4);
  1482.  
  1483.    | 07EH: (* ROR Abs,X *)
  1484.     nextPC2; INC(memAddr,reg.x); ReadCheck; ROR; WriteCheck;
  1485.     INC(clockCount,7);
  1486.  
  1487.    ELSE
  1488.     HALT;
  1489.    END;
  1490.  
  1491.   ELSE
  1492.    CASE operand OF
  1493.    | 081H: (* STA (Ind,X) *)
  1494.     IndX; operand:=reg.a; WriteCheck;
  1495.     INC(clockCount,6);
  1496.  
  1497.    | 084H: (* STY Zero *)
  1498.     nextPC; ram[operand]:=reg.y;
  1499.     INC(clockCount,3);
  1500.  
  1501.    | 085H: (* STA Zero *)
  1502.     nextPC; ram[operand]:=reg.a;
  1503.     INC(clockCount,3);
  1504.  
  1505.    | 086H: (* STX Zero *)
  1506.     nextPC; ram[operand]:=reg.x;
  1507.     INC(clockCount,3);
  1508.  
  1509.    | 088H: (* DEY *)
  1510.     DEC(reg.y); zero:=reg.y=0; negative:=reg.y>=128;
  1511.     INC(clockCount,2);
  1512.  
  1513.    | 08AH: (* TXA *)
  1514.     reg.a:=reg.x; zero:=reg.a=0; negative:=reg.a>=128;
  1515.     INC(clockCount,2);
  1516.  
  1517.    | 08CH: (* STY Abs *)
  1518.     nextPC2; operand:=reg.y; WriteCheck;
  1519.     INC(clockCount,4);
  1520.  
  1521.    | 08DH: (* STA Abs *)
  1522.     nextPC2; operand:=reg.a; WriteCheck;
  1523.     INC(clockCount,4);
  1524.  
  1525.    | 08EH: (* STX Abs *)
  1526.     nextPC2; operand:=reg.x; WriteCheck;
  1527.     INC(clockCount,4);
  1528.  
  1529.    | 090H: (* BCC Rel *)
  1530.     nextPC;
  1531.     IF ~carry THEN
  1532.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1533.      INC(clockCount,3);
  1534.     ELSE
  1535.      INC(clockCount,2);
  1536.     END;
  1537.  
  1538.    | 091H: (* STA (Ind),Y *)
  1539.     IndY; operand:=reg.a; WriteCheck;
  1540.     INC(clockCount,6);
  1541.  
  1542.    | 094H: (* STY Zero,X *)
  1543.     nextPC; ram[(reg.x+operand) MOD hi]:=reg.y;
  1544.     INC(clockCount,4);
  1545.  
  1546.    | 095H: (* STA Zero,X *)
  1547.     nextPC; ram[(reg.x+operand) MOD hi]:=reg.a;
  1548.     INC(clockCount,4);
  1549.  
  1550.    | 096H: (* STX Zero,Y *)
  1551.     nextPC; ram[(reg.y+operand) MOD hi]:=reg.x;
  1552.     INC(clockCount,4);
  1553.  
  1554.    | 098H: (* TYA *)
  1555.     reg.a:=reg.y; zero:=reg.a=0; negative:=reg.a>=128;
  1556.     INC(clockCount,2);
  1557.  
  1558.    | 099H: (* STA Abs,Y *)
  1559.     nextPC2; INC(memAddr,reg.y); operand:=reg.a; WriteCheck;
  1560.     INC(clockCount,5);
  1561.  
  1562.    | 09AH: (* TXS *)
  1563.     reg.sp:=reg.x;
  1564.     INC(clockCount,2);
  1565.  
  1566.    | 09DH: (* STA Abs,X *)
  1567.     nextPC2; INC(memAddr,reg.x); operand:=reg.a; WriteCheck;
  1568.     INC(clockCount,5);
  1569.  
  1570.    | 0A0H: (* LDY Imm *)
  1571.     nextPC; reg.y:=operand; zero:=reg.y=0; negative:=reg.y>=128;
  1572.     INC(clockCount,2);
  1573.  
  1574.    | 0A1H: (* LDA (Ind,X) *)
  1575.     IndX; ReadCheck; reg.a:=operand; zero:=reg.a=0; negative:=reg.a>=128;
  1576.     INC(clockCount,6);
  1577.  
  1578.    | 0A2H: (* LDX Imm *)
  1579.     nextPC; reg.x:=operand; zero:=reg.x=0; negative:=reg.x>=128;
  1580.     INC(clockCount,2);
  1581.  
  1582.    | 0A4H: (* LDY Zero *)
  1583.     nextPC; reg.y:=ram[operand]; zero:=reg.y=0; negative:=reg.y>=128;
  1584.     INC(clockCount,3);
  1585.  
  1586.    | 0A5H: (* LDA Zero *)
  1587.     nextPC; reg.a:=ram[operand]; zero:=reg.a=0; negative:=reg.a>=128;
  1588.     INC(clockCount,3);
  1589.  
  1590.    | 0A6H: (* LDX Zero *)
  1591.     nextPC; reg.x:=ram[operand]; zero:=reg.x=0; negative:=reg.x>=128;
  1592.     INC(clockCount,3);
  1593.  
  1594.    | 0A8H: (* TAY *)
  1595.     reg.y:=reg.a; zero:=reg.y=0; negative:=reg.y>=128;
  1596.     INC(clockCount,2);
  1597.  
  1598.    | 0A9H: (* LDA Imm *)
  1599.     nextPC; reg.a:=operand; zero:=reg.a=0; negative:=reg.a>=128;
  1600.     INC(clockCount,2);
  1601.  
  1602.    | 0AAH: (* TAX *)
  1603.     reg.x:=reg.a; zero:=reg.x=0; negative:=reg.x>=128;
  1604.     INC(clockCount,2);
  1605.  
  1606.    | 0ACH: (* LDY Abs *)
  1607.     nextPC2; ReadCheck; reg.y:=operand; zero:=reg.y=0; negative:=reg.y>=128;
  1608.     INC(clockCount,4);
  1609.  
  1610.    | 0ADH: (* LDA Abs *)
  1611.     nextPC2; ReadCheck; reg.a:=operand; zero:=reg.a=0; negative:=reg.a>=128;
  1612.     INC(clockCount,4);
  1613.  
  1614.    | 0AEH: (* LDX Abs *)
  1615.     nextPC2; ReadCheck; reg.x:=operand; zero:=reg.x=0; negative:=reg.x>=128;
  1616.     INC(clockCount,4);
  1617.  
  1618.    | 0B0H: (* BCS Rel *)
  1619.     nextPC;
  1620.     IF carry THEN
  1621.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1622.      INC(clockCount,3);
  1623.     ELSE
  1624.      INC(clockCount,2);
  1625.     END;
  1626.  
  1627.    | 0B1H:(* LDA (Ind),Y *)
  1628.     IndY; ReadCheck; reg.a:=operand; zero:=reg.a=0; negative:=reg.a>=128;
  1629.     INC(clockCount,5);
  1630.  
  1631.    | 0B4H: (* LDY Zero,X *)
  1632.     nextPC; reg.y:=ram[(reg.x+operand) MOD hi]; zero:=reg.y=0; negative:=reg.y>=128;
  1633.     INC(clockCount,4);
  1634.  
  1635.    | 0B5H: (* LDA Zero,X *)
  1636.     nextPC; reg.a:=ram[(reg.x+operand) MOD hi]; zero:=reg.a=0; negative:=reg.a>=128;
  1637.     INC(clockCount,4);
  1638.  
  1639.    | 0B6H: (* LDX Zero,Y *)
  1640.     nextPC; reg.x:=ram[(reg.y+operand) MOD hi]; zero:=reg.x=0; negative:=reg.x>=128;
  1641.     INC(clockCount,4);
  1642.  
  1643.    | 0B8H: (* CLV *)
  1644.     overflow:=FALSE;
  1645.     INC(clockCount,2);
  1646.  
  1647.    | 0B9H: (* LDA Abs,Y *)
  1648.     nextPC2; INC(memAddr,reg.y); ReadCheck;
  1649.     reg.a:=operand; zero:=reg.a=0; negative:=reg.a>=128;
  1650.     INC(clockCount,4);
  1651.  
  1652.    | 0BAH: (* TSX *)
  1653.     reg.x:=reg.sp; zero:=reg.x=0; negative:=reg.x>=128;
  1654.     INC(clockCount,2);
  1655.  
  1656.    | 0BCH: (* LDY Abs,X *)
  1657.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1658.     reg.y:=operand; zero:=reg.y=0; negative:=reg.y>=128;
  1659.     INC(clockCount,4);
  1660.  
  1661.    | 0BDH: (* LDA Abs,X *)
  1662.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1663.     reg.a:=operand; zero:=reg.a=0; negative:=reg.a>=128;
  1664.     INC(clockCount,4);
  1665.  
  1666.    | 0BEH: (* LDX Abs,Y *)
  1667.     nextPC2; INC(memAddr,reg.y); ReadCheck;
  1668.     reg.x:=operand; zero:=reg.x=0; negative:=reg.x>=128;
  1669.     INC(clockCount,4);
  1670.  
  1671.    | 0C0H: (* CPY Imm *)
  1672.     nextPC; CPY;
  1673.     INC(clockCount,2);
  1674.  
  1675.    | 0C1H: (* CMP (Ind,X) *)
  1676.     IndX; ReadCheck; CMP;
  1677.     INC(clockCount,6);
  1678.  
  1679.    | 0C4H: (* CPY Zero *)
  1680.     nextPC; operand:=ram[operand]; CPY;
  1681.     INC(clockCount,3);
  1682.  
  1683.    | 0C5H: (* CMP Zero *)
  1684.     nextPC; operand:=ram[operand]; CMP;
  1685.     INC(clockCount,3);
  1686.  
  1687.    | 0C6H: (* DEC Zero *)
  1688.     nextPC; temp:=ram[operand]; DEC(temp); ram[operand]:=temp;
  1689.     zero:=temp=0; negative:=temp>=128;
  1690.     INC(clockCount,5);
  1691.  
  1692.    | 0C8H: (* INY *)
  1693.     INC(reg.y); zero:=reg.y=0; negative:=reg.y>=128;
  1694.     INC(clockCount,2);
  1695.  
  1696.    | 0C9H: (* CMP Imm *)
  1697.     nextPC; CMP;
  1698.     INC(clockCount,2);
  1699.  
  1700.    | 0CAH: (* DEX *)
  1701.     DEC(reg.x); zero:=reg.x=0; negative:=reg.x>=128;
  1702.     INC(clockCount,2);
  1703.  
  1704.    | 0CCH: (* CPY Abs *)
  1705.     nextPC2; ReadCheck; CPY;
  1706.     INC(clockCount,4);
  1707.  
  1708.    | 0CDH: (* CMP Abs *)
  1709.     nextPC2; ReadCheck; CMP;
  1710.     INC(clockCount,4);
  1711.  
  1712.    | 0CEH: (* DEC Abs *)
  1713.     nextPC2; ReadCheck;
  1714.     DEC(operand); zero:=operand=0; negative:=operand>=128;
  1715.     WriteCheck;
  1716.     INC(clockCount,6);
  1717.  
  1718.    | 0D0H: (* BNE Rel *)
  1719.     nextPC;
  1720.     IF ~zero THEN
  1721.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1722.      INC(clockCount,3);
  1723.     ELSE
  1724.      INC(clockCount,2);
  1725.     END;
  1726.  
  1727.    | 0D1H: (* CMP (Ind),Y *)
  1728.     IndY; ReadCheck; CMP;
  1729.     INC(clockCount,5);
  1730.  
  1731.    | 0D5H: (* CMP Zero,X *)
  1732.     nextPC; operand:=ram[(reg.x+operand) MOD hi]; CMP;
  1733.     INC(clockCount,4);
  1734.  
  1735.    | 0D6H: (* DEC Zero,X *)
  1736.     ZeroXR;
  1737.     DEC(operand); zero:=operand=0; negative:=operand>=128;
  1738.     ram[memAddr]:=operand;
  1739.     INC(clockCount,6);
  1740.  
  1741.    | 0D8H: (* CLD *)
  1742.     decimal:=FALSE;
  1743.     INC(clockCount,2);
  1744.  
  1745.    | 0D9H: (* CMP Abs,Y *)
  1746.     nextPC2; INC(memAddr,reg.y); ReadCheck; CMP;
  1747.     INC(clockCount,4);
  1748.  
  1749.    | 0DDH: (* CMP Abs,X *)
  1750.     nextPC2; INC(memAddr,reg.x); ReadCheck; CMP;
  1751.     INC(clockCount,4);
  1752.  
  1753.    | 0DEH: (* DEC Abs,X *)
  1754.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1755.     DEC(operand); zero:=operand=0; negative:=operand>=128;
  1756.     WriteCheck;
  1757.     INC(clockCount,7);
  1758.  
  1759.    | 0E0H: (* CPX Imm *)
  1760.     nextPC; CPX;
  1761.     INC(clockCount,2);
  1762.  
  1763.    | 0E1H: (* SBC (Ind,X) *)
  1764.     IndX; ReadCheck; SBC;
  1765.     INC(clockCount,6);
  1766.  
  1767.    | 0E4H: (* CPX Zero *)
  1768.     nextPC; operand:=ram[operand]; CPX;
  1769.     INC(clockCount,3);
  1770.  
  1771.    | 0E5H: (* SBC Zero *)
  1772.     nextPC; operand:=ram[operand]; SBC;
  1773.     INC(clockCount,3);
  1774.  
  1775.    | 0E6H: (* INC Zero *)
  1776.     nextPC; temp:=ram[operand]; INC(temp); ram[operand]:=temp;
  1777.     zero:=temp=0; negative:=temp>=128;
  1778.     INC(clockCount,5);
  1779.  
  1780.    | 0E8H: (* INX *)
  1781.     INC(reg.x); zero:=reg.x=0; negative:=reg.x>=128;
  1782.     INC(clockCount,2);
  1783.  
  1784.    | 0E9H: (* SBC Imm *)
  1785.     nextPC; SBC;
  1786.     INC(clockCount,2);
  1787.  
  1788.    | 0EAH: (* NOP *)
  1789.     INC(clockCount,2);
  1790.  
  1791.    | 0ECH: (* CPX Abs *)
  1792.     nextPC2; ReadCheck; CPX;
  1793.     INC(clockCount,4);
  1794.  
  1795.    | 0EDH: (* SBC Abs *)
  1796.     nextPC2; ReadCheck; SBC;
  1797.     INC(clockCount,4);
  1798.  
  1799.    | 0EEH: (* INC Abs *)
  1800.     nextPC2; ReadCheck;
  1801.     INC(operand); zero:=operand=0; negative:=operand>=128;
  1802.     WriteCheck;
  1803.     INC(clockCount,6);
  1804.  
  1805.    | 0F0H: (* BEQ Rel *)
  1806.     nextPC;
  1807.     IF zero THEN
  1808.      reg.pc:=CAST(Address,CAST(INTEGER,reg.pc)+CAST(SignedByte,operand));
  1809.      INC(clockCount,3);
  1810.     ELSE
  1811.      INC(clockCount,2);
  1812.     END;
  1813.  
  1814.    | 0F1H: (* SBC (Ind),Y *)
  1815.     IndY; ReadCheck; SBC;
  1816.     INC(clockCount,5);
  1817.  
  1818.    | 0F5H: (* SBC Zero,X *)
  1819.     nextPC; operand:=ram[(reg.x+operand) MOD hi]; SBC;
  1820.     INC(clockCount,4);
  1821.  
  1822.    | 0F6H: (* INC Zero,X *)
  1823.     ZeroXR;
  1824.     INC(operand); zero:=operand=0; negative:=operand>=128;
  1825.     ram[memAddr]:=operand;
  1826.     INC(clockCount,6);
  1827.  
  1828.    | 0F8H: (* SED *)
  1829.     decimal:=TRUE;
  1830.     INC(clockCount,2);
  1831.  
  1832.    | 0F9H: (* SBC Abs,Y *)
  1833.     nextPC2; INC(memAddr,reg.y); ReadCheck; SBC;
  1834.     INC(clockCount,4);
  1835.  
  1836.    | 0FDH: (* SBC Abs,X *)
  1837.     nextPC2; INC(memAddr,reg.x); ReadCheck; SBC;
  1838.     INC(clockCount,4);
  1839.  
  1840.    | 0FEH: (* Inc Abs,X *)
  1841.     nextPC2; INC(memAddr,reg.x); ReadCheck;
  1842.     INC(operand); zero:=operand=0; negative:=operand>=128;
  1843.     WriteCheck;
  1844.     INC(clockCount,7);
  1845.  
  1846.    ELSE
  1847.     HALT;
  1848.    END;
  1849.   END;
  1850.  END;
  1851. END ProcessorLoop;
  1852. (*$ POP OverflowChk POP RangeChk *)
  1853.  
  1854. VAR
  1855.  dummy,oldPri:SHORTINT;
  1856.  err:BOOLEAN;
  1857.  task:e.TaskPtr;
  1858. BEGIN
  1859. (*
  1860.  lower priority, as this program does not have any waits in it.
  1861. *)
  1862.  task:=E.FindTask(NIL);
  1863.  oldPri:=E.SetTaskPri(task,4);
  1864.  dummy:=E.SetTaskPri(task,oldPri-3);
  1865.  
  1866.  InitApple(err);
  1867.  IF ~err THEN
  1868.   InitProcessor;
  1869.   AS.quit:=SetQuit;
  1870.   AS.reset:=SetRST;
  1871.   AS.diskLoad:=DiskLoad;
  1872.   AS.diskUnload:=DiskUnload;
  1873.   AS.diskProtect:=DiskProtect;
  1874.   ProcessorLoop;
  1875.  END;
  1876. CLOSE
  1877. (*
  1878.  Restore tasks priority.
  1879. *)
  1880.  dummy:=E.SetTaskPri(task,oldPri);
  1881. END Apple.
  1882.