home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1364 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  58.3 KB

  1. From: skrenta@blekko.UUCP (Rich Skrenta)
  2. Newsgroups: alt.sources
  3. Subject: a2 - Apple II emulator, part 1/2
  4. Message-ID: <122@blekko.UUCP>
  5. Date: 23 May 90 16:34:28 GMT
  6.  
  7. Here's my Apple II emulator.  I can't post the ROM images, they're
  8. copyrighted, so keep in mind that you'll need them before you can do
  9. anything interesting with the emulator.
  10.  
  11. Features:  high level DOS 3.3 & Prodos interception, scroll interception,
  12.            memory map Disk II support (raw disk reads).
  13.            It's fast, too.  If you have one of those new spiffy RISC
  14.            workstations you may even be able to run the emulator at
  15.            the speed of the original Apple.
  16.  
  17. Doesn't have:  graphics, raw disk writes.
  18.  
  19. Send bug fixes and enhancements to me so they can be included in a
  20. future release.
  21.  
  22.  
  23. # This is a shell archive.  Remove anything before this line,
  24. # then unpack it by saving it in a file and typing "sh file".
  25. #
  26. # This archive contains:
  27. #    Makefile    Notes        Snarf        Cli.doc        
  28. #    a2.c        a2.h        curses.c    disk.c        
  29. #    tbl.c        
  30. #
  31.  
  32. echo x - Makefile
  33. cat >Makefile <<'@EOF'
  34.  
  35.  
  36. #
  37. #  Use -O if you can.  It gave a 20% speedup on one test.
  38. #
  39. CFLAGS = -O
  40. LIBS   = -lcurses -ltermcap
  41.  
  42. #  If Using 286 Xenix, uncomment the following lines:
  43. # CFLAGS  = -M2l -O
  44. # LARGE   = -LARGE
  45. #
  46. # Make SYSTEM be -DBSD for Berkeley-ish machines, leave blank otherwise
  47. #
  48. SYSTEM = 
  49. #SYSTEM = -DBSD
  50.  
  51.  
  52. OBJECTS =    a2.o table.o jump.o curses.o main.o screen.o \
  53.         mem.o tbl.o parse.o commands.o dos.o cli.o vidout.o \
  54.         disk.o prodos.o
  55.  
  56. a2:    $(OBJECTS)
  57.     cc -o a2 $(CFLAGS) $(OBJECTS) $(LIBS)
  58.  
  59. curses.o:    curses.c
  60.     cc -c $(SYSTEM) $(CFLAGS) curses.c
  61.  
  62. shar:
  63.     -mv ../a2.shar ../a2.shar-
  64.     shar -v Makefile Notes Snarf Cli.doc Todo *.[ch] > ../a2.shar
  65.  
  66. tar:
  67.     -mv ../a2.tar ../a2.tar-
  68.     tar -cvf ../a2.tar [A-Z]* *.[ch]
  69.  
  70. clean:
  71.     rm -f *.o core
  72.  
  73. clobber:    clean
  74.     rm -f a2
  75.  
  76.  
  77. a2.o:        a2.h a2.c
  78.     cc $(LARGE) $(CFLAGS) -c a2.c
  79.  
  80. cli.o:        cli.c a2.h cli.h
  81. commands.o:    commands.c cli.h a2.h
  82. disk.o:        disk.c a2.h
  83. dos.o:        dos.c a2.h
  84. jump.o:        jump.c a2.h
  85. main.o:        main.c a2.h
  86. mem.o:        mem.c a2.h
  87. parse.o:    parse.c cli.h a2.h
  88. pascal.o:    pascal.c a2.h
  89. screen.o:    screen.c a2.h
  90. table.o:    table.c a2.h
  91. tbl.o:        tbl.c cli.h a2.h
  92. vidout.o:    vidout.c a2.h
  93. @EOF
  94.  
  95. chmod 644 Makefile
  96.  
  97. echo x - Notes
  98. cat >Notes <<'@EOF'
  99. The default escape character is ~
  100.  
  101. Speed is everything in the emulator.  I use macros instead of functions;
  102. autoincrement wherever I can; suitably sized variables to take advantage
  103. of wraparound so I don't have to & 0xFF or & 0xFFFF.  These things are done
  104. for speed, not safety, although they should work on most machines.  Hopefully
  105. the safety_check() routine will assert fail if at least some of these
  106. assumptions are not true.
  107.  
  108. The main loop of the cpu is handled by a big switch statement.  There
  109. are no function calls since they incur a large overhead.  I count on
  110. your compiler generating an efficient jump table for the switch.
  111.  
  112. The Apple's memory is represented by a 64K array of bytes (unsigned char).
  113. All memory references, with the exception of special locataions in the
  114. C000-CFFF range, come unintercepted from the mem array.
  115.  
  116. References in the C000-CFFF range are taken from the mem_map() function.
  117. It implements things such as the keyboard read & strobe locations and
  118. the bank switching toggles.  If mem_map() doesn't have a special hook
  119. for a Cxxx location, it will return the mem[] value associated with
  120. the location.  Thus you can load device PROM images there and you will
  121. be able to reference them.
  122.  
  123. Memory stores may be caught on a per-page basis.  For example, stores to
  124. the C0xx range are caught by store_c0().  Besides the Cxxx functions,
  125. store catching routines are used for the memory mapped video from $400-7FF
  126. also for the language card.
  127.  
  128. Certain PC values are intercepted and dealt with by C routines.  The 64K
  129. array jmp_tbl[] determines whether a location is "caught"; if zero, nothing
  130. will happen.  If non-zero, the value is passed to jump().  Pc's are only
  131. intercepted on JMP and JSR instructions (so that we don't pay a speed
  132. penalty for every instruction fetch).  This imposes obvious limitations
  133. on what code can be caught.
  134.  
  135. Intercepted routines include the ROM routines to handle scrolling, the
  136. ROM wait and bell calls, and some Cxxx calls.  Scrolling must be caught
  137. and done separately or it looks horrible.  RWTS and Prodos are also
  138. caught at the block read/write level to speed up disk access.
  139.  
  140. Note that none of the jump intercepts are necessary.  They speed up
  141. scrolling and disk access (for Prodos & DOS 3.3) quite a bit, but you
  142. can turn them all off and the emulator will still run.  The memory map
  143. support is enough.
  144.  
  145. The Pc catches ignore whether the language card is active or not; instead,
  146. they look for key values to see if they routines they're supposed to sit
  147. on top of really are there.  If not, they let the real code execute.
  148. If we just caught ROM calls, and didn't catch calls that executed when
  149. the RAM card was active, then copying the ROM into the language card and
  150. switching to it would cause us to lose all of our interception.
  151.  
  152. Beware when adding intercepts for the ROM or other functions: there's
  153. always some piece of code that depends on a side effect of a function.
  154.  
  155. The blocks in the disk image are ordered in DOS 3.3 layout.  The prodos
  156. code uses a mapping table.  Thus, one Prodos block consists of two non-
  157. contiguous 256 byte blocks in a disk image.
  158.  
  159. I only have the old Disk II boot prom from $C600.  Jump.c patches it to
  160. look something like a Prodos device controller, so that Prodos has high-
  161. level disk intercept support.  I don't know if a prom image from a newer
  162. disk controller will work or not.
  163.  
  164. The emulator supports raw access to the disk controller by nibble
  165. encoding sector images as they're fed in through the shift data register.
  166. A routine decodes the motion of the disk head based on references to
  167. the stepper magnets.
  168.  
  169. @EOF
  170.  
  171. chmod 644 Notes
  172.  
  173. echo x - Snarf
  174. cat >Snarf <<'@EOF'
  175. Snarfing the ROM images
  176. -----------------------
  177.  
  178. In order to run the Apple II emulator you will need several ROM images.
  179. Since they are copyrighted they cannot be distributed with this program.
  180.  
  181.  
  182. File to put image in            Location in Apple
  183.  
  184. AUTOSTART.ROM                F800-FFFF
  185. APPLESOFT.ROM                D000-EFFF
  186. DISK.PROM                C600-C6FF    (slot 6 Disk II cont.)
  187.  
  188. MONITOR.ROM                F800-FFFF    (old Apples)
  189. INTEGER.ROM                D000-EFFF    (old Apples)
  190.  
  191.  
  192. How I snarfed the ROMs:
  193.  
  194. My Apple has an el-cheapo serial card; neither Kermit nor any of my
  195. communications programs would talk to it.  If I'd had any sort of working
  196. communications software when I set out to snarf my ROMs I probably wouldn't
  197. have done it this way; as it turns out, however, I've been very happy
  198. with this method.
  199.  
  200. I have my Apple connected to my Unix box through the serial card.  I
  201. can type IN#2 on my apple and cu into it from the Unix machine (typing
  202. PR#2 once I'm connected).
  203.  
  204. Once I'm cu'd in, it's easy to use the ROM monitor to dump stuff.  It
  205. looks something like this:
  206.  
  207.     $ cu -l /dev/tty06 -s 9600 -e | tee log
  208.     Connected
  209.     <type PR#2>
  210.     ]CALL -151
  211.  
  212.     *F800.FFFF
  213.  
  214.     F800-  00 00 00 ...
  215.     ...
  216.     *
  217.  
  218. Then when I escape back to the Unix side I have a log of the session
  219. in "log".  I use this sed command to strip off the junk and only leave
  220. the hex data:
  221.  
  222.     sed -n -e 's/^M$//' -e '/^[0-9A-F]...-/p'
  223.  
  224. In other words, put the above in a file, say 'fix', chmod +w fix, and say:
  225.  
  226.     fix < log > foo
  227.  
  228. Then I run the hex dump through a simple C program to turn it back into
  229. binary (the program is called hex.c, and should be in the directory with
  230. the emulator source):
  231.  
  232.     hex < foo > AUTOSTART.ROM
  233.  
  234. I snarf disk images in much the same way.  Here's a little DOS 3.3
  235. routine to dump an entire disk in hex:
  236.  
  237.  
  238. 0300-   A9 00       LDA   #$00        ; set up IOB
  239. 0302-   8D F0 B7    STA   $B7F0        ; BUFFL
  240. 0305-   8D EB B7    STA   $B7EB        ; VOLUME
  241. 0308-   8D EC B7    STA   $B7EC        ; TRACK
  242. 030B-   8D ED B7    STA   $B7ED        ; SECTOR
  243. 030E-   A9 10       LDA   #$10
  244. 0310-   8D F1 B7    STA   $B7F1        ; BUFFH
  245. 0313-   A9 B7       LDA   #$B7        ; IOBH
  246. 0315-   A0 E8       LDY   #$E8        ; IOBL
  247. 0317-   20 B5 B7    JSR   $B7B5        ; call RWTS
  248. 031A-   EE F1 B7    INC   $B7F1        ; next page of memory
  249. 031D-   EE ED B7    INC   $B7ED        ; next sector
  250. 0320-   AD ED B7    LDA   $B7ED
  251. 0323-   C9 10       CMP   #$10        ; end of track?
  252. 0325-   90 EC       BCC   $0313
  253. 0327-   20 3A 03    JSR   $033A        ; dump 1000-1FFF in hex
  254. 032A-   A9 00       LDA   #$00        ; Start at sector 0 again
  255. 032C-   8D ED B7    STA   $B7ED
  256. 032F-   EE EC B7    INC   $B7EC        ; next track
  257. 0332-   AD EC B7    LDA   $B7EC
  258. 0335-   C9 23       CMP   #$23        ; last track on disk?
  259. 0337-   90 D5       BCC   $030E
  260. 0339-   60          RTS   
  261. 033A-   A9 00       LDA   #$00
  262. 033C-   85 3C       STA   $3C
  263. 033E-   A9 FF       LDA   #$FF        ; range 1000-1FFF
  264. 0340-   85 3E       STA   $3E
  265. 0342-   A9 10       LDA   #$10
  266. 0344-   85 3D       STA   $3D
  267. 0346-   A9 1F       LDA   #$1F
  268. 0348-   85 3F       STA   $3F
  269. 034A-   20 B3 FD    JSR   $FDB3        ; dump hex region
  270. 034D-   60          RTS   
  271.  
  272. Run fix and hex on the log, and you can put together binary disk images
  273. for the emulator.  I've converted about 45 of my disks this way.
  274.  
  275. Since the emulator expects disk images to be in DOS 3.3 sector ordering,
  276. if you use another tool to snarf disk you may need to convert them.
  277. The program mapper.c converts from Prodos sector ordered disks into
  278. DOS 3.3 sector ordered images:
  279.  
  280.     mapper < foo > bar
  281.  
  282. @EOF
  283.  
  284. chmod 644 Snarf
  285.  
  286. echo x - Cli.doc
  287. cat >Cli.doc <<'@EOF'
  288.  
  289. CLI Basics
  290. ----------
  291. The ~ key (default value) will break the emulation and put the User into 
  292. the Command Language Interpreter (CLI). The CLI prompt is >>> .  The 
  293. user may type ? to see a list of available commands in the CLI. The CLI 
  294. allows partial completion of commands.  The partial command name must 
  295. be unambiguous.  For instance, "e" or "exam" may be 
  296. substituted for "examine".
  297.  
  298. General Commands
  299. ----------------
  300.  
  301. cd [path]    - With no paramters, displays current working directory (CWD).
  302.           Otherwise attempts to set the CWD to path.
  303.  
  304. continue or c    - Resume the emulation and refresh the screen.
  305.  
  306. escape [char]    - Make the character which breaks the emulator into char or
  307.           display current escape char.
  308.  
  309. dup l|p        
  310. pop l|p    
  311. push l|p|addr
  312.         - The CLI maintains a value stack for the convenience of 
  313.            the user.  The emulator doesnt use the stack at all.
  314.           Values may be pushed on the stack with push and
  315.           retrieved later with pop or dup.  The l and p parameters
  316.           are used to retrive/store values into the lpoint (list
  317.           point) and pc.
  318.  
  319. help        - Gives a quick list of commands
  320.  
  321. map        - Toggle lower to uppercase mapping during emulation.  The
  322.           default is to perform mapping.
  323.  
  324. quit         - Exit the Emulator
  325.  
  326. .            - Display the current point
  327.  
  328. ![command]    - Unix Shell escape.  Without command, the shell is called.
  329.            Otherwise, command is executed.
  330.  
  331. File Commands
  332. -------------
  333.  
  334. bload file addr
  335.       -  Bload will Allow the loading of binary images into the memory of
  336.          the emulator.  bload binfile F000  will load file "binfile" at
  337.      address F000.
  338.  
  339. bsave file addr1 size
  340.        - Bsave will save a section of memory to a file.  For instance,
  341.        bsave mybin 300 FF  will save all of the memory from 300 to 3FF
  342.      to file "mybin".
  343.  
  344. disk
  345.        - Display the names of the disks which are currently inserted in
  346.      the virtual disk drives.
  347.  
  348. insert file [drive#]
  349.        - Insert will make a file the disk in a particular drive. For 
  350.          Instance: insert mydisk  will make the file "mydisk" appear
  351.        to the emulator as the disk in drive 1.
  352.  
  353. Register Manipulation
  354. ---------------------
  355.  
  356. cl[cdinvz] - Clears Status register bit.  For instance, clc will clear
  357.          the carry bit.  clz will clear the zero bit.
  358.  
  359. se[cdinvz] - Set Status register bit.  For instance, sec will set the
  360.          carry flag.  sez will set the zero bit.
  361.  
  362. ld[axys] value 
  363.        - Load a value into a register.  lda ff will load ff into
  364.          the accumulator.  lds 02 will load 02 into the Stack Pointer.
  365.  
  366. jmp addr
  367.        - Sets PC = addr.  A continue will resume at that location.
  368.  
  369. reset or ~
  370.        - Sets PC = addr in the Apple II reset Vector.  Combined
  371.          with continue, will emulate the pressing of the reset
  372.          button on the Apple II.
  373.  
  374. Memory Manipulation/Examination
  375. -------------------------------
  376.  
  377. examine addr [addr]
  378.        - Display current memory location if no paramters are givin.
  379.          If one parameter is givin, the contents of that location are
  380.          displayed.  If two parameters are givin, all memory between
  381.          the two locations is displayed. examine 300 400 will display
  382.          all memory between $300 and $400. e 300 will display the
  383.          8 bit contents of $300
  384.  
  385. deposit addr value [value]+
  386.        - Put values into memory.  Addr must be specified as well as
  387.          one or more values.  Deposit 300 20  will put 20 into memory
  388.          location 300.  Deposit 300 10 20 30 40 will load 10,20,30,40
  389.          into consequtive addresses beginning at 300.
  390.  
  391. list [low] [high]
  392.        - Dissassembly.  If noparameters are supplied, dissassembly
  393.          begins at the current point and continues for 1 page. If
  394.          low is specified, dissassembly begins at low and continues
  395.          for 1 page.  If both low and high are specified the region
  396.          between low and high is dissassembled.
  397.  
  398. Debugging Commands
  399. ------------------
  400.  
  401. breakpoint [addr]
  402.        - Set breakpoint.  If addr is not specified, the current
  403.          breakpoint is displayed.  Otherwise, the breakpoint is set
  404.          to addr.  When PC == addr, the emulator breaks into the
  405.          command mode.  break 3FFF   sets the breakpoint to 3FFF.
  406.  
  407. nobreak       - Turn of breakpoint.
  408.  
  409. trace [low high] [file]
  410.        - Enable tracing.  With no parameters, the current trace status
  411.          is displayed.  When low and high are givin, tracing for that
  412.          region is enabled (i.e. when low <= pc <= high ).  An output
  413.          consisting of dissassembly and status registers is written to
  414.          the trace file.  If file is specified, output is sent to that
  415.          file, otherwise the file "trace" is used. For instance,
  416.          trace 3F0 400  will trace the region of 3F0-400 and send its
  417.          output to trace.
  418.  
  419. notrace       - Disable tracing.
  420.  
  421. phantom location high low [file]
  422.        - Enable phantom tracing of range low,high.  Phantom tracing
  423.          allows a trace to be performed AFTER location is reached.
  424.          For instance, phantom 300 F300 F400 will enable tracing of
  425.          f300-f400 only AFTER PC == 300. Once the PC has reached 300,
  426.          tracing between F300-F400 is enabled.  If file is specified
  427.          trace output will go to the specified file.  Otherwise, "trace"
  428.          is assumed.
  429. nophantom
  430.        - disable phantom trace.
  431.  
  432. @EOF
  433.  
  434. chmod 600 Cli.doc
  435.  
  436. echo x - a2.c
  437. cat >a2.c <<'@EOF'
  438. /*
  439.  *  a2, an Apple II emulator in C
  440.  *  (c) Copyright 1990 by Rich Skrenta
  441.  *
  442.  *  Command line interface written by Tom Markson
  443.  *
  444.  *  Distribution agreement:
  445.  *
  446.  *    You may freely copy or redistribute this software, so long
  447.  *    as there is no profit made from its use, sale, trade or
  448.  *    reproduction.  You may not change this copyright notice,
  449.  *    and it must be included prominently in any copy made.
  450.  *
  451.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  452.  *                    skrenta@blekko.uucp
  453.  */
  454.  
  455.  
  456. #include    <stdio.h>
  457. #include    "a2.h"
  458.  
  459. #define    BRANCH()    val = mem[Pc++]; if (val & 0x80) Pc += val - 256; else Pc += val;
  460.  
  461. #define    put_status(s) stmp = s; N = stmp & 0x80; V = stmp & 0x40; B = stmp & 0x10; D = stmp & 0x08; I = stmp & 0x04; NZ = !(stmp & 0x02); C = stmp & 0x01;
  462.  
  463.  
  464. extern long trace_lo, trace_hi;
  465. extern FILE *logging_fp;
  466. extern long phantom_location;
  467. extern long breakpoint;
  468.  
  469.  
  470.  
  471. run()
  472. {
  473. register unsigned short ptr;
  474. register unsigned short ptmp;
  475. register unsigned int val;
  476. register unsigned int tmp;
  477. register unsigned int num;
  478. unsigned char stmp;
  479. int foo;
  480. int show_flags = FALSE;
  481.  
  482.  
  483.     do {                    /* while (tracing) */
  484.     if (tracing) {
  485.  
  486.         if (breakpoint == Pc) {
  487.             MoveCursor(term_lines, 0);
  488.             printf("Break at $%.4X\n", Pc);
  489.             return;
  490.         }
  491.  
  492.         if (phantom_location == (long) Pc)
  493.             phantom_location = -1;        /* start tracing now */
  494.  
  495.         if (phantom_location == -1
  496.         &&  trace_lo != -1
  497.         &&  (long) Pc >= trace_lo
  498.         &&  (long) Pc <= trace_hi) {
  499.             diss(Pc, logging_fp);
  500.             show_flags = TRUE;
  501.         } else
  502.             show_flags = FALSE;
  503.     }
  504.  
  505.  
  506.     do {                    /* while (running) */
  507.         switch (mem[Pc++]) {
  508.         case 0x00:            /* BRK */
  509.             PCINC;
  510.             push(high(Pc));
  511.             push(low(Pc));
  512.             B = 1;                /* set I flag? */
  513.             push(get_status());
  514.             Pc = join(mem[0xFFFE], mem[0xFFFF]);
  515.             break;
  516.  
  517.         case 0x01:    /* ORA (indirect, X) */
  518.             INDX;
  519.             A |= REFptr;
  520.             SIGN(A);
  521.             ZERO(A);
  522.             break;
  523.  
  524.         case 0x02:
  525.             break;
  526.  
  527.         case 0x03:
  528.             break;
  529.  
  530.         case 0x04:    /* TSB zero page    65C02 */
  531.             break;
  532.  
  533.         case 0x05:    /* ORA zero page */
  534.             A |= rZEROP;
  535.             SIGN(A);
  536.             ZERO(A);
  537.             break;
  538.  
  539.         case 0x06:    /* ASL zero page */
  540.             ZEROP;
  541.             val = REFzero << 1;
  542.             CARRY(val);
  543.             val &= 0xFF;
  544.             SETzero(val);
  545.             SIGN(val);
  546.             ZERO(val);
  547.             break;
  548.  
  549.         case 0x07:
  550.             break;
  551.  
  552.         case 0x08:    /* PHP */
  553.             push(get_status());
  554.             break;
  555.  
  556.         case 0x09:    /* ORA immediate */
  557.             A |= REFimm;
  558.             SIGN(A);
  559.             ZERO(A);
  560.             break;
  561.  
  562.         case 0x0A:    /* ASL accumulator */
  563.             A = A << 1;
  564.             CARRY(A);
  565.             A &= 0xFF;
  566.             SIGN(A);
  567.             ZERO(A);
  568.             break;
  569.  
  570.         case 0x0B:
  571.             break;
  572.  
  573.         case 0x0C:    /* TSB absolute        65C02 */
  574.             break;
  575.  
  576.         case 0x0D:    /* ORA absolute */
  577.             ABSOL;
  578.             A |= REFptr;
  579.             SIGN(A);
  580.             ZERO(A);
  581.             break;
  582.  
  583.         case 0x0E:    /* ASL absolute */
  584.             ABSOL;
  585.             val = REFptr << 1;
  586.             CARRY(val);
  587.             val &= 0xFF;
  588.             SETptr(val);
  589.             SIGN(val);
  590.             ZERO(val);
  591.             break;
  592.  
  593.         case 0x0F:
  594.             break;
  595.  
  596.         case 0x10:    /* BPL */
  597.             if (N) {
  598.                 PCINC;
  599.             } else {
  600.                 BRANCH();
  601.             }
  602.             break;
  603.  
  604.         case 0x11:    /* ORA (indirect), Y */
  605.             INDY;
  606.             A |= REFptr;
  607.             SIGN(A);
  608.             ZERO(A);
  609.             break;
  610.  
  611.         case 0x12:    /* ORA (indz)        65C02 */
  612.             break;
  613.  
  614.         case 0x13:
  615.             break;
  616.  
  617.         case 0x14:    /* TRB zero page    65C02 */
  618.             break;
  619.  
  620.         case 0x15:    /* ORA zero page, X */
  621.             A |= rZEROX;
  622.             SIGN(A);
  623.             ZERO(A);
  624.             break;
  625.  
  626.         case 0x16:    /* ASL zero page, X */
  627.             ZEROX;
  628.             val = REFzero << 1;
  629.             CARRY(val);
  630.             val &= 0xFF;
  631.             SETzero(val);
  632.             SIGN(val);
  633.             ZERO(val);
  634.             break;
  635.  
  636.         case 0x17:
  637.             break;
  638.  
  639.         case 0x18:    /* CLC */
  640.             C = 0;
  641.             break;
  642.  
  643.         case 0x19:    /* ORA absolute, Y */
  644.             ABSY;
  645.             A |= REFptr;
  646.             SIGN(A);
  647.             ZERO(A);
  648.             break;
  649.  
  650.         case 0x1A:    /* INA            65C02 */
  651.             break;
  652.  
  653.         case 0x1C:    /* TRB absolute        65C02 */
  654.             break;
  655.  
  656.         case 0x1D:    /* ORA absolute, X */
  657.             ABSX;
  658.             A |= REFptr;
  659.             SIGN(A);
  660.             ZERO(A);
  661.             break;
  662.  
  663.         case 0x1E:    /* ASL absolute, X */
  664.             ABSX;
  665.             val = REFptr << 1;
  666.             CARRY(val);
  667.             val &= 0xFF;
  668.             SETptr(val);
  669.             SIGN(val);
  670.             ZERO(val);
  671.             break;
  672.  
  673.         case 0x1F:
  674.             break;
  675.  
  676.         case 0x20:    /* JSR */
  677.             ptmp = REFimm;
  678.             ptmp |= mem[Pc] << 8;
  679.             push(high(Pc));
  680.             push(low(Pc));
  681.             Pc = ptmp;
  682.  
  683.             if (jmp_tbl[Pc])
  684.                 jump(jmp_tbl[Pc]);
  685.             break;
  686.  
  687.         case 0x21:    /* AND (indirect, X) */
  688.             INDX;
  689.             A &= REFptr;
  690.             SIGN(A);
  691.             ZERO(A);
  692.             break;
  693.  
  694.         case 0x22:
  695.             break;
  696.  
  697.         case 0x23:
  698.             break;
  699.  
  700.         case 0x24:    /* BIT zero page */
  701.             tmp = rZEROP;
  702.             ZERO(A & tmp);
  703.             N = tmp & 0x80;
  704.             V = tmp & 0x40;
  705.             break;
  706.  
  707.         case 0x25:    /* AND zero page */
  708.             A &= rZEROP;
  709.             SIGN(A);
  710.             ZERO(A);
  711.             break;
  712.  
  713.         case 0x26:    /* ROL zero page */
  714.             ZEROP;
  715.             val = REFzero;
  716.             tmp = C;
  717.             val = val << 1;
  718.             CARRY(val);
  719.             val = (val & 0xFF) | tmp;
  720.             SETzero(val);
  721.             SIGN(val);
  722.             ZERO(val);
  723.             break;
  724.  
  725.         case 0x27:
  726.             break;
  727.  
  728.         case 0x28:    /* PLP */
  729.             put_status(pop());
  730.             break;
  731.  
  732.         case 0x29:    /* AND immediate */
  733.             A &= REFimm;
  734.             SIGN(A);
  735.             ZERO(A);
  736.             break;
  737.  
  738.         case 0x2A:    /* ROL accumulator */
  739.             tmp = C;
  740.             A = A << 1;
  741.             CARRY(A);
  742.             A = (A & 0xFF) | tmp;
  743.             SIGN(A);
  744.             ZERO(A);
  745.             break;
  746.  
  747.         case 0x2B:
  748.             break;
  749.  
  750.         case 0x2C:    /* BIT absolute */
  751.             ABSOL;
  752.             tmp = REFptr;
  753.             ZERO(A & tmp);
  754.             N = tmp & 0x80;
  755.             V = tmp & 0x40;
  756.             break;
  757.  
  758.         case 0x2D:    /* AND absolute */
  759.             ABSOL;
  760.             A &= REFptr;
  761.             SIGN(A);
  762.             ZERO(A);
  763.             break;
  764.  
  765.         case 0x2E:    /* ROL absolute */
  766.             ABSOL;
  767.             val = REFptr;
  768.             tmp = C;
  769.             val = val << 1;
  770.             CARRY(val);
  771.             val = (val & 0xFF) | tmp;
  772.             SETptr(val);
  773.             SIGN(val);
  774.             ZERO(val);
  775.             break;
  776.  
  777.         case 0x2F:
  778.             break;
  779.  
  780.         case 0x30:    /* BMI */
  781.             if (N) {
  782.                 BRANCH();
  783.             } else{
  784.                 PCINC;
  785.             }
  786.             break;
  787.  
  788.         case 0x31:    /* AND (indirect), Y */
  789.             INDY;
  790.             A &= REFptr;
  791.             SIGN(A);
  792.             ZERO(A);
  793.             break;
  794.  
  795.         case 0x32:    /* AND (indz)        65C02 */
  796.             break;
  797.  
  798.         case 0x33:
  799.             break;
  800.  
  801.         case 0x34:    /* BIT zero page, X    65C02 */
  802.             break;
  803.  
  804.         case 0x35:    /* AND zero page, X */
  805.             A &= rZEROX;
  806.             SIGN(A);
  807.             ZERO(A);
  808.             break;
  809.  
  810.         case 0x36:    /* ROL zero page, X */
  811.             ZEROX;
  812.             val = REFzero;
  813.             tmp = C;
  814.             val = val << 1;
  815.             CARRY(val);
  816.             val = (val & 0xFF) | tmp;
  817.             SETzero(val);
  818.             SIGN(val);
  819.             ZERO(val);
  820.             break;
  821.  
  822.         case 0x37:
  823.             break;
  824.  
  825.         case 0x38:    /* SEC */
  826.             C = 1;
  827.             break;
  828.  
  829.         case 0x39:    /* AND absolute, Y */
  830.             ABSY;
  831.             A &= REFptr;
  832.             SIGN(A);
  833.             ZERO(A);
  834.             break;
  835.  
  836.         case 0x3A:    /* DEA            65C02 */
  837.             break;
  838.  
  839.         case 0x3B:
  840.             break;
  841.  
  842.         case 0x3C:    /* BIT absolute, X    65C02 */
  843.             break;
  844.  
  845.         case 0x3D:    /* AND absolute, X */
  846.             ABSX;
  847.             A &= REFptr;
  848.             SIGN(A);
  849.             ZERO(A);
  850.             break;
  851.  
  852.         case 0x3E:    /* ROL absolute, X */
  853.             ABSX;
  854.             val = REFptr;
  855.             tmp = C;
  856.             val = val << 1;
  857.             CARRY(val);
  858.             val = (val & 0xFF) | tmp;
  859.             SETptr(val);
  860.             SIGN(val);
  861.             ZERO(val);
  862.             break;
  863.  
  864.         case 0x3F:
  865.             break;
  866.  
  867.         case 0x40:    /* RTI */
  868.             put_status(pop());
  869.             Pc = pop();
  870.             Pc |= pop() << 8;
  871.             break;
  872.  
  873.         case 0x41:    /* EOR (indirect, X) */
  874.             INDX;
  875.             A ^= REFptr;
  876.             SIGN(A);
  877.             ZERO(A);
  878.             break;
  879.  
  880.         case 0x42:
  881.             break;
  882.  
  883.         case 0x43:
  884.             break;
  885.  
  886.         case 0x44:
  887.             break;
  888.  
  889.         case 0x45:    /* EOR zero page */
  890.             A ^= rZEROP;
  891.             SIGN(A);
  892.             ZERO(A);
  893.             break;
  894.  
  895.         case 0x46:    /* LSR zero page */
  896.             ZEROP;
  897.             tmp = REFzero;
  898.             C = (tmp & 0x01);
  899.             tmp = tmp >> 1;
  900.             SETzero(tmp);
  901.             N = 0;
  902.             ZERO(tmp);
  903.             break;
  904.  
  905.         case 0x47:
  906.             break;
  907.  
  908.         case 0x48:    /* PHA */
  909.             push(A);
  910.             break;
  911.  
  912.         case 0x49:    /* EOR immediate */
  913.             A ^= REFimm;
  914.             SIGN(A);
  915.             ZERO(A);
  916.             break;
  917.  
  918.         case 0x4A:    /* LSR accumulator */
  919.             C = (A & 0x01);
  920.             A = A >> 1;
  921.             N = 0;
  922.             ZERO(A);
  923.             break;
  924.  
  925.         case 0x4B:
  926.             break;
  927.  
  928.         case 0x4C:    /* JMP absolute */
  929.             ptmp = REFimm;
  930.             ptmp |= REFimm << 8;
  931.             Pc = ptmp;
  932.  
  933.             if (jmp_tbl[Pc])
  934.                 jump(jmp_tbl[Pc]);
  935.             break;
  936.  
  937.         case 0x4D:    /* EOR absolute */
  938.             ABSOL;
  939.             A ^= REFptr;
  940.             SIGN(A);
  941.             ZERO(A);
  942.             break;
  943.  
  944.         case 0x4E:    /* LSR absolute */
  945.             ABSOL;
  946.             tmp = REFptr;
  947.             C = (tmp & 0x01);
  948.             tmp = tmp >> 1;
  949.             SETptr(tmp);
  950.             N = 0;
  951.             ZERO(tmp);
  952.             break;
  953.  
  954.         case 0x4F:
  955.             break;
  956.  
  957.         case 0x50:    /* BVC */
  958.             if (V) {
  959.                 PCINC;
  960.             } else {
  961.                 BRANCH();
  962.             }
  963.             break;
  964.  
  965.         case 0x51:    /* EOR (indirect), Y */
  966.             INDY;
  967.             A ^= REFptr;
  968.             SIGN(A);
  969.             ZERO(A);
  970.             break;
  971.  
  972.         case 0x52:    /* EOR (indz)        65C02 */
  973.             break;
  974.  
  975.         case 0x53:
  976.             break;
  977.  
  978.         case 0x54:
  979.             break;
  980.  
  981.         case 0x55:    /* EOR zero page, X */
  982.             A ^= rZEROX;
  983.             SIGN(A);
  984.             ZERO(A);
  985.             break;
  986.  
  987.         case 0x56:    /* LSR zero page, X */
  988.             ZEROX;
  989.             tmp = REFzero;
  990.             C = (tmp & 0x01);
  991.             tmp = tmp >> 1;
  992.             SETzero(tmp);
  993.             N = 0;
  994.             ZERO(tmp);
  995.             break;
  996.  
  997.         case 0x57:
  998.             break;
  999.  
  1000.         case 0x58:    /* CLI */
  1001.             I = 0;
  1002.             break;
  1003.  
  1004.         case 0x59:    /* EOR absolute, Y */
  1005.             ABSY;
  1006.             A ^= REFptr;
  1007.             SIGN(A);
  1008.             ZERO(A);
  1009.             break;
  1010.  
  1011.         case 0x5A:    /* PHY        65C02 */
  1012.             break;
  1013.  
  1014.         case 0x5B:
  1015.             break;
  1016.  
  1017.         case 0x5C:
  1018.             break;
  1019.  
  1020.         case 0x5D:    /* EOR absolute, X */
  1021.             ABSX;
  1022.             A ^= REFptr;
  1023.             SIGN(A);
  1024.             ZERO(A);
  1025.             break;
  1026.  
  1027.         case 0x5E:    /* LSR absolute, X */
  1028.             ABSX;
  1029.             tmp = REFptr;
  1030.             C = (tmp & 0x01);
  1031.             tmp = tmp >> 1;
  1032.             SETptr(tmp);
  1033.             N = 0;
  1034.             ZERO(tmp);
  1035.             break;
  1036.  
  1037.         case 0x5F:
  1038.             break;
  1039.  
  1040.         case 0x60:    /* RTS */
  1041.             DO_RTS;
  1042.             break;
  1043.  
  1044.         case 0x61:    /* ADC (indirect, X) */
  1045.             INDX;
  1046.             val = REFptr;
  1047.             tmp = A & 0x80;
  1048.             stmp = val & 0x80;
  1049.             if (D) {
  1050.                 num = tobinary(val);
  1051.                 val = tobinary(A);
  1052.  
  1053.                 val += num + C;
  1054.                 dCARRY(val);
  1055.                 while (val >= 100)
  1056.                     val -= 100;
  1057.  
  1058.                 A = tobcd(val);
  1059.             } else {
  1060.                 A += val + C;
  1061.                 CARRY(A);
  1062.                 A &= 0xFF;
  1063.             }
  1064.             ZERO(A);
  1065.             SIGN(A);
  1066.             V = (tmp == stmp) && (tmp != N);
  1067.             break;
  1068.  
  1069.         case 0x62:
  1070.             break;
  1071.  
  1072.         case 0x63:
  1073.             break;
  1074.  
  1075.         case 0x64:    /* STZ zero page    65C02 */
  1076.             break;
  1077.  
  1078.         case 0x65:    /* ADC zero page */
  1079.             val = rZEROP;
  1080.             tmp = A & 0x80;
  1081.             stmp = val & 0x80;
  1082.             if (D) {
  1083.                 num = tobinary(val);
  1084.                 val = tobinary(A);
  1085.  
  1086.                 val += num + C;
  1087.                 dCARRY(val);
  1088.                 while (val >= 100)
  1089.                     val -= 100;
  1090.  
  1091.                 A = tobcd(val);
  1092.             } else {
  1093.                 A += val + C;
  1094.                 CARRY(A);
  1095.                 A &= 0xFF;
  1096.             }
  1097.             ZERO(A);
  1098.             SIGN(A);
  1099.             V = (tmp == stmp) && (tmp != N);
  1100.             break;
  1101.  
  1102.  
  1103.         case 0x66:    /* ROR zero page */
  1104.             ZEROP;
  1105.             val = REFzero;
  1106.             tmp = C;
  1107.             C = val & 0x01;
  1108.             val = val >> 1;
  1109.             val |= tmp << 7;
  1110.             SETzero(val);
  1111.             SIGN(val);
  1112.             ZERO(val);
  1113.             break;
  1114.  
  1115.         case 0x67:
  1116.             break;
  1117.  
  1118.         case 0x68:    /* PLA */
  1119.             A = pop();
  1120.             SIGN(A);
  1121.             ZERO(A);
  1122.             break;
  1123.  
  1124.         case 0x69:    /* ADC immediate */
  1125.             val = REFimm;
  1126.             tmp = A & 0x80;
  1127.             stmp = val & 0x80;
  1128.             if (D) {
  1129.                 num = tobinary(val);
  1130.                 val = tobinary(A);
  1131.  
  1132.                 val += num + C;
  1133.                 dCARRY(val);
  1134.                 while (val >= 100)
  1135.                     val -= 100;
  1136.  
  1137.                 A = tobcd(val);
  1138.             } else {
  1139.                 A += val + C;
  1140.                 CARRY(A);
  1141.                 A &= 0xFF;
  1142.             }
  1143.             ZERO(A);
  1144.             SIGN(A);
  1145.             V = (tmp == stmp) && (tmp != N);
  1146.             break;
  1147.  
  1148.         case 0x6A:    /* ROR accumulator */
  1149.             tmp = C;
  1150.             C = A & 0x01;
  1151.             A = A >> 1;
  1152.             A |= tmp << 7;
  1153.             SIGN(A);
  1154.             ZERO(A);
  1155.             break;
  1156.  
  1157.         case 0x6B:
  1158.             break;
  1159.  
  1160.         case 0x6C:    /* JMP indirect */
  1161.             ptmp = REFimm;
  1162.             ptmp |= REFimm << 8;
  1163.             Pc = mem[ptmp++];
  1164.             Pc |= mem[ptmp] << 8;
  1165.  
  1166.             if (jmp_tbl[Pc])
  1167.                 jump(jmp_tbl[Pc]);
  1168.             break;
  1169.  
  1170.         case 0x6D:    /* ADC absolute */
  1171.             ABSOL;
  1172.             val = REFptr;
  1173.             tmp = A & 0x80;
  1174.             stmp = val & 0x80;
  1175.             if (D) {
  1176.                 num = tobinary(val);
  1177.                 val = tobinary(A);
  1178.  
  1179.                 val += num + C;
  1180.                 dCARRY(val);
  1181.                 while (val >= 100)
  1182.                     val -= 100;
  1183.  
  1184.                 A = tobcd(val);
  1185.             } else {
  1186.                 A += val + C;
  1187.                 CARRY(A);
  1188.                 A &= 0xFF;
  1189.             }
  1190.             ZERO(A);
  1191.             SIGN(A);
  1192.             V = (tmp == stmp) && (tmp != N);
  1193.             break;
  1194.  
  1195.         case 0x6E:    /* ROR absolute */
  1196.             ABSOL;
  1197.             val = REFptr;
  1198.             tmp = C;
  1199.             C = val & 0x01;
  1200.             val = val >> 1;
  1201.             val |= tmp << 7;
  1202.             SETptr(val);
  1203.             SIGN(val);
  1204.             ZERO(val);
  1205.             break;
  1206.  
  1207.         case 0x6F:
  1208.             break;
  1209.  
  1210.         case 0x70:    /* BVS */
  1211.             if (V) {
  1212.                 BRANCH();
  1213.             } else {
  1214.                 PCINC;
  1215.             }
  1216.             break;
  1217.  
  1218.         case 0x71:    /* ADC (indirect),Y */
  1219.             INDY;
  1220.             val = REFptr;
  1221.             tmp = A & 0x80;
  1222.             stmp = val & 0x80;
  1223.             if (D) {
  1224.                 num = tobinary(val);
  1225.                 val = tobinary(A);
  1226.  
  1227.                 val += num + C;
  1228.                 dCARRY(val);
  1229.                 while (val >= 100)
  1230.                     val -= 100;
  1231.  
  1232.                 A = tobcd(val);
  1233.             } else {
  1234.                 A += val + C;
  1235.                 CARRY(A);
  1236.                 A &= 0xFF;
  1237.             }
  1238.             ZERO(A);
  1239.             SIGN(A);
  1240.             V = (tmp == stmp) && (tmp != N);
  1241.             break;
  1242.  
  1243.         case 0x72:    /* ADC (indz)        65C02 */
  1244.             break;
  1245.  
  1246.         case 0x73:
  1247.             break;
  1248.  
  1249.         case 0x74:    /* STZ zero page, X    65C02 */
  1250.             break;
  1251.  
  1252.         case 0x75:    /* ADC zero page, X */
  1253.             val = rZEROX;
  1254.             tmp = A & 0x80;
  1255.             stmp = val & 0x80;
  1256.             if (D) {
  1257.                 num = tobinary(val);
  1258.                 val = tobinary(A);
  1259.  
  1260.                 val += num + C;
  1261.                 dCARRY(val);
  1262.                 while (val >= 100)
  1263.                     val -= 100;
  1264.  
  1265.                 A = tobcd(val);
  1266.             } else {
  1267.                 A += val + C;
  1268.                 CARRY(A);
  1269.                 A &= 0xFF;
  1270.             }
  1271.             ZERO(A);
  1272.             SIGN(A);
  1273.             V = (tmp == stmp) && (tmp != N);
  1274.             break;
  1275.  
  1276.         case 0x76:    /* ROR zero page, X */
  1277.             ZEROX;
  1278.             val = REFzero;
  1279.             tmp = C;
  1280.             C = val & 0x01;
  1281.             val = val >> 1;
  1282.             val |= tmp << 7;
  1283.             SETzero(val);
  1284.             SIGN(val);
  1285.             ZERO(val);
  1286.             break;
  1287.  
  1288.         case 0x77:
  1289.             break;
  1290.  
  1291.         case 0x78:    /* SEI */
  1292.             I = 1;
  1293.             break;
  1294.  
  1295.         case 0x79:    /* ADC absolute, Y */
  1296.             ABSY;
  1297.             val = REFptr;
  1298.             tmp = A & 0x80;
  1299.             stmp = val & 0x80;
  1300.             if (D) {
  1301.                 num = tobinary(val);
  1302.                 val = tobinary(A);
  1303.  
  1304.                 val += num + C;
  1305.                 dCARRY(val);
  1306.                 while (val >= 100)
  1307.                     val -= 100;
  1308.  
  1309.                 A = tobcd(val);
  1310.             } else {
  1311.                 A += val + C;
  1312.                 CARRY(A);
  1313.                 A &= 0xFF;
  1314.             }
  1315.             ZERO(A);
  1316.             SIGN(A);
  1317.             V = (tmp == stmp) && (tmp != N);
  1318.             break;
  1319.  
  1320.         case 0x7A:    /* PLY        65C02 */
  1321.             break;
  1322.  
  1323.         case 0x7B:
  1324.             break;
  1325.  
  1326.         case 0x7C:    /* JMP (abs indirect, X)    65C02 */
  1327.             break;
  1328.  
  1329.         case 0x7D:    /* ADC absolute, X */
  1330.             ABSX;
  1331.             val = REFptr;
  1332.             tmp = A & 0x80;
  1333.             stmp = val & 0x80;
  1334.             if (D) {
  1335.                 num = tobinary(val);
  1336.                 val = tobinary(A);
  1337.  
  1338.                 val += num + C;
  1339.                 dCARRY(val);
  1340.                 while (val >= 100)
  1341.                     val -= 100;
  1342.  
  1343.                 A = tobcd(val);
  1344.             } else {
  1345.                 A += val + C;
  1346.                 CARRY(A);
  1347.                 A &= 0xFF;
  1348.             }
  1349.             ZERO(A);
  1350.             SIGN(A);
  1351.             V = (tmp == stmp) && (tmp != N);
  1352.             break;
  1353.  
  1354.         case 0x7E:    /* ROR absolute, X */
  1355.             ABSX;
  1356.             val = REFptr;
  1357.             tmp = C;
  1358.             C = val & 0x01;
  1359.             val = val >> 1;
  1360.             val |= tmp << 7;
  1361.             SETptr(val);
  1362.             SIGN(val);
  1363.             ZERO(val);
  1364.             break;
  1365.  
  1366.         case 0x7F:
  1367.             break;
  1368.  
  1369.         case 0x80:    /* BRA            65C02 */
  1370.             break;
  1371.  
  1372.         case 0x81:    /* STA (indirect, X) */
  1373.             INDX;
  1374.             SETptr(A);
  1375.             break;
  1376.  
  1377.         case 0x82:
  1378.             break;
  1379.  
  1380.         case 0x83:
  1381.             break;
  1382.  
  1383.         case 0x84:    /* STY zero page */
  1384.             sZEROP(Y);
  1385.             break;
  1386.  
  1387.         case 0x85:    /* STA zero page */
  1388.             sZEROP(A);
  1389.             break;
  1390.  
  1391.         case 0x86:    /* STX zero page */
  1392.             sZEROP(X);
  1393.             break;
  1394.  
  1395.         case 0x87:
  1396.             break;
  1397.  
  1398.         case 0x88:    /* DEY */
  1399.             Y--;
  1400.             SIGN(Y);
  1401.             ZERO(Y);
  1402.             break;
  1403.  
  1404.         case 0x89:
  1405.             break;
  1406.  
  1407.         case 0x8A:    /* TXA */
  1408.             A = X;
  1409.             SIGN(A);
  1410.             ZERO(A);
  1411.             break;
  1412.  
  1413.         case 0x8B:
  1414.             break;
  1415.  
  1416.         case 0x8C:    /* STY absolute */
  1417.             ABSOL;
  1418.             SETptr(Y);
  1419.             break;
  1420.  
  1421.         case 0x8D:    /* STA absolute */
  1422.             ABSOL;
  1423.             SETptr(A);
  1424.             break;
  1425.  
  1426.         case 0x8E:    /* STX absolute */
  1427.             ABSOL;
  1428.             SETptr(X);
  1429.             break;
  1430.  
  1431.         case 0x8F:
  1432.             break;
  1433.  
  1434.         case 0x90:    /* BCC */
  1435.             if (C) {
  1436.                 PCINC;
  1437.             } else {
  1438.                 BRANCH();
  1439.             }
  1440.             break;
  1441.  
  1442.         case 0x91:    /* STA (indirect), Y */
  1443.             INDY;
  1444.             SETptr(A);
  1445.             break;
  1446.  
  1447.         case 0x92:
  1448.             break;
  1449.  
  1450.         case 0x93:
  1451.             break;
  1452.  
  1453.         case 0x94:    /* STY zero page, X */
  1454.             sZEROX(Y);
  1455.             break;
  1456.  
  1457.         case 0x95:    /* STA zero page, X */
  1458.             sZEROX(A);
  1459.             break;
  1460.  
  1461.         case 0x96:    /* STX zero page, Y */
  1462.             sZEROY(X);
  1463.             break;
  1464.  
  1465.         case 0x97:
  1466.             break;
  1467.  
  1468.         case 0x98:    /* TYA */
  1469.             A = Y;
  1470.             SIGN(A);
  1471.             ZERO(A);
  1472.             break;
  1473.  
  1474.         case 0x99:    /* STA absolute, Y */
  1475.             ABSY;
  1476.             SETptr(A);
  1477.             break;
  1478.  
  1479.         case 0x9A:    /* TXS */
  1480.             Sp = X;
  1481.             break;
  1482.  
  1483.         case 0x9B:
  1484.             break;
  1485.  
  1486.         case 0x9C:    /* STZ absolute        65C02 */
  1487.             break;
  1488.  
  1489.         case 0x9D:    /* STA absolute, X */
  1490.             ABSX;
  1491.             SETptr(A);
  1492.             break;
  1493.  
  1494.         case 0x9E:    /* STZ absolute, X    65C02 */
  1495.             break;
  1496.  
  1497.         case 0x9F:
  1498.             break;
  1499.  
  1500.         case 0xA0:    /* LDY immediate */
  1501.             Y = REFimm;
  1502.             SIGN(Y);
  1503.             ZERO(Y);
  1504.             break;
  1505.  
  1506.         case 0xA1:    /* LDA (indirect, X) */
  1507.             INDX;
  1508.             A = REFptr;
  1509.             SIGN(A);
  1510.             ZERO(A);
  1511.             break;
  1512.  
  1513.         case 0xA2:    /* LDX immediate */
  1514.             X = REFimm;
  1515.             SIGN(X);
  1516.             ZERO(X);
  1517.             break;
  1518.  
  1519.         case 0xA3:
  1520.             break;
  1521.  
  1522.         case 0xA4:     /* LDY zero page */
  1523.             Y = rZEROP;
  1524.             SIGN(Y);
  1525.             ZERO(Y);
  1526.             break;
  1527.  
  1528.         case 0xA5:    /* LDA zero page */
  1529.             A = rZEROP;
  1530.             SIGN(A);
  1531.             ZERO(A);
  1532.             break;
  1533.  
  1534.         case 0xA6:    /* LDX zero page */
  1535.             X = rZEROP;
  1536.             SIGN(X);
  1537.             ZERO(X);
  1538.             break;
  1539.  
  1540.         case 0xA7:
  1541.             break;
  1542.  
  1543.         case 0xA8:    /* TAY */
  1544.             Y = A;
  1545.             SIGN(Y);
  1546.             ZERO(Y);
  1547.             break;
  1548.  
  1549.         case 0xA9:    /* LDA immediate */
  1550.             A = REFimm;
  1551.             SIGN(A);
  1552.             ZERO(A);
  1553.             break;
  1554.  
  1555.         case 0xAA:    /* TAX */
  1556.             X = A;
  1557.             SIGN(X);
  1558.             ZERO(X);
  1559.             break;
  1560.  
  1561.         case 0xAB:
  1562.             break;
  1563.  
  1564.         case 0xAC:    /* LDY absolute */
  1565.             ABSOL;
  1566.             Y = REFptr;
  1567.             SIGN(Y);
  1568.             ZERO(Y);
  1569.             break;
  1570.  
  1571.         case 0xAD:    /* LDA absolute */
  1572.             ABSOL;
  1573.             A = REFptr;
  1574.             SIGN(A);
  1575.             ZERO(A);
  1576.             break;
  1577.  
  1578.         case 0xAE:    /* LDX absolute */
  1579.             ABSOL;
  1580.             X = REFptr;
  1581.             SIGN(X);
  1582.             ZERO(X);
  1583.             break;
  1584.  
  1585.         case 0xAF:
  1586.             break;
  1587.  
  1588.         case 0xB0:    /* BCS */
  1589.             if (C) {
  1590.                 BRANCH();
  1591.             } else {
  1592.                 PCINC;
  1593.             }
  1594.             break;
  1595.  
  1596.         case 0xB1:    /* LDA (indirect), Y */
  1597.             INDY;
  1598.             A = REFptr;
  1599.             SIGN(A);
  1600.             ZERO(A);
  1601.             break;
  1602.  
  1603.         case 0xB2:    /* LDA (indz)        65C02 */
  1604.             break;
  1605.  
  1606.         case 0xB3:
  1607.             break;
  1608.  
  1609.         case 0xB4:    /* LDY zero page, X */
  1610.             Y = rZEROX;
  1611.             SIGN(Y);
  1612.             ZERO(Y);
  1613.             break;
  1614.  
  1615.         case 0xB5:    /* LDA zero page, X */
  1616.             A = rZEROX;
  1617.             SIGN(A);
  1618.             ZERO(A);
  1619.             break;
  1620.  
  1621.         case 0xB6:    /* LDX zero page, Y */
  1622.             X = rZEROY;
  1623.             SIGN(X);
  1624.             ZERO(X);
  1625.             break;
  1626.  
  1627.         case 0xB7:
  1628.             break;
  1629.  
  1630.         case 0xB8:    /* CLV */
  1631.             V = 0;
  1632.             break;
  1633.  
  1634.         case 0xB9:    /* LDA absolute, Y */
  1635.             ABSY;
  1636.             A = REFptr;
  1637.             SIGN(A);
  1638.             ZERO(A);
  1639.             break;
  1640.  
  1641.         case 0xBA:    /* TSX */
  1642.             X = Sp;
  1643.             SIGN(X);
  1644.             ZERO(X);
  1645.             break;
  1646.  
  1647.         case 0xBB:
  1648.             break;
  1649.  
  1650.         case 0xBC:    /* LDY absolute, X */
  1651.             ABSX;
  1652.             Y = REFptr;
  1653.             SIGN(Y);
  1654.             ZERO(Y);
  1655.             break;
  1656.  
  1657.         case 0xBD:    /* LDA absolute, X */
  1658.             ABSX;
  1659.             A = REFptr;
  1660.             SIGN(A);
  1661.             ZERO(A);
  1662.             break;
  1663.  
  1664.         case 0xBE:    /* LDX absolute, Y */
  1665.             ABSY;
  1666.             X = REFptr;
  1667.             SIGN(X);
  1668.             ZERO(X);
  1669.             break;
  1670.  
  1671.         case 0xBF:
  1672.             break;
  1673.  
  1674.         case 0xC0:    /* CPY immediate */
  1675.             tmp = REFimm;
  1676.             C = (Y >= tmp);
  1677.             tmp = (Y - tmp) & 0xFF;
  1678.             SIGN(tmp);
  1679.             ZERO(tmp);
  1680.             break;
  1681.  
  1682.         case 0xC1:    /* CMP (indirect, X) */
  1683.             INDX;
  1684.             tmp = REFptr;
  1685.             C = (A >= tmp);
  1686.             tmp = (A - tmp) & 0xFF;
  1687.             SIGN(tmp);
  1688.             ZERO(tmp);
  1689.             break;
  1690.  
  1691.         case 0xC2:
  1692.             break;
  1693.  
  1694.         case 0xC3:
  1695.             break;
  1696.  
  1697.         case 0xC4:    /* CPY zero page */
  1698.             tmp = rZEROP;
  1699.             C = (Y >= tmp);
  1700.             tmp = (Y - tmp) & 0xFF;
  1701.             SIGN(tmp);
  1702.             ZERO(tmp);
  1703.             break;
  1704.  
  1705.         case 0xC5:    /* CMP zero page */
  1706.             tmp = rZEROP;
  1707.             C = (A >= tmp);
  1708.             tmp = (A - tmp) & 0xFF;
  1709.             SIGN(tmp);
  1710.             ZERO(tmp);
  1711.             break;
  1712.  
  1713.         case 0xC6:    /* DEC zero page */
  1714.             ZEROP;
  1715.             stmp = REFzero - 1;
  1716.             SETzero(stmp);
  1717.             SIGN(stmp);
  1718.             ZERO(stmp);
  1719.             break;
  1720.  
  1721.         case 0xC7:
  1722.             break;
  1723.  
  1724.         case 0xC8:    /* INY */
  1725.             Y++;
  1726.             SIGN(Y);
  1727.             ZERO(Y);
  1728.             break;
  1729.  
  1730.         case 0xC9:    /* CMP immediate */
  1731.             tmp = REFimm;
  1732.             C = (A >= tmp);
  1733.             tmp = (A - tmp) & 0xFF;
  1734.             SIGN(tmp);
  1735.             ZERO(tmp);
  1736.             break;
  1737.  
  1738.         case 0xCA:    /* DEX */
  1739.             X--;
  1740.             SIGN(X);
  1741.             ZERO(X);
  1742.             break;
  1743.  
  1744.         case 0xCB:
  1745.             break;
  1746.  
  1747.         case 0xCC:    /* CPY absolute */
  1748.             ABSOL;
  1749.             tmp = REFptr;
  1750.             C = (Y >= tmp);
  1751.             tmp = (Y - tmp) & 0xFF;
  1752.             SIGN(tmp);
  1753.             ZERO(tmp);
  1754.             break;
  1755.  
  1756.         case 0xCD:    /* CMP absolute */
  1757.             ABSOL;
  1758.             tmp = REFptr;
  1759.             C = (A >= tmp);
  1760.             tmp = (A - tmp) & 0xFF;
  1761.             SIGN(tmp);
  1762.             ZERO(tmp);
  1763.             break;
  1764.  
  1765.         case 0xCE:    /* DEC absolute */
  1766.             ABSOL;
  1767.             stmp = REFptr - 1;
  1768.             SETptr(stmp);
  1769.             SIGN(stmp);
  1770.             ZERO(stmp);
  1771.             break;
  1772.  
  1773.         case 0xCF:
  1774.             break;
  1775.  
  1776.         case 0xD0:    /* BNE */
  1777.             if (NZ) {
  1778.                 BRANCH();
  1779.             } else {
  1780.                 PCINC;
  1781.             }
  1782.             break;
  1783.  
  1784.         case 0xD1:    /* CMP (indirect), Y */
  1785.             INDY;
  1786.             tmp = REFptr;
  1787.             C = (A >= tmp);
  1788.             tmp = (A - tmp) & 0xFF;
  1789.             SIGN(tmp);
  1790.             ZERO(tmp);
  1791.             break;
  1792.  
  1793.         case 0xD2:    /* CMP (indz)        65C02 */
  1794.             break;
  1795.  
  1796.         case 0xD3:
  1797.             break;
  1798.  
  1799.         case 0xD4:
  1800.             break;
  1801.  
  1802.         case 0xD5:    /* CMP zero page, X */
  1803.             tmp = rZEROX;
  1804.             C = (A >= tmp);
  1805.             tmp = (A - tmp) & 0xFF;
  1806.             SIGN(tmp);
  1807.             ZERO(tmp);
  1808.             break;
  1809.  
  1810.         case 0xD6:    /* DEC zero page, X */
  1811.             ZEROX;
  1812.             stmp = REFzero - 1;
  1813.             SETzero(stmp);
  1814.             SIGN(stmp);
  1815.             ZERO(stmp);
  1816.             break;
  1817.  
  1818.         case 0xD7:
  1819.             break;
  1820.  
  1821.         case 0xD8:    /* CLD */
  1822.             D = 0;
  1823.             break;
  1824.  
  1825.         case 0xD9:    /* CMP absolute, Y */
  1826.             ABSY;
  1827.             tmp = REFptr;
  1828.             C = (A >= tmp);
  1829.             tmp = (A - tmp) & 0xFF;
  1830.             SIGN(tmp);
  1831.             ZERO(tmp);
  1832.             break;
  1833.  
  1834.         case 0xDA:    /* PHX        65C02 */
  1835.             break;
  1836.  
  1837.         case 0xDB:
  1838.             break;
  1839.  
  1840.         case 0xDC:
  1841.             break;
  1842.  
  1843.         case 0xDD:    /* CMP absolute, X */
  1844.             ABSX;
  1845.             tmp = REFptr;
  1846.             C = (A >= tmp);
  1847.             tmp = (A - tmp) & 0xFF;
  1848.             SIGN(tmp);
  1849.             ZERO(tmp);
  1850.             break;
  1851.  
  1852.         case 0xDE:    /* DEC absolute, X */
  1853.             ABSX;
  1854.             stmp = REFptr - 1;
  1855.             SETptr(stmp);
  1856.             SIGN(stmp);
  1857.             ZERO(stmp);
  1858.             break;
  1859.  
  1860.         case 0xDF:
  1861.             break;
  1862.  
  1863.         case 0xE0:    /* CPX immediate */
  1864.             tmp = REFimm;
  1865.             C = (X >= tmp);
  1866.             tmp = (X - tmp) & 0xFF;
  1867.             SIGN(tmp);
  1868.             ZERO(tmp);
  1869.             break;
  1870.  
  1871.         case 0xE1:    /* SBC (indirect, X) */
  1872.             INDX;
  1873.             val = REFptr;
  1874.             tmp = A & 0x80;
  1875.             stmp = val & 0x80;
  1876.             if (D) {
  1877.                 assert(FALSE);
  1878.             } else {
  1879.                 foo = A - (val + !C);
  1880.                 C = (foo >= 0);
  1881.                 A = foo & 0xFF;
  1882.             }
  1883.             ZERO(A);
  1884.             SIGN(A);
  1885.             V = (tmp != stmp) && (tmp != N);
  1886.             break;
  1887.  
  1888.         case 0xE2:
  1889.             break;
  1890.  
  1891.         case 0xE3:
  1892.             break;
  1893.  
  1894.         case 0xE4:    /* CPX zero page */
  1895.             tmp = rZEROP;
  1896.             C = (X >= tmp);
  1897.             tmp = (X - tmp) & 0xFF;
  1898.             SIGN(tmp);
  1899.             ZERO(tmp);
  1900.             break;
  1901.  
  1902.         case 0xE5:    /* SBC zero page */
  1903.             val = rZEROP;
  1904.             tmp = A & 0x80;
  1905.             stmp = val & 0x80;
  1906.             if (D) {
  1907.                 assert(FALSE);
  1908.             } else {
  1909.                 foo = A - (val + !C);
  1910.                 C = (foo >= 0);
  1911.                 A = foo & 0xFF;
  1912.             }
  1913.             ZERO(A);
  1914.             SIGN(A);
  1915.             V = (tmp != stmp) && (tmp != N);
  1916.             break;
  1917.  
  1918.         case 0xE6:    /* INC zero page */
  1919.             ZEROP;
  1920.             stmp = REFzero + 1;
  1921.             SIGN(stmp);
  1922.             ZERO(stmp);
  1923.             SETzero(stmp);
  1924.             break;
  1925.  
  1926.         case 0xE7:
  1927.             break;
  1928.  
  1929.         case 0xE8:    /* INX */
  1930.             X++;
  1931.             SIGN(X);
  1932.             ZERO(X);
  1933.             break;
  1934.  
  1935.         case 0xE9:    /* SBC immediate */
  1936.             val = REFimm;
  1937.             tmp = A & 0x80;
  1938.             stmp = val & 0x80;
  1939.             if (D) {
  1940.                 assert(FALSE);
  1941.             } else {
  1942.                 foo = A - (val + !C);
  1943.                 C = (foo >= 0);
  1944.                 A = foo & 0xFF;
  1945.             }
  1946.             ZERO(A);
  1947.             SIGN(A);
  1948.             V = (tmp != stmp) && (tmp != N);
  1949.             break;
  1950.  
  1951.         case 0xEA:    /* NOP */
  1952.             break;
  1953.  
  1954.         case 0xEB:
  1955.             break;
  1956.  
  1957.         case 0xEC:    /* CPX absolute */
  1958.             ABSOL;
  1959.             tmp = REFptr;
  1960.             C = (X >= tmp);
  1961.             tmp = (X - tmp) & 0xFF;
  1962.             SIGN(tmp);
  1963.             ZERO(tmp);
  1964.             break;
  1965.  
  1966.         case 0xED:    /* SBC absolute */
  1967.             ABSOL;
  1968.             val = REFptr;
  1969.             tmp = A & 0x80;
  1970.             stmp = val & 0x80;
  1971.             if (D) {
  1972.                 assert(FALSE);
  1973.             } else {
  1974.                 foo = A - (val + !C);
  1975.                 C = (foo >= 0);
  1976.                 A = foo & 0xFF;
  1977.             }
  1978.             ZERO(A);
  1979.             SIGN(A);
  1980.             V = (tmp != stmp) && (tmp != N);
  1981.             break;
  1982.  
  1983.         case 0xEE:    /* INC absolute */
  1984.             ABSOL;
  1985.             stmp = REFptr + 1;
  1986.             SETptr(stmp);
  1987.             SIGN(stmp);
  1988.             ZERO(stmp);
  1989.             break;
  1990.  
  1991.         case 0xEF:
  1992.             break;
  1993.  
  1994.         case 0xF0:    /* BEQ */
  1995.             if (NZ) {
  1996.                 PCINC;
  1997.             } else {
  1998.                 BRANCH();
  1999.             }
  2000.             break;
  2001.  
  2002.         case 0xF1:    /* SBC (indirect), Y */
  2003.             INDY;
  2004.             val = REFptr;
  2005.             tmp = A & 0x80;
  2006.             stmp = val & 0x80;
  2007.             if (D) {
  2008.                 assert(FALSE);
  2009.             } else {
  2010.                 foo = A - (val + !C);
  2011.                 C = (foo >= 0);
  2012.                 A = foo & 0xFF;
  2013.             }
  2014.             ZERO(A);
  2015.             SIGN(A);
  2016.             V = (tmp != stmp) && (tmp != N);
  2017.             break;
  2018.  
  2019.         case 0xF2:    /* SBC (indz)        65C02 */
  2020.             break;
  2021.  
  2022.         case 0xF3:
  2023.             break;
  2024.  
  2025.         case 0xF4:
  2026.             break;
  2027.  
  2028.         case 0xF5:    /* SBC zero page, X */
  2029.             val = rZEROX;
  2030.             tmp = A & 0x80;
  2031.             stmp = val & 0x80;
  2032.             if (D) {
  2033.                 assert(FALSE);
  2034.             } else {
  2035.                 foo = A - (val + !C);
  2036.                 C = (foo >= 0);
  2037.                 A = foo & 0xFF;
  2038.             }
  2039.             ZERO(A);
  2040.             SIGN(A);
  2041.             V = (tmp != stmp) && (tmp != N);
  2042.             break;
  2043.  
  2044.         case 0xF6:    /* INC zero page, X */
  2045.             ZEROX;
  2046.             stmp = REFzero + 1;
  2047.             SETzero(stmp);
  2048.             SIGN(stmp);
  2049.             ZERO(stmp);
  2050.             break;
  2051.  
  2052.         case 0xF7:
  2053.             break;
  2054.  
  2055.         case 0xF8:    /* SED */
  2056.             D = 1;
  2057.             break;
  2058.  
  2059.         case 0xF9:    /* SBC absolute, Y */
  2060.             ABSY;
  2061.             val = REFptr;
  2062.             tmp = A & 0x80;
  2063.             stmp = val & 0x80;
  2064.             if (D) {
  2065.                 assert(FALSE);
  2066.             } else {
  2067.                 foo = A - (val + !C);
  2068.                 C = (foo >= 0);
  2069.                 A = foo & 0xFF;
  2070.             }
  2071.             ZERO(A);
  2072.             SIGN(A);
  2073.             V = (tmp != stmp) && (tmp != N);
  2074.             break;
  2075.  
  2076.         case 0xFA:    /* PLX        65C02 */
  2077.             break;
  2078.  
  2079.         case 0xFB:
  2080.             break;
  2081.  
  2082.         case 0xFC:
  2083.             break;
  2084.  
  2085.         case 0xFD:    /* SBC absolute, X */
  2086.             ABSX;
  2087.             val = REFptr;
  2088.             tmp = A & 0x80;
  2089.             stmp = val & 0x80;
  2090.             if (D) {
  2091.                 assert(FALSE);
  2092.             } else {
  2093.                 foo = A - (val + !C);
  2094.                 C = (foo >= 0);
  2095.                 A = foo & 0xFF;
  2096.             }
  2097.             ZERO(A);
  2098.             SIGN(A);
  2099.             V = (tmp != stmp) && (tmp != N);
  2100.             break;
  2101.  
  2102.         case 0xFE:    /* INC absolute, X */
  2103.             ABSX;
  2104.             stmp = REFptr + 1;
  2105.             SETptr(stmp);
  2106.             SIGN(stmp);
  2107.             ZERO(stmp);
  2108.             break;
  2109.  
  2110.         case 0xFF:
  2111.             break;
  2112.         }
  2113.     } while (running);
  2114.  
  2115.     if (show_flags)
  2116.         flags(logging_fp);
  2117.     } while (tracing);
  2118. }
  2119.  
  2120.  
  2121. @EOF
  2122.  
  2123. chmod 644 a2.c
  2124.  
  2125. echo x - a2.h
  2126. cat >a2.h <<'@EOF'
  2127. /*
  2128.  *  a2, an Apple II emulator in C
  2129.  *  (c) Copyright 1990 by Rich Skrenta
  2130.  *
  2131.  *  Command line interface written by Tom Markson
  2132.  *
  2133.  *  Distribution agreement:
  2134.  *
  2135.  *    You may freely copy or redistribute this software, so long
  2136.  *    as there is no profit made from its use, sale, trade or
  2137.  *    reproduction.  You may not change this copyright notice,
  2138.  *    and it must be included prominently in any copy made.
  2139.  *
  2140.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2141.  *                    skrenta@blekko.uucp
  2142.  */
  2143.  
  2144.  
  2145.  
  2146. #define        TRUE        1
  2147. #define        FALSE        0
  2148.  
  2149. extern FILE    *sfp;
  2150.  
  2151. /*
  2152.  *  Assertion verifier
  2153.  */
  2154. #define    assert(p)    if(! (p)) asfail(__FILE__, __LINE__, "p"); else
  2155.  
  2156.  
  2157. #define        join(low, high)        ((low) | ((high) << 8))
  2158. #define        low(x)            ((x) & 0xFF)
  2159. #define        high(x)            ((x) >> 8)
  2160.  
  2161. #define        tobinary(v)        ((v >> 4) * 10 + (v & 0xF))
  2162. #define        tobcd(v)        ((v % 10) | ((v / 10) << 4))
  2163.  
  2164. #define        push(s)            mem[0x100 | Sp--] = s;
  2165. #define        pop()            mem[0x100 | ++Sp]
  2166.  
  2167. #define        SIGN(x)            N = ((x) & 0x80)
  2168. #define        ZERO(x)            NZ = (x)
  2169. #define        CARRY(x)        C = ((x) > 0xFF)
  2170. #define        dCARRY(x)        C = ((x) > 99)
  2171.  
  2172.  
  2173. #define    REF(a)        ((a & 0xF000) == 0xC000 ? mem_map(a) : mem[a])
  2174. #define    REFptr        ((ptr & 0xF000) == 0xC000 ? mem_map(ptr) : mem[ptr])
  2175. #define    REFzero        mem[ptr]
  2176. #define    REFimm        mem[Pc++]
  2177.  
  2178. #define    SET(a,v)    if (mem_set[a >> 8]) (*mem_set[a >> 8])(a,v); else mem[a] = v;
  2179. #define    SETptr(v)    if (mem_set[ptr >> 8]) (*mem_set[ptr >> 8])(ptr,v); else mem[ptr] = v;
  2180. #define    SETzero(v)    mem[ptr] = v;
  2181.  
  2182. #define    PCINC        Pc++;
  2183.  
  2184. #define    ABSOL        ptr = mem[Pc++]; ptr |= mem[Pc++] << 8;
  2185. #define    ABSX        ptr = mem[Pc++]; ptr |= mem[Pc++] << 8; ptr += X;
  2186. #define    ABSY        ptr = mem[Pc++]; ptr |= mem[Pc++] << 8; ptr += Y;
  2187. #define    ZEROP        ptr = mem[Pc++];
  2188. #define    ZEROX        ptr = (mem[Pc++] + X) & 0xFF;
  2189. #define    ZEROY        ptr = (mem[Pc++] + Y) & 0xFF;
  2190. #define    INDX    stmp = mem[Pc++] + X; ptr = mem[stmp++]; ptr |= mem[stmp] << 8;
  2191. #define    INDY    stmp = mem[Pc++]; ptr = mem[stmp++]; ptr |= mem[stmp] << 8; ptr += Y;
  2192.  
  2193. #define    rZEROP        mem[ mem[Pc++] ]
  2194. #define    rZEROX        mem[ (mem[Pc++] + X) & 0xFF ]
  2195. #define    rZEROY        mem[ (mem[Pc++] + Y) & 0xFF ]
  2196. #define    sZEROP(v)    mem[ mem[Pc++] ] = v;
  2197. #define    sZEROX(v)    mem[ (mem[Pc++] + X) & 0xFF ] = v;
  2198. #define    sZEROY(v)    mem[ (mem[Pc++] + Y) & 0xFF ] = v;
  2199.  
  2200. #define    ZIND        ptr = mem[ mem[Pc++] ];
  2201. #define    ABINDX        stmp = mem[Pc++]; stmp |= mem[Pc++] << 8; ptr = mem[stmp++]; ptr |= mem[stmp] << 8; ptr += X;
  2202.  
  2203.  
  2204. /*
  2205.  *  Since we store flags as 0/nonzero instead of 0/1, we need to turn
  2206.  *  nonzero back into 1.  Thus, "!!" is not a no-op.
  2207.  */
  2208.  
  2209. #define    get_status()   ((!!N << 7)|(!!V << 6)|(!!B << 4)|(!!D << 3)|(!!I << 2)|(!NZ << 1)|(!!C))
  2210.  
  2211. extern unsigned char mem[];           /* 64K memory image */
  2212. extern unsigned char jmp_tbl[];           /* jmp & jsr interceptor functions */
  2213. extern int (*mem_set[])();           /* memory store interceptors */
  2214.  
  2215. extern unsigned char mem_map();
  2216.  
  2217.  
  2218. extern unsigned short Pc;
  2219. extern unsigned char Sp;    /* stack pointer     */
  2220. extern unsigned int A;        /* accumulator        */
  2221. extern unsigned char X;        /* X register        */
  2222. extern unsigned char Y;        /* Y register        */
  2223.  
  2224. extern unsigned int N;        /* 7 - sign        */
  2225. extern unsigned int V;        /* 6 - Overflow        */
  2226.                 /* 5 - Unused        */
  2227. extern unsigned int B;        /* 4 - Break        */
  2228. extern unsigned int D;        /* 3 - Decimal        */
  2229. extern unsigned int I;        /* 2 - Interrupt    */
  2230. extern unsigned int NZ;        /* 1 - inverse of Zero  */
  2231. extern unsigned int C;        /* 0 - Carry        */
  2232.  
  2233.  
  2234. /*
  2235.  *  Note:
  2236.  *    Flags are stored as zero/nonzero instead of 0/1, except for
  2237.  *    N which is stored 0/0x80.  NZ is "not Z"; use !NZ to get
  2238.  *    the zero flag.
  2239.  *
  2240.  *    The flags code is tight, especially around overflow set on ADC
  2241.  *    and SBC.  Integer basic is a good test to see if it still works.
  2242.  */
  2243.  
  2244.  
  2245. #define        M_NONE        0
  2246. #define        M_ZP        1
  2247. #define        M_ZPX        2
  2248. #define        M_ZPY        3
  2249. #define        M_IND        4
  2250. #define        M_INDX        5
  2251. #define        M_INDY        6
  2252. #define        M_ABS        7
  2253. #define        M_ABSX        8
  2254. #define        M_ABSY        9
  2255. #define        M_IMM        10
  2256. #define        M_REL        11
  2257. #define        M_ZIND        12    /* zero page indirect, 65C02 */
  2258. #define        M_ABINDX    13    /* for jmp $7C in 65C02 */
  2259.  
  2260.  
  2261. extern int ram_read;
  2262. extern int ram_write;
  2263. extern int bank2_enable;
  2264.  
  2265. struct op_info {
  2266.     char *name;
  2267.     int add_mode;
  2268. };
  2269.  
  2270. extern struct op_info opcode[];
  2271. extern int running;
  2272. extern int tracing;
  2273. extern char *my_malloc();
  2274. extern int term_lines, term_cols;
  2275.  
  2276. extern int text1[];        /* base addresses for text page 1 */
  2277. extern int last_line;        /* line the cursor is on now */
  2278. extern int last_col;        /* current column of cursor */
  2279.  
  2280. extern int disk[2];
  2281. extern int write_prot[2];
  2282. extern int drive;
  2283.  
  2284. #define    DO_RTS    Pc = pop(); Pc |= pop() << 8; Pc++;
  2285.  
  2286. @EOF
  2287.  
  2288. chmod 644 a2.h
  2289.  
  2290. echo x - curses.c
  2291. cat >curses.c <<'@EOF'
  2292. /*
  2293.  *  a2, an Apple II emulator in C
  2294.  *  (c) Copyright 1990 by Rich Skrenta
  2295.  *
  2296.  *  Command line interface written by Tom Markson
  2297.  *
  2298.  *  Distribution agreement:
  2299.  *
  2300.  *    You may freely copy or redistribute this software, so long
  2301.  *    as there is no profit made from its use, sale, trade or
  2302.  *    reproduction.  You may not change this copyright notice,
  2303.  *    and it must be included prominently in any copy made.
  2304.  *
  2305.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2306.  *                    skrenta@blekko.uucp
  2307.  */
  2308.  
  2309. /*
  2310. **  This a screen management library borrowed with permission from the
  2311. **  Elm mail system (a great mailer--I highly recommend it!).
  2312. **
  2313. **  I've hacked this library to only provide what I need.
  2314. **
  2315. **  Original copyright follows:
  2316. */
  2317. /*******************************************************************************
  2318.  *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
  2319.  *
  2320.  *             Copyright (c) 1986 Dave Taylor
  2321.  ******************************************************************************/
  2322.  
  2323. #ifndef M_XENIX
  2324. #include <sys/termio.h>
  2325. #endif
  2326.  
  2327. #include <stdio.h>
  2328. #include <curses.h>
  2329. #include <ctype.h>
  2330.  
  2331. #define DEFAULT_term_lines    24
  2332. #define DEFAULT_COLUMNS    80
  2333. #define TTYIN    0
  2334.  
  2335.  
  2336. #define        VERY_LONG_STRING    2500
  2337.  
  2338. int term_lines = DEFAULT_term_lines - 1;
  2339. int term_cols  = DEFAULT_COLUMNS;
  2340. extern char escape_char;
  2341.  
  2342. #ifdef SHORTNAMES
  2343. # define _cleartoeoln    _clrtoeoln
  2344. # define _cleartoeos    _clr2eos
  2345. #endif
  2346.  
  2347. #ifndef BSD
  2348. struct termio raw_tty, 
  2349.               orig_tty;
  2350. #else
  2351. #define TCGETA    TIOCGETP
  2352. #define TCSETAW    TIOCSETP
  2353.  
  2354. struct sgttyb raw_tty,
  2355.           orig_tty;
  2356. #endif
  2357.  
  2358. static int inraw = 0;                  /* are we IN rawmode?    */
  2359.  
  2360.  
  2361. static int _memory_locked = 0;        /* are we IN memlock??   */
  2362.  
  2363. static int _intransmit;            /* are we transmitting keys? */
  2364.  
  2365. static
  2366. char *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
  2367.     *_setinverse, *_clearinverse;
  2368.  
  2369.  
  2370. static
  2371. int _lines,_columns;
  2372.  
  2373. static char _terminal[1024];              /* Storage for terminal entry */
  2374. static char _capabilities[1024];           /* String for cursor motion */
  2375.  
  2376. static char *ptr = _capabilities;    /* for buffering         */
  2377.  
  2378. int    outchar();            /* char output for tputs */
  2379. char  *tgetstr(),                    /* Get termcap capability */
  2380.       *tgoto();                /* and the goto stuff    */
  2381.  
  2382. InitScreen()
  2383. {
  2384. int  tgetent(),      /* get termcap entry */
  2385.      err;
  2386. char termname[40];
  2387. char *strcpy(), *getenv();
  2388.     
  2389.     if (getenv("TERM") == NULL) {
  2390.         fprintf(stderr,
  2391.           "TERM variable not set; Screen capabilities required\n");
  2392.         return(FALSE);
  2393.     }
  2394.     if (strcpy(termname, getenv("TERM")) == NULL) {
  2395.         fprintf(stderr,"Can't get TERM variable\n");
  2396.         return(FALSE);
  2397.     }
  2398.     if ((err = tgetent(_terminal, termname)) != 1) {
  2399.         fprintf(stderr,"Can't get entry for TERM\n");
  2400.         return(FALSE);
  2401.     }
  2402.  
  2403.     /* load in all those pesky values */
  2404.     _clearscreen       = tgetstr("cl", &ptr);
  2405.     _moveto            = tgetstr("cm", &ptr);
  2406.     _cleartoeoln       = tgetstr("ce", &ptr);
  2407.     _cleartoeos        = tgetstr("cd", &ptr);
  2408.     _setinverse        = tgetstr("so", &ptr);
  2409.     _clearinverse      = tgetstr("se", &ptr);
  2410.     _lines                 = tgetnum("li");
  2411.     _columns       = tgetnum("co");
  2412.  
  2413.     if (!_clearscreen) {
  2414.         fprintf(stderr,
  2415.             "Terminal must have clearscreen (cl) capability\n");
  2416.         return(FALSE);
  2417.     }
  2418.     if (!_moveto) {
  2419.         fprintf(stderr,
  2420.             "Terminal must have cursor motion (cm)\n");
  2421.         return(FALSE);
  2422.     }
  2423.     if (!_cleartoeoln) {
  2424.         fprintf(stderr,
  2425.             "Terminal must have clear to end-of-line (ce)\n");
  2426.         return(FALSE);
  2427.     }
  2428.     if (!_cleartoeos) {
  2429.         fprintf(stderr,
  2430.             "Terminal must have clear to end-of-screen (cd)\n");
  2431.         return(FALSE);
  2432.     }
  2433.     if (_lines == -1)
  2434.         _lines = DEFAULT_term_lines;
  2435.     if (_columns == -1)
  2436.         _columns = DEFAULT_COLUMNS;
  2437.     return(TRUE);
  2438. }
  2439.  
  2440. ScreenSize(lines, columns)
  2441. int *lines, *columns;
  2442. {
  2443.     /** returns the number of lines and columns on the display. **/
  2444.  
  2445.     if (_lines == 0) _lines = DEFAULT_term_lines;
  2446.     if (_columns == 0) _columns = DEFAULT_COLUMNS;
  2447.  
  2448.     *lines = _lines - 1;        /* assume index from zero*/
  2449.     *columns = _columns;        /* assume index from one */
  2450. }
  2451.  
  2452. ClearScreen()
  2453. {
  2454.     /* clear the screen: returns -1 if not capable */
  2455.  
  2456.     tputs(_clearscreen, 1, outchar);
  2457.     fflush(stdout);      /* clear the output buffer */
  2458. }
  2459.  
  2460. MoveCursor(row, col)
  2461. int row, col;
  2462. {
  2463.     /** move cursor to the specified row column on the screen.
  2464.             0,0 is the top left! **/
  2465.  
  2466.     char *stuff, *tgoto();
  2467.  
  2468.     stuff = tgoto(_moveto, col, row);
  2469.     tputs(stuff, 1, outchar);
  2470. /*    fflush(stdout);    */
  2471. }
  2472.  
  2473. CleartoEOLN()
  2474. {
  2475.     /** clear to end of line **/
  2476.  
  2477.     tputs(_cleartoeoln, 1, outchar);
  2478.     fflush(stdout);  /* clear the output buffer */
  2479. }
  2480.  
  2481. CleartoEOS()
  2482. {
  2483.     /** clear to end of screen **/
  2484.  
  2485.     tputs(_cleartoeos, 1, outchar);
  2486.     fflush(stdout);  /* clear the output buffer */
  2487. }
  2488.  
  2489. Raw(state)
  2490. int state;
  2491. {
  2492.     /** state is either TRUE or FALSE, as indicated by call **/
  2493.  
  2494.     if (state == FALSE && inraw) {
  2495.       (void) ioctl(TTYIN, TCSETAW, &orig_tty);
  2496.       inraw = 0;
  2497.     }
  2498.     else if (state == TRUE && ! inraw) {
  2499.  
  2500.       (void) ioctl(TTYIN, TCGETA, &orig_tty);    /** current setting **/
  2501.  
  2502.       (void) ioctl(TTYIN, TCGETA, &raw_tty);    /** again! **/
  2503. #ifdef BSD
  2504. /*      raw_tty.sg_flags &= ~(ECHO | CRMOD);    /* echo off */
  2505.       raw_tty.sg_flags &= ~ECHO;        /* echo off */
  2506.       raw_tty.sg_flags |= CBREAK;    /* raw on    */
  2507. #else
  2508.       raw_tty.c_lflag &= ~(ICANON | ECHO);    /* noecho raw mode        */
  2509.  
  2510.       raw_tty.c_cc[VMIN] = '\01';    /* minimum # of chars to queue    */
  2511.       raw_tty.c_cc[VTIME] = '\0';    /* minimum time to wait for input */
  2512.  
  2513. #endif
  2514.       raw_tty.c_cc[VINTR]= escape_char;
  2515.       (void) ioctl(TTYIN, TCSETAW, &raw_tty);
  2516.       inraw = 1;
  2517.     }
  2518. }
  2519.  
  2520. int
  2521. ReadCh()
  2522. {
  2523.     /** read a character with Raw mode set! **/
  2524.  
  2525.     register int result;
  2526.     char ch;
  2527.     result = read(0, &ch, 1);
  2528.         return((result <= 0 ) ? EOF : ch);
  2529. }
  2530.  
  2531.  
  2532. outchar(c)
  2533. char c;
  2534. {
  2535.     /** output the given character.  From tputs... **/
  2536.     /** Note: this CANNOT be a macro!              **/
  2537.  
  2538.     putc(c, stdout);
  2539. }
  2540.  
  2541.  
  2542. #if 0
  2543. static int inverse = FALSE;
  2544.  
  2545. SetInverse() {
  2546.  
  2547.     if (!inverse) {
  2548.         StartInverse();
  2549.         inverse = TRUE;
  2550.     }
  2551. }
  2552.  
  2553. SetNormal() {
  2554.  
  2555.     if (inverse) {
  2556.         EndInverse();
  2557.         inverse = FALSE;
  2558.     }
  2559. }
  2560. #endif
  2561.  
  2562.  
  2563. StartInverse()
  2564. {
  2565.     /** set inverse video mode **/
  2566.  
  2567.     if (!_setinverse)
  2568.         return(-1);
  2569.  
  2570.     tputs(_setinverse, 1, outchar);
  2571. /*    fflush(stdout);    */
  2572.     return(0);
  2573. }
  2574.  
  2575.  
  2576. EndInverse()
  2577. {
  2578.     /** compliment of startinverse **/
  2579.  
  2580.     if (!_clearinverse)
  2581.         return(-1);
  2582.  
  2583.     tputs(_clearinverse, 1, outchar);
  2584. /*    fflush(stdout);    */
  2585.     return(0);
  2586. }
  2587.  
  2588. @EOF
  2589.  
  2590. chmod 644 curses.c
  2591.  
  2592. echo x - disk.c
  2593. cat >disk.c <<'@EOF'
  2594. /*
  2595.  *  a2, an Apple II emulator in C
  2596.  *  (c) Copyright 1990 by Rich Skrenta
  2597.  *
  2598.  *  Command line interface written by Tom Markson
  2599.  *
  2600.  *  Distribution agreement:
  2601.  *
  2602.  *    You may freely copy or redistribute this software, so long
  2603.  *    as there is no profit made from its use, sale, trade or
  2604.  *    reproduction.  You may not change this copyright notice,
  2605.  *    and it must be included prominently in any copy made.
  2606.  *
  2607.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2608.  *                    skrenta@blekko.uucp
  2609.  */
  2610.  
  2611.  
  2612. #include    <stdio.h>
  2613. #include    "a2.h"
  2614.  
  2615.  
  2616. #define        GAP    0x7F;        /* data gap byte */
  2617.  
  2618.  
  2619. /*
  2620.  *  4 by 4 nibble encoding macros
  2621.  */
  2622.  
  2623. #define        nib1(a)    (((a) >> 1) | 0xAA)
  2624. #define        nib2(a)    ((a) | 0xAA)
  2625. #define        denib(a,b)    (((((a) & 0x55) << 1) & 0xFF) | ((b) & 0x55))
  2626.  
  2627.  
  2628. int cur_track[2] = {0, 0};
  2629. int sect_pos[2];        /* current sector within track */
  2630.  
  2631. extern unsigned char tab1[];    /* For nibblizing.  At end of this file */
  2632. extern unsigned char tab2[];    /* Disk byte translation table. */
  2633. extern unsigned char phys[];    /* DOS 3.3 to physical sector mapping */
  2634.  
  2635. unsigned char sect_buf[2][1024];
  2636. unsigned char *sectp = NULL;
  2637. unsigned char *sect_point[2] = {NULL, NULL};
  2638. unsigned char write_reg;    /* write data register */
  2639. int write_mode = FALSE;
  2640.  
  2641.  
  2642.  
  2643. unsigned char
  2644. disk_ref(a, n)
  2645. unsigned short a;
  2646. unsigned char n;
  2647. {
  2648.  
  2649.     switch (a) {
  2650.     case 0xC0E0:    /* Phase 0 off */
  2651.     case 0xC0E1:    /* Phase 0 on */
  2652.     case 0xC0E2:    /* Phase 1 off */
  2653.     case 0xC0E3:    /* Phase 1 on */
  2654.     case 0xC0E4:    /* Phase 2 off */
  2655.     case 0xC0E5:    /* Phase 2 on */
  2656.     case 0xC0E6:    /* Phase 3 off */
  2657.     case 0xC0E7:    /* Phase 3 on */
  2658.         step_motor(a);
  2659.         break;
  2660.  
  2661.     case 0xC0E8:    /* Drive off */
  2662.         break;
  2663.  
  2664.     case 0xC0E9:    /* Drive on */
  2665.         break;
  2666.  
  2667.     case 0xC0EA:    /* Select drive 1 */
  2668.         sect_point[drive] = sectp;
  2669.         drive = 0;
  2670.         sectp = sect_point[0];
  2671.         break;
  2672.  
  2673.     case 0xC0EB:    /* Select drive 2 */
  2674.         sect_point[drive] = sectp;
  2675.         drive = 1;
  2676.         sectp = sect_point[1];
  2677.         break;
  2678.  
  2679.     case 0xC0EC:    /* Shift data register */
  2680.         if (disk[drive] < 0)
  2681.             return(0xFF);
  2682.  
  2683.         if (write_mode) {
  2684.             raw_disk_write();
  2685.             return(0);
  2686.         }
  2687.  
  2688.         if (sectp == NULL || *sectp == '\0') {
  2689.             sect_pos[drive]--;
  2690.             if (sect_pos[drive] < 0)
  2691.                 sect_pos[drive] = 15;
  2692.             setup_sector(cur_track[drive], sect_pos[drive]);
  2693.         }
  2694.  
  2695.         return(*sectp++);
  2696.  
  2697.     case 0xC0ED:    /* Load data register */
  2698.         write_reg = n;
  2699.         break;
  2700.  
  2701.     case 0xC0EE:    /* Read mode */
  2702.         write_mode = FALSE;
  2703.         return(write_prot[drive] ? 0xFF : 0);
  2704.         break;
  2705.  
  2706.     case 0xC0EF:    /* Write mode */
  2707.         write_mode = TRUE;
  2708.         break;
  2709.     }
  2710.  
  2711.     return(0);
  2712. }
  2713.  
  2714.  
  2715.  
  2716. /*
  2717.  *  Determine what track the disk head is over by watching toggles to
  2718.  *  the four stepper motor magnets.
  2719.  */
  2720.  
  2721. step_motor(a)
  2722. unsigned short a;
  2723. {
  2724. static    int mag[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}},
  2725.     pmag[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}},    /* previous */
  2726.     ppmag[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}},    /* previous previous */
  2727.     pnum[2] = {0, 0},
  2728.     ppnum[2] = {0, 0},
  2729.     track_pos[2] = {0, 0};
  2730.  
  2731. static int prev_track[2] = {0, 0};
  2732. int magnet_number;
  2733.  
  2734.     a &= 7;
  2735.     magnet_number = a >> 1;
  2736.  
  2737.     ppmag[drive][ppnum[drive]] = pmag[drive][ppnum[drive]];
  2738.     ppnum[drive] = pnum[drive];
  2739.  
  2740.     pmag[drive][pnum[drive]] = mag[drive][pnum[drive]];
  2741.     pnum[drive] = magnet_number;
  2742.  
  2743.     if ((a & 1) == 0)
  2744.         mag[drive][magnet_number] = FALSE;
  2745.     else {
  2746.         if (ppmag[drive][(magnet_number + 1) & 3]) {
  2747.             track_pos[drive]--;
  2748.             if (track_pos[drive] < 0) {
  2749.                 track_pos[drive] = 0;
  2750.                 if (drive)
  2751.                     info("recal d2");
  2752.                 else
  2753.                     info("recal");
  2754.             }
  2755.         }
  2756.  
  2757.         if (ppmag[drive][(magnet_number - 1) & 3]) {
  2758.             track_pos[drive]++;
  2759.             if (track_pos[drive] > 140)
  2760.                 track_pos[drive] = 140;
  2761.  
  2762.         }
  2763.         mag[drive][magnet_number] = TRUE;
  2764.     }
  2765.  
  2766.     cur_track[drive] = (track_pos[drive] + 1) / 2;
  2767.     if (cur_track[drive] != prev_track[drive]) {
  2768. #if 0
  2769.         sprintf(s, "step to %d%s", cur_track[drive],
  2770.                         drive ? " d2" : "");
  2771.         info(s);
  2772. #endif
  2773.         sectp[drive] = NULL;    /* recompute sector if head moves */
  2774.         sect_pos[drive] = 0;
  2775.         prev_track[drive] = cur_track[drive];
  2776.     }
  2777. }
  2778.  
  2779.  
  2780.  
  2781. setup_sector(track, sector)
  2782. int track;
  2783. int sector;
  2784. {
  2785. int checksum;
  2786. int physical_sector;
  2787. char s[50];
  2788. int i;
  2789.  
  2790.     physical_sector = phys[sector];
  2791.  
  2792.     sprintf(s, "raw t=%d s=%d%s", track, sector, drive ? " d2" : "");
  2793.     info(s);
  2794.  
  2795.     sectp = sect_buf[drive];
  2796.  
  2797.     for (i = 0; i < 16; i++)
  2798.         *sectp++ = GAP;
  2799.  
  2800.     *sectp++ = 0xD5;            /* address header */
  2801.     *sectp++ = 0xAA;
  2802.     *sectp++ = 0x96;
  2803.  
  2804.     *sectp++ = 0xFF;            /* disk volume 254 */
  2805.     *sectp++ = 0xFE;
  2806.  
  2807.     *sectp++ = nib1(track);
  2808.     *sectp++ = nib2(track);
  2809.  
  2810.     *sectp++ = nib1(physical_sector);
  2811.     *sectp++ = nib2(physical_sector);
  2812.  
  2813.     checksum = 254 ^ track ^ physical_sector;
  2814.     *sectp++ = nib1(checksum);
  2815.     *sectp++ = nib2(checksum);
  2816.  
  2817.     *sectp++ = 0xDE;            /* address trailer */
  2818.     *sectp++ = 0xAA;
  2819.  
  2820.     for (i = 0; i < 8; i++)
  2821.         *sectp++ = GAP;
  2822.  
  2823.     *sectp++ = 0xD5;            /* data header */
  2824.     *sectp++ = 0xAA;
  2825.     *sectp++ = 0xAD;
  2826.  
  2827.     encode_data(track, sector);        /* nibblized data */
  2828.  
  2829.     *sectp++ = 0xDE;            /* data trailer */
  2830.     *sectp++ = 0xAA;
  2831.     *sectp++ = 0xEB;
  2832.  
  2833.     *sectp = '\0';                /* ending mark for our use */
  2834.     sectp = sect_buf[drive];        /* start reading at beginning */
  2835. }
  2836.  
  2837.  
  2838. /*
  2839.  *  Take a normal 256 byte sector and nibblize it into 342 bytes
  2840.  *  Checksum it with itself; this yields one more byte.
  2841.  *  Translate the resulting 343 bytes into "disk bytes".
  2842.  *  Insert them into the sector buffer.
  2843.  *
  2844.  *  See a reference such as _Beneath Apple Prodos_ for an explanation
  2845.  *  of why & how this is done.
  2846.  */
  2847.  
  2848. encode_data(track, sector)
  2849. int track;
  2850. int sector;
  2851. {
  2852. unsigned char buf[344];
  2853. unsigned char *one;
  2854. unsigned char *bump;
  2855. unsigned char *two;
  2856. unsigned char *three;
  2857. unsigned char *dest;
  2858. int i;
  2859.  
  2860.     read_disk(track, sector, &buf[86]);
  2861.     buf[342] = 0;
  2862.     buf[343] = 0;
  2863.  
  2864.     dest = buf;
  2865.     one = &buf[86];
  2866.     two = &buf[86 + 0x56];
  2867.     bump = two;
  2868.     three = &buf[86 + 0xAC];
  2869.  
  2870.     do {
  2871.         i = (*one++ & 0x03) |
  2872.             ((*two++ & 0x03) << 2) | ((*three++ & 0x03) << 4);
  2873.  
  2874.         *dest++ = tab1[i];
  2875.     } while (one != bump);
  2876.  
  2877.     sectp[0] = buf[0];
  2878.     for (i = 1; i <= 342; i++)
  2879.         sectp[i] = buf[i - 1] ^ buf[i];
  2880.  
  2881.     for (i = 0; i <= 342; i++)
  2882.         sectp[i] = tab2[ sectp[i] >> 2 ];
  2883.  
  2884.     sectp = §p[343];
  2885. }
  2886.  
  2887.  
  2888. raw_disk_write() {
  2889.  
  2890.     printf("raw write %.2X\n", write_reg);
  2891. }
  2892.  
  2893.  
  2894. read_disk(track, sector, buf)
  2895. int track;
  2896. int sector;
  2897. unsigned char *buf;
  2898. {
  2899. long block;
  2900.  
  2901.     block = track * 16 + sector;
  2902.  
  2903.     lseek(disk[drive], block * 256, 0);
  2904.     if (read(disk[drive], buf, 256) != 256)
  2905.         perror("bad read");
  2906. }
  2907.  
  2908.  
  2909. write_disk(track, sector, buf)
  2910. int track;
  2911. int sector;
  2912. unsigned char *buf;
  2913. {
  2914. long block;
  2915.  
  2916.     block = track * 16 + sector;
  2917.  
  2918.     lseek(disk[drive], block * 256, 0);
  2919.     if (write(disk[drive], buf, 256) != 256)
  2920.         perror("bad write");
  2921. }
  2922.  
  2923.  
  2924. /*
  2925.  *  Helps with the bit fiddling necessary to extract the bottom
  2926.  *  two bits during the 256 - 342 byte nibblize.
  2927.  */
  2928.  
  2929. unsigned char tab1[] = {
  2930.     0x00, 0x08, 0x04, 0x0C, 0x20, 0x28, 0x24, 0x2C,
  2931.     0x10, 0x18, 0x14, 0x1C, 0x30, 0x38, 0x34, 0x3C,
  2932.     0x80, 0x88, 0x84, 0x8C, 0xA0, 0xA8, 0xA4, 0xAC,
  2933.     0x90, 0x98, 0x94, 0x9C, 0xB0, 0xB8, 0xB4, 0xBC,
  2934.     0x40, 0x48, 0x44, 0x4C, 0x60, 0x68, 0x64, 0x6C,
  2935.     0x50, 0x58, 0x54, 0x5C, 0x70, 0x78, 0x74, 0x7C,
  2936.     0xC0, 0xC8, 0xC4, 0xCC, 0xE0, 0xE8, 0xE4, 0xEC,
  2937.     0xD0, 0xD8, 0xD4, 0xDC, 0xF0, 0xF8, 0xF4, 0xFC,
  2938. };
  2939.  
  2940.  
  2941. /*
  2942.  *  Translates to "disk bytes"
  2943.  */
  2944.  
  2945. unsigned char tab2[] = {
  2946.     0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 
  2947.     0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, 
  2948.     0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 
  2949.     0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, 
  2950.     0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 
  2951.     0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, 
  2952.     0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 
  2953.     0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 
  2954. };
  2955.  
  2956.  
  2957. /*
  2958.  *  Dos 3.3 to physical sector conversion
  2959.  */
  2960.  
  2961. unsigned char phys[] = {
  2962.     0x00, 0x0D, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01,
  2963.     0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x0F,
  2964. };
  2965.  
  2966. @EOF
  2967.  
  2968. chmod 644 disk.c
  2969.  
  2970. echo x - tbl.c
  2971. cat >tbl.c <<'@EOF'
  2972. /*
  2973.  *  a2, an Apple II emulator in C
  2974.  *  (c) Copyright 1990 by Rich Skrenta
  2975.  *
  2976.  *  Command line interface written by Tom Markson
  2977.  *
  2978.  *  Distribution agreement:
  2979.  *
  2980.  *    You may freely copy or redistribute this software, so long
  2981.  *    as there is no profit made from its use, sale, trade or
  2982.  *    reproduction.  You may not change this copyright notice,
  2983.  *    and it must be included prominently in any copy made.
  2984.  *
  2985.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2986.  *                    skrenta@blekko.uucp
  2987.  */
  2988.  
  2989.  
  2990. #include    <stdio.h>
  2991. #include    "cli.h"
  2992.  
  2993.  
  2994. int quit_emulator();
  2995. int cont();
  2996. int refresh();
  2997. int clc(), sec(), sev(), clb(), seb();
  2998. int clri(), sei(), sez(), clz(), sen(), cln(), sed(), cld(), clv();
  2999. int ver();
  3000. int shell_escape();
  3001. int do_soft_reset();
  3002. int do_bload();
  3003. int do_bsave();
  3004. int show_point();
  3005. int do_jump();
  3006. int ldx(), ldy(), lds(), lda();
  3007. int trace();
  3008. int set_break_point(), clear_break_point();
  3009. int notrace();
  3010. int insert_disk();
  3011. int dissassemble();
  3012. int hex_dump();
  3013. int deposit();
  3014. int phantom_trace();
  3015. int no_phantom_trace();
  3016. int cd();
  3017. int map();
  3018. int sex();
  3019. int help();
  3020. int set_escape_char();
  3021. int hack();
  3022. int init_point(), push_point(), dup_point(), pop_point();
  3023. int disk_names();
  3024.  
  3025. struct cmdtbl first_tbl[] = {
  3026.     {"!",        shell_escape},
  3027.     {".",        show_point},
  3028.     {"bload",    do_bload},
  3029.     {"breakpoint",    set_break_point},
  3030.     {"bsave",    do_bsave},
  3031.     {"cd",        cd},
  3032.     {"clc",        clc},
  3033.     {"cld",        cld},
  3034.     {"cli",        clri},
  3035.     {"cln",        cln},
  3036.     {"clv",        clv},
  3037.     {"clz",        clz},
  3038.     {"continue",    refresh},
  3039.     {"deposit",    deposit},
  3040.     {"disks",    disk_names},
  3041.     {"dup",        dup_point},
  3042.     {"escape",    set_escape_char},
  3043.     {"examine",    hex_dump},
  3044.     {".e",        hex_dump},
  3045.     {"hack",    hack},
  3046.     {"help",    help},
  3047.     {"insert",    insert_disk},
  3048.     {"jmp",        do_jump},
  3049.     {"lda",        lda},
  3050.     {"lds",        lds},
  3051.     {"ldx",        ldx},
  3052.     {"ldy",        ldy},
  3053.     {"list",    dissassemble},
  3054.     {"map",        map},
  3055.     {"nobreak",    clear_break_point},
  3056.     {"notrace",    notrace},
  3057.     {"pop",        pop_point},
  3058.     {"push",    push_point},
  3059.     {"quit",    quit_emulator},
  3060.     {"reset",    do_soft_reset},
  3061.     {"sec",        sec},
  3062.     {"sed",        sed},
  3063.     {"sei",        sei},
  3064.     {"sen",        sen},
  3065.     {"sev",        sev},
  3066.     {".sex",    sex},
  3067.     {"sez",        sez},
  3068.     {"trace",    trace},
  3069.     {".version",    ver},
  3070.     {".c",        refresh},
  3071.     {".clb",    clb},
  3072.     {".d",        deposit},
  3073.     {".e",        hex_dump},
  3074.     {".l",        dissassemble},
  3075.     {".phantom",    phantom_trace},
  3076.     {".seb",    seb},
  3077.     {".nophantom",    no_phantom_trace},
  3078.     {NULL,        NULL},
  3079. };
  3080.  
  3081. @EOF
  3082.  
  3083. chmod 644 tbl.c
  3084.  
  3085. exit 0
  3086. -- 
  3087. skrenta@blekko.commodore.com
  3088.