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

  1. From: skrenta@blekko.UUCP (Rich Skrenta)
  2. Newsgroups: alt.sources
  3. Subject: a2 - Apple II emulator, part 2/2
  4. Message-ID: <123@blekko.UUCP>
  5. Date: 23 May 90 16:35:40 GMT
  6.  
  7.  
  8.  
  9. # This is a shell archive.  Remove anything before this line,
  10. # then unpack it by saving it in a file and typing "sh file".
  11. #
  12. # This archive contains:
  13. #    cli.c        cli.h        commands.c    dos.c        
  14. #    hex.c        jump.c        main.c        mapper.c    
  15. #    mem.c        parse.c        prodos.c    screen.c    
  16. #    table.c        vidout.c    
  17. #
  18.  
  19. echo x - cli.c
  20. cat >cli.c <<'@EOF'
  21. /*
  22.  *  a2, an Apple II emulator in C
  23.  *  (c) Copyright 1990 by Rich Skrenta
  24.  *
  25.  *  Command line interface written by Tom Markson
  26.  *
  27.  *  Distribution agreement:
  28.  *
  29.  *    You may freely copy or redistribute this software, so long
  30.  *    as there is no profit made from its use, sale, trade or
  31.  *    reproduction.  You may not change this copyright notice,
  32.  *    and it must be included prominently in any copy made.
  33.  *
  34.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  35.  *                    skrenta@blekko.uucp
  36.  */
  37.  
  38.  
  39.  
  40. #include    <stdio.h>
  41. #include    <setjmp.h>
  42. #include    <signal.h>
  43. #include    "a2.h"
  44. #include    "cli.h"
  45.  
  46.  
  47. FILE *logging_fp = NULL;
  48. long    breakpoint = -1;
  49. long    trace_lo = -1;
  50. long    trace_hi;
  51. int    in_cli;
  52.  
  53. unsigned short lpoint;        /* point where dissassembly occurs */
  54. long phantom_location = -1;
  55. int map_to_upper = 1;
  56. jmp_buf jb;
  57.  
  58. cli_catch() {
  59.     signal(SIGINT,cli_catch);
  60.     printf("\n");
  61.     longjmp(jb,1);
  62. }
  63.  
  64. cli() 
  65. {
  66.     char    foo[200];
  67.  
  68.     restore_term();
  69.     MoveCursor(term_lines, 0);
  70.     status(stdout);
  71.     in_cli = TRUE;
  72.     lpoint = Pc;
  73.     signal(SIGINT, cli_catch);
  74.     setjmp(jb);
  75.     do {
  76.         printf(">>>");
  77.         if (fgets(foo, 200, stdin) == NULL) {
  78.             printf("\n");
  79.             exit(0);
  80.         }
  81.         foo[strlen(foo)-1] = '\0';
  82.         if (parse(first_tbl, foo)) {
  83.             running = FALSE;
  84.             tracing = FALSE;
  85.             return;            /* single step; no redraw */
  86.         }
  87.     } while (in_cli);
  88.  
  89.     set_term();
  90.     redraw_screen();
  91.     if (breakpoint != -1 || trace_lo != -1) {
  92.         tracing = TRUE;
  93.         running = FALSE;
  94.     } else {
  95.         tracing = FALSE;
  96.         running = TRUE;
  97.     }
  98. }
  99.  
  100.  
  101. status(fp)
  102. FILE *fp;
  103. {
  104.  
  105.     diss(Pc, fp);
  106.     flags(fp);
  107. }
  108.  
  109.  
  110. @EOF
  111.  
  112. chmod 644 cli.c
  113.  
  114. echo x - cli.h
  115. cat >cli.h <<'@EOF'
  116. /*
  117.  *  a2, an Apple II emulator in C
  118.  *  (c) Copyright 1990 by Rich Skrenta
  119.  *
  120.  *  Command line interface written by Tom Markson
  121.  *
  122.  *  Distribution agreement:
  123.  *
  124.  *    You may freely copy or redistribute this software, so long
  125.  *    as there is no profit made from its use, sale, trade or
  126.  *    reproduction.  You may not change this copyright notice,
  127.  *    and it must be included prominently in any copy made.
  128.  *
  129.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  130.  *                    skrenta@blekko.uucp
  131.  */
  132.  
  133.  
  134.  
  135. /*
  136.  *  Return codes for match(), find_box(), and parse()
  137.  */
  138.  
  139. #define        NO_MATCH    -1    /* strings are different */
  140. #define        PARTIAL        -3    /* partial match */
  141. #define        IDENTICAL    -4    /* strings matched perfectly */
  142.  
  143. #define        AMBIGUOUS    -2    /* amiguous match */
  144. #define        OK        -5    /* command executed ok */
  145. #define        NOT_IMPLEMENTED    -6    /* haven't written this one yet */
  146. #define        DISPLAY        -7    /* redisplay the diss & flags line */
  147.  
  148. #define MAXSTACK 100
  149.  
  150. struct cmdtbl {
  151.     char *name;
  152.     int (*func)();
  153. };
  154.  
  155. extern long breakpoint;
  156. extern struct cmdtbl first_tbl[];
  157. extern int in_cli;
  158. extern long trace_lo, trace_hi;
  159. extern long get_hex_number();
  160. extern FILE *logging_fp;
  161. extern char *getenv();
  162. extern char *split();
  163.  
  164. @EOF
  165.  
  166. chmod 644 cli.h
  167.  
  168. echo x - commands.c
  169. cat >commands.c <<'@EOF'
  170. /*
  171.  *  a2, an Apple II emulator in C
  172.  *  (c) Copyright 1990 by Rich Skrenta
  173.  *
  174.  *  Command line interface written by Tom Markson
  175.  *
  176.  *  Distribution agreement:
  177.  *
  178.  *    You may freely copy or redistribute this software, so long
  179.  *    as there is no profit made from its use, sale, trade or
  180.  *    reproduction.  You may not change this copyright notice,
  181.  *    and it must be included prominently in any copy made.
  182.  *
  183.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  184.  *                    skrenta@blekko.uucp
  185.  */
  186.  
  187.  
  188. #include    <stdio.h>
  189. #include    <ctype.h>
  190. #include    <signal.h>
  191. #include    "a2.h"
  192. #include    "cli.h"
  193.  
  194.  
  195. extern unsigned short lpoint;
  196. extern long phantom_location;
  197. extern char *getcwd();
  198. extern int map_to_upper;
  199. extern char escape_char;
  200. long get_hex_number();
  201.  
  202. char diskname[2][200];        /* disk names stored here */
  203.  
  204. struct point_stack {
  205.     unsigned short data[MAXSTACK];
  206.     int sp;
  207. } pstack;
  208.  
  209. init_point(){
  210.     pstack.sp = -1;
  211. }
  212.  
  213. pop_point(rest)
  214. char *rest;
  215. {
  216.     if (pstack.sp < 0 ) {
  217.         printf("stack empty\n");
  218.         return OK;
  219.     }
  220.     switch (*rest){
  221.         case 'l':
  222.         case 'L':
  223.             printf("%x\n", lpoint = pstack.data[pstack.sp--]);
  224.             break;
  225.         case 'p':
  226.         case 'P':
  227.             printf("%x\n", lpoint = pstack.data[pstack.sp--]);
  228.             break;
  229.         default : 
  230.             printf("pop [lp]\n");
  231.             break;
  232.     }
  233.     return(OK);
  234. }
  235.  
  236. dup_point(rest)
  237. char *rest;
  238. {
  239.     if (pstack.sp < 0 ) {
  240.         printf("stack empty\n");
  241.         return OK;
  242.     }
  243.     switch (*rest){
  244.         case 'l':
  245.         case 'L':
  246.             lpoint = pstack.data[pstack.sp];
  247.             break;
  248.         case 'p':
  249.         case 'P':
  250.             lpoint = pstack.data[pstack.sp];
  251.             break;
  252.         default : 
  253.             printf("dup [lp]\n");
  254.             break;
  255.     }
  256.     return(OK);
  257. }
  258.  
  259. push_point(rest)
  260. char *rest;
  261. {
  262.     long value;
  263.     char *addr;
  264.  
  265.     assert (pstack.sp < MAXSTACK);
  266.     switch (*rest){
  267.         case 'l':
  268.         case 'L':
  269.             pstack.data[++pstack.sp] = lpoint;
  270.             break;
  271.         case 'p':
  272.         case 'P':
  273.             pstack.data[++pstack.sp] = Pc;
  274.             break;
  275.         default:
  276.             addr = rest;
  277.             rest = split(rest);
  278.             value = get_hex_number(addr);
  279.             if (value == -1L) 
  280.                 printf("push [l|p|<addr>]\n");
  281.             else 
  282.                 pstack.data[++pstack.sp]=(unsigned short)value;
  283.             break;
  284.     }
  285.     return(OK);
  286. }
  287.  
  288.  
  289. clb(junk)
  290. char *junk;
  291. {
  292.  
  293.     B = 0;
  294.     return(DISPLAY);
  295. }
  296.  
  297.  
  298. seb(junk)
  299. char *junk;
  300. {
  301.  
  302.     B = 1;
  303.     return(DISPLAY);
  304. }
  305.  
  306.  
  307. clc(junk)
  308. char    *junk;
  309. {
  310.     C = 0;
  311.     return(DISPLAY);
  312. }
  313.  
  314.  
  315. sec(junk)
  316. char    *junk;
  317. {
  318.     C = 1;
  319.     return(DISPLAY);
  320. }
  321.  
  322.  
  323. sev(junk)
  324. char    *junk;
  325. {
  326.     V = 1;
  327.     return(DISPLAY);
  328. }
  329.  
  330.  
  331. clv(junk)
  332. char    *junk;
  333. {
  334.     V = 0;
  335.     return(DISPLAY);
  336. }
  337.  
  338.  
  339. sed(junk)
  340. char    *junk;
  341. {
  342.     D = 1;
  343.     return(DISPLAY);
  344. }
  345.  
  346.  
  347. cld(junk)
  348. char    *junk;
  349. {
  350.     D = 0;
  351.     return(DISPLAY);
  352. }
  353.  
  354.  
  355. sei(junk)
  356. char    *junk;
  357. {
  358.     I = 1;
  359.     return(DISPLAY);
  360. }
  361.  
  362.  
  363. clri(junk)
  364. char    *junk;
  365. {
  366.     I = 0;
  367.     return(DISPLAY);
  368. }
  369.  
  370.  
  371. sen(junk)
  372. char    *junk;
  373. {
  374.     N = 1;
  375.     return(DISPLAY);
  376. }
  377.  
  378.  
  379. cln(junk)
  380. char    *junk;
  381. {
  382.     N = 0;
  383.     return(DISPLAY);
  384. }
  385.  
  386.  
  387. sez(junk)
  388. char    *junk;
  389. {
  390.     NZ = 0;
  391.     return(DISPLAY);
  392. }
  393.  
  394.  
  395. clz(junk)
  396. char    *junk;
  397. {
  398.     NZ = 1;
  399.     return(DISPLAY);
  400. }
  401.  
  402.  
  403. quit_emulator(junk)
  404. char    *junk;
  405. {
  406.     exit(0);
  407. }
  408.  
  409.  
  410.  
  411. ver(junk)
  412. char    *junk;
  413. {
  414.     printf("a2 - Apple II emulator  (c) Copyright 1990 by Rich Skrenta & Tom Markson\n");
  415.     return(OK);
  416. }
  417.  
  418.  
  419. refresh(junk)
  420. char    *junk;
  421. {
  422.  
  423.     in_cli = FALSE;
  424.     return(OK);
  425. }
  426.  
  427.  
  428. shell_escape(rest)
  429. char    *rest;
  430. {
  431.     char    line[100];
  432.     char *s;
  433.  
  434.     s = getenv("SHELL");
  435.     if (s == NULL)
  436.         s = "/bin/sh";
  437.  
  438.     strcpy(line, s);
  439.  
  440.     if (*rest != '\0') {
  441.         strcat(line, " -c '");
  442.         strcat(line, rest);
  443.         strcat(line, "'");
  444.     }
  445.     system(line);
  446.  
  447.     printf("\n");
  448.     return(OK);
  449. }
  450.  
  451.  
  452. do_soft_reset(rest)
  453. char    *rest;
  454. {
  455.  
  456.     Pc = mem[0xFFFC] | (mem[0xFFFD] << 8);
  457.     return(DISPLAY);
  458. }
  459.  
  460.  
  461. do_bload(rest)
  462. char    *rest;
  463. {
  464.     char    *first;
  465.     char    *file;
  466.     unsigned short    start;
  467.     long    foo;
  468.  
  469.     file = rest;
  470.     rest = split(rest);
  471.     first = rest;
  472.     rest = split(rest);
  473.     foo = get_hex_number(first);
  474.     if (foo == -1) {
  475.         printf("usage: bload file hex-address\n");
  476.         return(OK);
  477.     }
  478.     start = (unsigned int) foo;
  479.     bload(file, start);
  480.  
  481.     return(OK);
  482. }
  483.  
  484.  
  485. do_bsave(rest)
  486. char    *rest;
  487. {
  488.     char    *startc, *sizec, *file;
  489.     unsigned short    start, size;
  490.     long    istart, iend;
  491.     file = rest;
  492.     rest = split(rest);
  493.     startc = rest;
  494.     rest = split(rest);
  495.     sizec = rest;
  496.     rest = split(rest);
  497.     istart = get_hex_number(startc);
  498.     iend = get_hex_number(sizec);
  499.     if ((istart == -1) || (iend == -1))
  500.         printf("usage: bsave file hex-address hex-length\n");
  501.     else {
  502.         start = (unsigned short) istart;
  503.         size  = (unsigned short) iend;
  504.         bsave(file, start, size);
  505.     }
  506.  
  507.     return(OK);
  508. }
  509.  
  510.  
  511.  
  512. show_point(rest)
  513. char    *rest;
  514. {
  515.  
  516.     lpoint = Pc;
  517.     return(DISPLAY);
  518. }
  519.  
  520.  
  521. hack(rest)
  522. char *rest;
  523. {
  524. extern int cur_track;
  525.  
  526.     cur_track = get_hex_number(rest);
  527.     return(OK);
  528. }
  529.  
  530.  
  531. do_jump(rest)
  532. char    *rest;
  533. {
  534.     char    *start;
  535.     long    istart;
  536.     start = rest;
  537.     rest = split(rest);
  538.     istart = get_hex_number(start);
  539.  
  540.     if (istart == -1) {
  541.         printf("usage: jmp <hex address>\n");
  542.         return(OK);
  543.     } else {
  544.         Pc = istart & 0xFFFF;
  545.         return(DISPLAY);
  546.     }
  547. }
  548.  
  549.  
  550.  
  551. trace(rest)
  552. char    *rest;
  553. {
  554.     char    *addr1, *addr2, *file;
  555.     long    addr1i, addr2i;
  556.  
  557.     addr1 = rest;
  558.     rest = split(rest);
  559.     addr2 = rest;
  560.     rest = split(rest);
  561.     file = rest;
  562.     rest = split(rest);
  563.     addr1i = get_hex_number(addr1);
  564.     addr2i = get_hex_number(addr2);
  565.     if (addr1i == -1 && addr2i == -1) {
  566.         if (trace_lo == -1)
  567.             printf("No trace region set\n");
  568.         else
  569.             printf("Tracing between $%.4X and $%.4x\n",
  570.                             trace_lo, trace_hi);
  571.         return(OK);
  572.     }
  573.  
  574.     if (addr1i == -1 || addr2i == -1) {
  575.         printf("usage: trace [low high]\n");
  576.         return(OK);
  577.     }
  578.  
  579.     if (logging_fp == NULL) {
  580.         if (*file == '\0' || file == NULL) {
  581.             printf("Trace log will go to file 'trace'.\n");
  582.             file = "trace";
  583.         }
  584.         logging_fp = fopen(file, "w");
  585.         if (logging_fp == NULL) {
  586.             perror("can't open trace file");
  587.             trace_lo = -1;
  588.             return(OK);
  589.         }
  590.     }
  591.  
  592.     trace_lo = addr1i & 0xFFFF;
  593.     trace_hi = addr2i & 0xFFFF;
  594.  
  595.     return(OK);
  596. }
  597.  
  598.  
  599. ldx(rest)
  600. char    *rest;
  601. {
  602.     long    number;
  603.     char    *first;
  604.  
  605.     first = rest;
  606.     rest = split(rest);
  607.     number = get_hex_number(first);
  608.  
  609.     number &= 0xFF;
  610.     if (number < 0) {
  611.         printf("usage: ldx <hex number>\n");
  612.         return(OK);
  613.     }
  614.  
  615.     X = number & 0xFF;
  616.     return(DISPLAY);
  617. }
  618.  
  619.  
  620. ldy(rest)
  621. char    *rest;
  622. {
  623.     long    number;
  624.     char    *first;
  625.     first = rest;
  626.     rest = split(rest);
  627.     number = get_hex_number(first);
  628.  
  629.     if (number < 0) {
  630.         printf("usage: ldy <hex number>\n");
  631.         return(OK);
  632.     }
  633.  
  634.     Y = number & 0xFF;
  635.     return(DISPLAY);
  636. }
  637.  
  638.  
  639. lda(rest)
  640. char    *rest;
  641. {
  642.     long    number;
  643.     char    *first;
  644.     first = rest;
  645.     rest = split(rest);
  646.     number = get_hex_number(first);
  647.     if (number < 0) {
  648.         printf("usage: lda <hex number>\n");
  649.         return(OK);
  650.     }
  651.  
  652.     A = number & 0xFF;
  653.     return(DISPLAY);
  654. }
  655.  
  656.  
  657. lds(rest)
  658. char    *rest;
  659. {
  660.     long    number;
  661.     char    *first;
  662.     first = rest;
  663.     rest = split(rest);
  664.     number = get_hex_number(first);
  665.     if (number < 0) {
  666.         printf("usage: lds <hex number>\n");
  667.         return(OK);
  668.     }
  669.  
  670.     Sp = number & 0xFF;
  671.     return(DISPLAY);
  672. }
  673.  
  674.  
  675. set_break_point(rest)
  676. char    *rest;
  677. {    
  678.     long    addr;
  679.     char    *first;
  680.     first = rest;
  681.     rest = split(rest);
  682.     addr = get_hex_number(first);
  683.     if (addr == -1)
  684.         if (breakpoint == -1)
  685.             printf("no breakpoint set\n");
  686.             else
  687.             printf("break point set at %x\n",
  688.                 (unsigned short)breakpoint);
  689.             else
  690.         breakpoint = addr;
  691.     running = FALSE;
  692.     return(OK);
  693. }
  694.  
  695.  
  696. clear_break_point(rest)
  697. char    *rest;
  698. {
  699.     breakpoint = -1;
  700.     return(OK);
  701. }
  702.  
  703.  
  704. notrace(junk)
  705. char    *junk;
  706. {
  707.  
  708.     trace_lo = -1;
  709.     if (logging_fp == NULL)
  710.         return(OK);
  711.     else
  712.         fclose(logging_fp);
  713.     logging_fp = NULL;
  714.     return(OK);
  715. }
  716.  
  717.  
  718. insert_disk(rest)
  719. char    *rest;
  720. {
  721.     char    *name;
  722.     char    *which;
  723.     int    fd;
  724.     int    read_only = 0;
  725.  
  726.     name = rest;
  727.     rest = split(rest);
  728.     which = rest;
  729.     rest = split(rest);
  730.  
  731.     if (name == NULL || *name == '\0') {
  732.         printf("usage: insert <file name> [drive]\n");
  733.         return(OK);
  734.     }
  735.  
  736.     fd = open(name, 2);        /* attempt open for read/write */
  737.     if (fd >= 0)
  738.         read_only = 0;
  739.     else  {                /* attempt open read only */
  740.         read_only = 1;
  741.         fd = open(name, 0);
  742.     }
  743.     if (fd < 0) {
  744.         fprintf(stderr, "can't open %s: ", name);
  745.         perror("");
  746.         return(OK);
  747.     }
  748.  
  749.     if (*which == '2')
  750.         drive = 1;
  751.     else
  752.         drive = 0;
  753.  
  754.     if (disk[drive] >= 0)
  755.         close(disk[drive]);
  756.  
  757.     strcpy(diskname[drive], name);
  758.  
  759.     disk[drive] = fd;
  760.     write_prot[drive] = read_only;
  761.  
  762.     printf("disk %d inserted, %swrite protected\n", drive + 1,
  763.                 read_only ? "" : "not ");
  764.  
  765.     return(OK);
  766. }
  767.  
  768.  
  769. dissassemble(rest)
  770. char *rest;
  771. {
  772.     unsigned short start,end;
  773.     long istart;
  774.     long iend;
  775.     int count = 0;
  776.     char *first,*last;
  777.  
  778.     first = rest;
  779.     rest = split(rest);
  780.     last = rest;
  781.     rest = split(rest);
  782.  
  783.     istart = get_hex_number(first);
  784.     iend   = get_hex_number(last);
  785.     if (istart != -1)
  786.         lpoint = istart;
  787.     if (iend == -1)
  788.         iend=65537;
  789.     while ( (long) lpoint < iend) {
  790.         lpoint += diss(lpoint, stdout);
  791.         printf("\n");
  792.         count++;
  793.         if (iend == 65537)
  794.             if (count > term_lines-3)
  795.                 break;
  796.     }
  797.     return OK;
  798. }
  799.  
  800. ascii_dump(l,h)
  801. unsigned short l,h;
  802. {
  803.     while (l < h) {
  804.         if (isprint(mem[l]))
  805.             printf("%c",mem[l]);
  806.         else 
  807.             printf(".");
  808.         l++;
  809.     }
  810. }
  811.  
  812. hex_dump(rest)
  813. char *rest;
  814. {
  815.     char *start,*end;
  816.     unsigned short last, addr,oaddr;
  817.     long iaddr1,iaddr2;
  818.     int count;
  819.  
  820.     start = rest;
  821.     rest = split(rest);
  822.     end = rest;
  823.     rest = split(rest);
  824.     iaddr1 = get_hex_number( start );
  825.     iaddr2 = get_hex_number( end );
  826.  
  827.     if (iaddr2 != -1 && iaddr1 > iaddr2)
  828.         return(OK);
  829.  
  830.     if (iaddr1 != -1)
  831.         lpoint = (unsigned short) iaddr1;
  832.     if (iaddr2 == -1)
  833.         last = lpoint + 1;
  834.     else
  835.         last = (unsigned short) iaddr2 + 1;
  836.  
  837.     last &= 0xFFFF;
  838.  
  839.     addr = lpoint;
  840.     count = 0;
  841.     printf("%.4X:  ", addr);
  842.     oaddr = addr;
  843.     do {
  844.         if (count % 16 == 0 && count != 0) {
  845.             ascii_dump(oaddr,addr);
  846.             oaddr = addr;
  847.             printf("\n%.4X:  ", addr);
  848.         }
  849.         printf("%.2X ", mem[addr]);
  850.         addr++;
  851.         count++;
  852.     } while (addr != last);
  853.     while ((count % 16) != 0) {
  854.         printf("   ");  /* 3 spaces dd_ */
  855.         count++;
  856.     }
  857.     ascii_dump(oaddr,addr);
  858.     printf("\n");
  859.     return(OK);
  860. }
  861.  
  862. deposit(rest)
  863. char *rest;
  864. {
  865.     char *addr;
  866.     char *value;
  867.     unsigned short location;
  868.     long iloc;
  869.     unsigned char val;
  870.     int fired_once;
  871.  
  872.     addr = rest;
  873.     rest = split(rest);
  874.     fired_once = 0;
  875.     iloc = get_hex_number(addr);
  876.     if (iloc == -1) {
  877.         printf("usage: deposit <addr> <value> [<value>...]\n");
  878.         return(OK);
  879.     }
  880.  
  881.     location = (unsigned short) iloc;
  882.     do {
  883.         value = rest;
  884.         rest = split(rest);
  885.         val = get_hex_number(value);
  886.         if (val == -1) {
  887.             if (!fired_once)
  888.                 printf("Invalid or Missing Hex address\n");
  889.             return OK;
  890.         }
  891.         mem[location++] = val;
  892.         fired_once = 1;
  893.     } while (*rest != '\0');
  894.  
  895.     return(OK);
  896. }
  897.  
  898. phantom_trace(rest)
  899. char *rest;
  900. {
  901.     char *phantoms;
  902.     char *addr1s;
  903.     char *addr2s;
  904.     char *file;
  905.     long  phantom;
  906.     long low_val,high_val;
  907.     int err = 0;
  908.  
  909.     phantoms = rest;
  910.     rest = split(rest);
  911.     addr1s = rest;
  912.     rest = split(rest);
  913.     addr2s = rest;
  914.     rest = split(rest);
  915.     file = rest;
  916.     rest = split(rest);
  917.  
  918.     phantom = (unsigned short)get_hex_number(phantoms);
  919.     low_val = get_hex_number(addr1s);
  920.     high_val = get_hex_number(addr2s);
  921.     if (*phantoms == '\0') {
  922.         if (phantom_location == -1) {
  923.             printf("The phantom sleeps.");
  924.             if (trace_lo != -1 && trace_hi != -1)
  925.                 printf("however, a trace is active.");
  926.             printf("\n");
  927.         } else 
  928.         printf("the phantom waits until Pc = %.4X and then traces from %.4X to %.4X\n",phantom_location,trace_lo,trace_hi);
  929.         return(OK);
  930.     }
  931.     if (low_val == -1 || high_val == -1 || phantom == -1) {
  932.         printf("usage: phantom <addr> <addr> <addr> [file]\n");
  933.         return OK;
  934.     } phantom_location = phantom; trace_lo = low_val; trace_hi = high_val; if (logging_fp == NULL) {
  935.         if (*file == '\0' || file == NULL) {
  936.             printf("the phantom will trace to file 'trace'.\n");
  937.             file = "trace";
  938.         }
  939.         logging_fp = fopen(file, "w");
  940.         if (logging_fp == NULL) {
  941.             perror("can't open trace file");
  942.             trace_lo = -1;
  943.             return(OK);
  944.         }
  945.     }
  946.     return OK;
  947. }
  948.  
  949. no_phantom_trace(rest)
  950. char *rest;
  951. {
  952.     phantom_location = -1;
  953.     trace_lo = -1;
  954.     printf("the phantom goes to sleep.\n");
  955.     if (logging_fp == NULL)
  956.         return OK;
  957.     fclose(logging_fp);
  958.     logging_fp = NULL;
  959.     return OK;
  960. }
  961.  
  962. cd(rest)
  963. char *rest;
  964. {
  965.  
  966.     char *first;
  967.     char path[200];
  968.  
  969.     first = rest;
  970.     rest = split(rest);
  971.     if (*first != '\0') {
  972.         if (chdir(first)) {
  973.             perror("cd");
  974.             printf("CWD remains ");
  975.         }
  976.     }
  977.     printf("%s\n",getcwd(path,198));
  978.     return OK;
  979. }
  980.  
  981. map(rest)
  982. char *rest;
  983. {
  984.     map_to_upper = !map_to_upper;
  985.     printf("Uppercase Mapping is %s\n",(map_to_upper)?"On":"Off");
  986.     return OK;
  987. }
  988.  
  989. sex(rest)
  990. char *rest;
  991. {
  992.     printf("You'll need a real Apple for that sort of thing\n");
  993.     return OK;
  994. }
  995.  
  996.  
  997. help(rest)
  998. char *rest;
  999. {
  1000.     printf("![command]        Escape to Unix\n");
  1001.     printf(".            Display Current Pc Point\n");
  1002.     printf("bload file addr        load binary file into mem at addr\n");
  1003.     printf("breakpoint [addr]    Set the Breakpoint to addr\n");
  1004.     printf("bsave file start end    Save Memory from start to end in file\n");
  1005.     printf("cd [directory]        Set/Show Current Working Directory\n");
  1006.     printf("cl[cdinvz]        Clear appropriate Status Bit\n");
  1007.     printf("continue        Resume Execution of Emulator\n");
  1008.     printf("deposit addr [val]+    Put val(s) into addr\n");
  1009.     printf("dup [l|p]        duplicate top of stack into l or p\n");
  1010.     printf("escape char        set escape char to be char \n");
  1011.     printf("examine addr        Display Value in addr\n");
  1012.     printf("insert file drive#    Make file disk in drive#\n");
  1013.     printf("jmp addr        Make Pc=addr\n");
  1014.     printf("ld[asxy] val        Load Register with val\n");
  1015.     printf("list [addr] [addr]    Dissassemble at point or addr\n");
  1016.     printf("map            Toggle lower -> upper case mapping\n");
  1017.     printf("nobreak            Turn off breakpoint\n");
  1018.     printf("pop [l|p]        get p or l from top of stack\n");
  1019.     printf("push [l|p|<addr>    push l,p, or hex addr on stack\n");
  1020.     printf("reset            Pc = Apple Reset Vector\n");
  1021.     printf("se[cdinvz]        Set appropriate Status Flag\n");
  1022.     printf("trace [addr] [addr]    Trace Between addresses/display trace point\n");
  1023.     return OK;
  1024. }
  1025.  
  1026. set_escape_char(rest)
  1027. char *rest;
  1028. {
  1029.     char c;
  1030.     if (*rest != '\0')
  1031.         escape_char = *rest;
  1032.     printf("escape character is ");
  1033.     if (isprint(escape_char))
  1034.         printf("%c",(int)escape_char);
  1035.     else 
  1036.         printf("^%c",(char)escape_char+64);
  1037.     printf(" (0x%.2X)",(int)escape_char);
  1038.     printf("\n");
  1039.     return(OK);
  1040. }
  1041.  
  1042. disk_names(rest)
  1043. char *rest;
  1044. {
  1045.  
  1046.     printf("drive 1: %s\n", disk[0] >= 0 ? diskname[0] : "empty");
  1047.     printf("drive 2: %s\n", disk[1] >= 0 ? diskname[1] : "empty");
  1048.     return(OK);
  1049. }
  1050. @EOF
  1051.  
  1052. chmod 644 commands.c
  1053.  
  1054. echo x - dos.c
  1055. cat >dos.c <<'@EOF'
  1056. /*
  1057.  *  a2, an Apple II emulator in C
  1058.  *  (c) Copyright 1990 by Rich Skrenta
  1059.  *
  1060.  *  Command line interface written by Tom Markson
  1061.  *
  1062.  *  Distribution agreement:
  1063.  *
  1064.  *    You may freely copy or redistribute this software, so long
  1065.  *    as there is no profit made from its use, sale, trade or
  1066.  *    reproduction.  You may not change this copyright notice,
  1067.  *    and it must be included prominently in any copy made.
  1068.  *
  1069.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  1070.  *                    skrenta@blekko.uucp
  1071.  */
  1072.  
  1073.  
  1074. #include    <stdio.h>
  1075. #include    "a2.h"
  1076.  
  1077.  
  1078.  
  1079. char *rwts_func[] = {"-s", "", "-w", "-?", "-f"};
  1080.  
  1081.  
  1082. rwts() {
  1083. char s[50];
  1084. unsigned short iob;
  1085. unsigned short buf;
  1086. int track;
  1087. int sector;
  1088. int cmd;
  1089. char zero_buf[256];
  1090. int i;
  1091.  
  1092.     mem[0x48] = Y;
  1093.     mem[0x49] = A;
  1094.     mem[0x6F8] = 2;
  1095.     mem[0x4F8] = 4;
  1096.  
  1097.     iob = join(Y, A);
  1098.  
  1099.     track = mem[iob + 4];
  1100.     sector = mem[iob + 5];
  1101.     buf = join(mem[iob + 8], mem[iob + 9]);
  1102.     cmd = mem[iob + 12];
  1103.  
  1104.     if (cmd > 4)
  1105.         cmd = 3;        /* unknown command */
  1106.  
  1107.     if (mem[iob + 2] == 2)
  1108.         drive = 1;
  1109.     else
  1110.         drive = 0;
  1111.  
  1112.     if ((cmd == 2 || cmd == 4) && write_prot[drive]) {
  1113.         C = 1;
  1114.         mem[iob + 13] = 0x10;        /* Write protected */
  1115.         DO_RTS;
  1116.         return;
  1117.     }
  1118.  
  1119.     if (mem[iob] != 1
  1120.     ||  disk[drive] < 0
  1121.     ||  track > 35
  1122.     ||  sector > 15
  1123.     ||  cmd == 3
  1124.     ||  buf > 0xFE00) {
  1125.         C = 1;
  1126.         mem[iob + 13] = 0x40;        /* IO Error */
  1127.         DO_RTS;
  1128.         return;
  1129.     }
  1130.  
  1131.     sprintf(s, "rwts%s t=%d s=%d%s", rwts_func[cmd],
  1132.                 track, sector, drive ? " d2" : "");
  1133.     info(s);
  1134.  
  1135.     switch (cmd) {
  1136.     case 0:                    /* seek */
  1137.         break;
  1138.  
  1139.     case 1:                    /* read */
  1140.         read_disk(track, sector, &mem[buf]);
  1141.         break;
  1142.  
  1143.     case 2:                    /* write */
  1144.         write_disk(track, sector, &mem[buf]);
  1145.         break;
  1146.  
  1147.     case 4:                    /* format */
  1148.         for (i = 0; i < 256; i++)
  1149.             zero_buf[i] = 0;
  1150.  
  1151.         for (track = 0; track < 35; track++)
  1152.             for (sector = 0; sector < 16; sector++)
  1153.                 write_disk(track, sector, zero_buf);
  1154.         break;
  1155.     }
  1156.  
  1157.     C = 0;
  1158.     A = 0;
  1159.     DO_RTS;
  1160. }
  1161.  
  1162. @EOF
  1163.  
  1164. chmod 644 dos.c
  1165.  
  1166. echo x - hex.c
  1167. cat >hex.c <<'@EOF'
  1168.  
  1169. /*
  1170.  *  Turn an Apple II monitor ROM hex dump back into binary data
  1171.  *    usage:  hex < hex_data > bin_data
  1172.  */
  1173.  
  1174.  
  1175. #include    <stdio.h>
  1176.  
  1177. main() {
  1178. char buf[100];
  1179. int i, j;
  1180. int addr;
  1181. int m[8];
  1182. unsigned char c;
  1183.  
  1184.     while (fgets(buf, 100, stdin) != NULL) {
  1185.         i = sscanf(buf, "%x- %x %x %x %x %x %x %x %x",
  1186.             &addr, &m[0], &m[1], &m[2], &m[3], &m[4], &m[5],
  1187.                         &m[6], &m[7]);
  1188.  
  1189.         for (j = 1; j < i; j++) {
  1190.             c = m[j - 1];
  1191.             write(1, &c, 1);
  1192.         }
  1193.     }
  1194. }
  1195.  
  1196. @EOF
  1197.  
  1198. chmod 644 hex.c
  1199.  
  1200. echo x - jump.c
  1201. cat >jump.c <<'@EOF'
  1202. /*
  1203.  *  a2, an Apple II emulator in C
  1204.  *  (c) Copyright 1990 by Rich Skrenta
  1205.  *
  1206.  *  Command line interface written by Tom Markson
  1207.  *
  1208.  *  Distribution agreement:
  1209.  *
  1210.  *    You may freely copy or redistribute this software, so long
  1211.  *    as there is no profit made from its use, sale, trade or
  1212.  *    reproduction.  You may not change this copyright notice,
  1213.  *    and it must be included prominently in any copy made.
  1214.  *
  1215.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  1216.  *                    skrenta@blekko.uucp
  1217.  */
  1218.  
  1219.  
  1220. #include    <stdio.h>
  1221. #include    <fcntl.h>
  1222. #include    "a2.h"
  1223.  
  1224. #define        jump_check(a,b,c,d)    (mem[Pc]==a && mem[Pc+1]==b && mem[Pc+2]==c && mem[Pc+3]==d)
  1225.  
  1226. /*
  1227.  *  In order to improve performance, we intercept the PC on JSR's
  1228.  *  and JMP's to certain locations and handled the intented function
  1229.  *  in C instead of letting the emulator interpret 6502.
  1230.  *
  1231.  *  This is done for video output, to produce an acceptable scroll;
  1232.  *  for the boot prom, so it crashes if there is no disk in the drive;
  1233.  *  and for other miscellaneous routines such as WAIT for speed.
  1234.  *
  1235.  *  In most cases the interceptor routine checks to see if the code it's
  1236.  *  intercepting looks like what it thinks should be there; it doesn't
  1237.  *  snatch the PC if the first four bytes of the routine don't match.
  1238.  */
  1239.  
  1240.  
  1241. #define        I_WAIT        1    /* defeat ROM WAIT routine           */
  1242. #define        I_PRODOS    2    /* Prodos high level intercept       */
  1243. #define        I_RWTS        3    /* DOS 3.3 high-level intercept      */
  1244. #define        I_BELL        4    /* don't toggle C030, output a bell  */
  1245. #define        I_VIDOUT    5    /* speeds up scrolling tremendously  */
  1246. #define        I_BOOT        6    /* crash if no disk on boot          */
  1247. #define        I_BOOTWAIT    7    /* defeat delay loops in DOS boot    */
  1248. #define        I_BOOTPATCH    8    /* patch dos for fast raw access     */
  1249.  
  1250.  
  1251. extern int map_to_upper;
  1252. extern unsigned char disk_ref();
  1253.  
  1254.  
  1255. set_special_jumps() {
  1256. extern int set_c0();
  1257. extern int set_writep();
  1258.  
  1259.     mem[0x43] = 0x60;            /* for ProDos boot */
  1260.  
  1261.     jmp_tbl[0xBD00] = I_RWTS;
  1262.     jmp_tbl[0xC600] = I_BOOT;
  1263.     jmp_tbl[0xC680] = I_PRODOS;    /* patched into boot prom below */
  1264.     jmp_tbl[0x9D84] = I_BOOTPATCH;    /* fast raw dos access */
  1265.     jmp_tbl[0xFBD9] = I_BELL;
  1266.     jmp_tbl[0xFBFD] = I_VIDOUT;
  1267.     jmp_tbl[0xFCA8] = I_WAIT;
  1268.  
  1269.     jmp_tbl[0x3A00] = I_BOOTWAIT;
  1270.  
  1271.     mem_set[0xC0] = set_c0;
  1272.     mem_set[0xC6] = set_writep;    /* write protect disk prom */
  1273.  
  1274. #if 0
  1275.     mem[0xC600] = 0;        /* flag for boot interception */
  1276.     mem[0xC601] = 0x20;        /* disk prom magic number */
  1277.     mem[0xC603] = 0x00;
  1278.     mem[0xC605] = 0x03;
  1279.     mem[0xC607] = 0x3C;
  1280. #endif
  1281.  
  1282. /*
  1283.  *  Patch boot rom for fake Prodos driver
  1284.  */
  1285.  
  1286.     mem[0xC6FF] = 0x80;        /* C680 is driver address */
  1287.     mem[0xC6FE] = 0x1F;        /* info about device */
  1288.  
  1289.     screen_setup();
  1290. }
  1291.  
  1292.  
  1293. jump(key)
  1294. int key;
  1295. {
  1296. int i;
  1297.  
  1298.     switch (key) {
  1299.     case I_WAIT:                    /* FCA8 */
  1300.         if (jump_check(0x38, 0x48, 0xE9, 0x01)) {
  1301.             A = 0;
  1302.             N = 0;
  1303.             V = 0;
  1304.             C = 1;
  1305.             DO_RTS;
  1306.         }
  1307.         break;
  1308.  
  1309.     case I_PRODOS:                    /* C680 */
  1310.         prodos();
  1311.         break;
  1312.  
  1313.     case I_RWTS:                    /* BD00 */
  1314.         if (jump_check(0x84, 0x48, 0x85, 0x49))
  1315.             rwts();
  1316.         break;
  1317.  
  1318.     case I_BELL:                    /* FBD9 */
  1319.         if (jump_check(0x60, 0x87, 0xD0, 0x12)) {
  1320.             putchar(7);
  1321.             fflush(stdout);
  1322.             DO_RTS;
  1323.         }
  1324.         break;
  1325.  
  1326.     case I_VIDOUT:                    /* FBFD */
  1327.         if (jump_check(0xC9, 0xA0, 0xB0, 0xEF))
  1328.             vidout();
  1329.         break;
  1330.  
  1331.     case I_BOOT:                    /* C600 */
  1332.         if (disk[0] < 0) {
  1333.             info("boot: no disk");
  1334.             PCINC;            /* BRK into the monitor */
  1335.             push(high(Pc));
  1336.             push(low(Pc));
  1337.             B = 1;
  1338.             push(get_status());
  1339.             Pc = mem[0xFFFE] | (mem[0xFFFF] << 8);
  1340.             return;
  1341.         }
  1342.         info("boot");
  1343.  
  1344. /* 
  1345.  *  We read the second half of a 512 byte block in case we're
  1346.  *  booting something that depends on this being a newer boot prom
  1347.  */
  1348.  
  1349.         drive = 0;
  1350.         read_disk(0, 14, &mem[0x900]);
  1351.         break;
  1352.  
  1353. /*
  1354.  *  Standard DOS 3.3 has some pretty gross delay loops in its
  1355.  *  boot code.  The following patches defeat two of them.
  1356.  *  This could be dangerous; it seems to work, but DOS's original
  1357.  *  side effects are not maintained.  Comment out the jmp_tbl assignment
  1358.  *  of I_BOOTWAIT above if you are distrustful.
  1359.  *
  1360.  *  Interesting.  Dos relocates the patches when it moves into higher
  1361.  *  memory.  If you boot with a fast-booting dos that doesn't have the
  1362.  *  delays at 3A00, but still has them at BA00 & BD9E when it starts
  1363.  *  up, it will be slow if you turn off RWTS interception and use the
  1364.  *  raw interface.  However, slow-booting real DOS that gets patched
  1365.  *  while it's booting will have a faster raw interface, since it
  1366.  *  relocated the patches...
  1367.  */
  1368.  
  1369.     case I_BOOTWAIT:                /* 3A00 */
  1370.         if (jump_check(0xA2, 0x11, 0xCA, 0xD0)) {
  1371.             mem[0x3A00] = 0x60;        /* RTS */
  1372.             if (mem[0x3D9E] == 0xA0
  1373.             &&  mem[0x3D9F] == 0x12
  1374.             &&  mem[0x3DA0] == 0x88) {
  1375.                 mem[0x3D9E] = 0x4C;    /* JMP past it */
  1376.                 mem[0x3D9F] = 0xAB;
  1377.                 mem[0x3DA0] = 0x3D;    /* gets relocated */
  1378.             }
  1379.         }
  1380.         break;
  1381.  
  1382. /*
  1383.  *  This one is unnecessary since we do high-level RWTS interception
  1384.  */
  1385.  
  1386.     case I_BOOTPATCH:                /* 9D84 */
  1387.         if (jump_check(0xAD, 0xE9, 0xB7, 0x4A)) {
  1388.             if (mem[0xBA00] == 0xA2
  1389.             &&  mem[0xBA01] == 0x11
  1390.             &&  mem[0xBA02] == 0xCA) {
  1391.                 mem[0xBA00] = 0x60;        /* RTS */
  1392.                 if (mem[0xBD9E] == 0xA0
  1393.                 &&  mem[0xBD9F] == 0x12
  1394.                 &&  mem[0xBDA0] == 0x88) {
  1395.                     mem[0xBD9E] = 0x4C;
  1396.                     mem[0xBD9F] = 0xAB;
  1397.                     mem[0xBDA0] = 0xBD;
  1398.                 }
  1399.             }
  1400.         }
  1401.         break;
  1402.  
  1403.     default:
  1404.         fprintf(stderr, "bad jump intercept key: %d\n", key);
  1405.         assert(FALSE);
  1406.     }
  1407. }
  1408.  
  1409.  
  1410. static int key_clear = TRUE;
  1411. static unsigned char last_key = 0;
  1412. static unsigned char temp_key;
  1413.  
  1414. extern int save_flags;
  1415.  
  1416. unsigned char
  1417. mem_map(a)
  1418. unsigned short a;
  1419. {
  1420.  
  1421.     switch (a) {
  1422.     case 0xC000:
  1423.         if (key_clear) {
  1424.             fcntl (0, F_SETFL, save_flags | O_NDELAY);
  1425.       
  1426.             if (read (0, &temp_key, 1) == 1) {
  1427.                 key_clear = FALSE;
  1428.                 if (temp_key == '\n')
  1429.                     temp_key = '\r';
  1430.                 else if (temp_key == 127)
  1431.                     temp_key = 8;
  1432.                 if (map_to_upper)
  1433.                     temp_key = toupper(temp_key);
  1434.                 last_key = temp_key | 0x80;
  1435.             }
  1436.       
  1437.             fcntl (0, F_SETFL, save_flags);
  1438.         }
  1439.         return(last_key);
  1440.  
  1441.     case 0xC010:
  1442.         key_clear = TRUE;
  1443.         last_key &= 0x7F;
  1444.         return(0);            /* what should this be? */
  1445.  
  1446.     case 0xC011:
  1447.         if (bank2_enable)
  1448.             return(0xFF);
  1449.         return(0x00);
  1450.  
  1451.     case 0xC012:
  1452.         if (ram_read)
  1453.             return(0xFF);
  1454.         return(0x00);
  1455.  
  1456.     case 0xC080: case 0xC081: case 0xC082: case 0xC083:
  1457.     case 0xC088: case 0xC089: case 0xC08A: case 0xC08B:
  1458.         ram_card(a);
  1459.         return(0x00);
  1460.  
  1461. /*
  1462.  *  Slot 6 Disk II memory map 
  1463.  */
  1464.  
  1465.     case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
  1466.     case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
  1467.     case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
  1468.     case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
  1469.         return( disk_ref(a, 0) );
  1470.  
  1471. #if 0
  1472. /*
  1473.  *  Keep the boot prom magic number from appearing if there is
  1474.  *  no disk in the drive
  1475.  */
  1476.  
  1477.     case 0xC600:
  1478.     case 0xC601:
  1479.         if (disk[0] < 0)
  1480.             return(0);
  1481.         break;
  1482. #endif
  1483.  
  1484.     }
  1485.  
  1486.     return(mem[a]);        /* default */
  1487. }
  1488.  
  1489.  
  1490. set_c0(a, n)
  1491. unsigned short a;
  1492. unsigned char n;
  1493. {
  1494.  
  1495.     switch (a & 0xFF) {
  1496.     case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15:
  1497.     case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B:
  1498.     case 0x1C: case 0x1D: case 0x1E: case 0x1F:
  1499.         key_clear = TRUE;
  1500.         last_key &= 0x7F;
  1501.         break;
  1502.  
  1503.     case 0x80: case 0x81: case 0x82: case 0x83:
  1504.     case 0x88: case 0x89: case 0x8A: case 0x8B:
  1505.         ram_card(a);
  1506.         break;
  1507.  
  1508. /*
  1509.  *  Slot 6 Disk II memory map 
  1510.  */
  1511.  
  1512.     case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
  1513.     case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
  1514.     case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
  1515.     case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
  1516.         disk_ref(a, n);
  1517.         break;
  1518.  
  1519.     default:
  1520.         mem[a] = n;
  1521.     }
  1522. }
  1523.  
  1524.  
  1525. @EOF
  1526.  
  1527. chmod 644 jump.c
  1528.  
  1529. echo x - main.c
  1530. cat >main.c <<'@EOF'
  1531. /*
  1532.  *  a2, an Apple II emulator in C
  1533.  *  (c) Copyright 1990 by Rich Skrenta
  1534.  *
  1535.  *  Command line interface written by Tom Markson
  1536.  *
  1537.  *  Distribution agreement:
  1538.  *
  1539.  *    You may freely copy or redistribute this software, so long
  1540.  *    as there is no profit made from its use, sale, trade or
  1541.  *    reproduction.  You may not change this copyright notice,
  1542.  *    and it must be included prominently in any copy made.
  1543.  *
  1544.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  1545.  *                    skrenta@blekko.uucp
  1546.  */
  1547.  
  1548.  
  1549.  
  1550. #include    <stdio.h>
  1551. #include    <signal.h>
  1552. #include    <fcntl.h>
  1553. #include    "a2.h"
  1554.  
  1555.  
  1556. int save_flags;            /* terminal flags */
  1557. char escape_char = '~';
  1558.  
  1559. unsigned short Pc;
  1560. unsigned char Sp = 0xFF;    /* stack pointer     */
  1561. unsigned int  A = 0;        /* accumulator        */
  1562. unsigned char X = 0;        /* X register        */
  1563. unsigned char Y = 0;        /* Y register        */
  1564.  
  1565. unsigned int N = 0;        /* 7 - sign        */
  1566. unsigned int V = 0;        /* 6 - Overflow        */
  1567.                 /* 5 - Unused        */
  1568. unsigned int B = 1;        /* 4 - Break        */
  1569. unsigned int D = 0;        /* 3 - Decimal        */
  1570. unsigned int I = 0;        /* 2 - Interrupt    */
  1571. unsigned int NZ = 1;        /* 1 - Zero        */
  1572. unsigned int C = 0;        /* 0 - Carry        */
  1573.  
  1574. int term_lines, term_cols;
  1575. int running = TRUE;
  1576. int tracing = FALSE;
  1577.  
  1578. int disk[] = {-1, -1};
  1579. int write_prot[2];
  1580. int drive = 0;
  1581.  
  1582.  
  1583. main(argc, argv)
  1584. int argc;
  1585. char **argv;
  1586. {
  1587. int c;
  1588. int errflag = 0;
  1589. char *f8rom, *d0rom;
  1590. int cli_first = FALSE;
  1591.  
  1592.     safety_check();
  1593.     f8rom = "AUTOSTART.ROM";
  1594.     d0rom = "APPLESOFT.ROM";
  1595.  
  1596.     while ((c = getopt(argc, argv, "cim")) != -1) {
  1597.         switch (c) {
  1598.         case 'c':
  1599.             cli_first = TRUE;
  1600.             break;
  1601.  
  1602.         case 'i':
  1603.             d0rom = "INTEGER.ROM";
  1604.             break;
  1605.  
  1606.         case 'm':
  1607.             f8rom = "MONITOR.ROM";
  1608.             break;
  1609.  
  1610.         case '?':
  1611.         default:
  1612.             errflag++;
  1613.         }
  1614.     }
  1615.  
  1616.     if (errflag) {
  1617.         fprintf(stderr, "usage:  %s\n", argv[0]);
  1618. fprintf(stderr, "\t-m\tLoad MONITOR.ROM instead of AUTOSTART.ROM at $F800\n");
  1619. fprintf(stderr, "\t-i\tLoad INTEGER.ROM instead of APPLESOFT.ROM at $D000\n");
  1620. fprintf(stderr, "\t-c\tEnter command mode before executing any instructions\n");
  1621.         exit(1);
  1622.     }
  1623.  
  1624.     printf("a2 -- Apple II emulator.  Escape character is %c\n",
  1625.                                 escape_char);
  1626.  
  1627.     if (!bload(f8rom, 0xF800))
  1628.         exit(1);
  1629.     bload(d0rom, 0xD000);
  1630.     bload("DISK.PROM", 0xC600);
  1631.  
  1632.     if (!InitScreen())
  1633.         exit(1);
  1634.     ScreenSize(&term_lines, &term_cols);
  1635.  
  1636.     memory_setup();
  1637.     set_special_jumps();
  1638.     Pc = join(mem[0xFFFC], mem[0xFFFD]);
  1639.  
  1640.     if (cli_first)
  1641.         cli();
  1642.     else
  1643.         ClearScreen();
  1644.     while (1) {
  1645.         set_term();
  1646.         run();
  1647.         cli();
  1648.     }
  1649. }
  1650.  
  1651.  
  1652. restore_term() {
  1653.  
  1654. /*    SetNormal();                /* Turn off inverse video */
  1655.     Raw(FALSE);
  1656.     fcntl(0, F_SETFL, save_flags);
  1657.     signal(SIGINT, SIG_DFL);
  1658. }
  1659.  
  1660.  
  1661. set_term() {
  1662. int catch_intr();
  1663. int cleanup();
  1664.  
  1665.     signal(SIGINT, catch_intr);
  1666.     signal(SIGQUIT, cleanup);
  1667.     signal(SIGTERM, cleanup);
  1668.     save_flags = fcntl(0, F_GETFL, 0);
  1669.     Raw(TRUE);
  1670. }
  1671.  
  1672.  
  1673. cleanup() {
  1674.  
  1675.     restore_term();
  1676.     exit(0);
  1677. }
  1678.  
  1679.  
  1680. catch_intr() {
  1681.  
  1682.     signal(SIGINT, catch_intr);
  1683.     running = FALSE;
  1684.     tracing = FALSE;
  1685. }
  1686.  
  1687.  
  1688. bload(fnam, addr)
  1689. char *fnam;
  1690. unsigned short addr;
  1691. {
  1692. int fd;
  1693. long len;
  1694.  
  1695.     fd = open(fnam, O_RDONLY);
  1696.     if (fd < 0) {
  1697.         fprintf(stderr, "can't open %s: ", fnam);
  1698.         perror("");
  1699.         return(FALSE);
  1700.     }
  1701.  
  1702.     len = 65536 - addr;
  1703.  
  1704.     if (len == 65536) {        /* stupid $%!*&#~ 16 bit systems */
  1705.         if (read(fd, &mem[addr], 4096) < 0) {
  1706.             fprintf(stderr, "bad read of %s: ", fnam);
  1707.             perror("");
  1708.             return(FALSE);
  1709.         }
  1710.  
  1711.         addr += 4096;
  1712.         len -= 4096;
  1713.     }
  1714.  
  1715.     if (read(fd, &mem[addr], len) < 0) {
  1716.         fprintf(stderr, "bad read of %s: ", fnam);
  1717.         perror("");
  1718.         return(FALSE);
  1719.     }
  1720.  
  1721.     close(fd);
  1722.     return(TRUE);
  1723. }
  1724.  
  1725. bsave(fnam, addr, size)
  1726. char *fnam;
  1727. unsigned short addr,size;
  1728. {
  1729.     int fd;
  1730.     unsigned sizel;
  1731.     int x;
  1732.     sizel=size;
  1733.     if (sizel==0) sizel=65535;
  1734.     fd=open(fnam,O_WRONLY|O_CREAT,0644);
  1735.     if (fd < 0) {
  1736.         printf("can't open %s: ", fnam);
  1737.         perror("");
  1738.         return;
  1739.     }
  1740.     x=write(fd,&mem[addr],sizel);
  1741.     if (size == 0)
  1742.         x=write(fd,&mem[65535],1);
  1743.     if (x==-1) perror("write");
  1744.     close(fd);
  1745. }
  1746.  
  1747.  
  1748. /*
  1749.  *  I make certain assumptions about rollover so that I can do
  1750.  *  things like X++ and know that if X is 0xFF it will rollover
  1751.  *  to 0x00.  If I didn't know this I'd have to do X = (X+1) & 0xFF
  1752.  *  If your machine assert fails on the code below you'll have to
  1753.  *  rewrite the code that depends on rollover
  1754.  */
  1755.  
  1756. safety_check() {
  1757. unsigned char c;
  1758. unsigned short s;
  1759.  
  1760.     c = 0xFF;
  1761.     assert(++c == 0x00);
  1762.     assert(--c == 0xFF);
  1763.  
  1764.     s = 0xFFFF;
  1765.     assert(++s == 0x0000);
  1766.     assert(--s == 0xFFFF);
  1767. }
  1768.  
  1769.  
  1770. asfail(file, line, cond)
  1771. char    *file;
  1772. int    line;
  1773. char    *cond;
  1774. {
  1775.     fprintf(stderr, "assertion failure: %s (%d): %s\n", file, line, cond);
  1776.     restore_term();
  1777.     abort();
  1778.     exit(1);
  1779. }
  1780.  
  1781. @EOF
  1782.  
  1783. chmod 644 main.c
  1784.  
  1785. echo x - mapper.c
  1786. cat >mapper.c <<'@EOF'
  1787.  
  1788. #include    <stdio.h>
  1789.  
  1790.  
  1791. /*
  1792.  *  Map a disk image in Prodos block ordering to DOS 3.3 block ordering
  1793.  *    usage:  mapper < old_image > new_image
  1794.  */
  1795.  
  1796. main() {
  1797. unsigned char buf[4096];
  1798. int track;
  1799.  
  1800.     for (track = 0; track < 35; track++) {
  1801.         if (read(0, buf, 4096) != 4096) {
  1802.             perror("bad read");
  1803.             exit(1);
  1804.         }
  1805.  
  1806.         write(1, buf, 256);
  1807.         write(1, &buf[0xE00], 256);
  1808.         write(1, &buf[0xD00], 256);
  1809.         write(1, &buf[0xC00], 256);
  1810.         write(1, &buf[0xB00], 256);
  1811.         write(1, &buf[0xA00], 256);
  1812.         write(1, &buf[0x900], 256);
  1813.         write(1, &buf[0x800], 256);
  1814.         write(1, &buf[0x700], 256);
  1815.         write(1, &buf[0x600], 256);
  1816.         write(1, &buf[0x500], 256);
  1817.         write(1, &buf[0x400], 256);
  1818.         write(1, &buf[0x300], 256);
  1819.         write(1, &buf[0x200], 256);
  1820.         write(1, &buf[0x100], 256);
  1821.         write(1, &buf[0xF00], 256);
  1822.     }
  1823. }
  1824.  
  1825.  
  1826. @EOF
  1827.  
  1828. chmod 644 mapper.c
  1829.  
  1830. echo x - mem.c
  1831. cat >mem.c <<'@EOF'
  1832. /*
  1833.  *  a2, an Apple II emulator in C
  1834.  *  (c) Copyright 1990 by Rich Skrenta
  1835.  *
  1836.  *  Command line interface written by Tom Markson
  1837.  *
  1838.  *  Distribution agreement:
  1839.  *
  1840.  *    You may freely copy or redistribute this software, so long
  1841.  *    as there is no profit made from its use, sale, trade or
  1842.  *    reproduction.  You may not change this copyright notice,
  1843.  *    and it must be included prominently in any copy made.
  1844.  *
  1845.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  1846.  *                    skrenta@blekko.uucp
  1847.  */
  1848.  
  1849.  
  1850. #include    <stdio.h>
  1851. #include    "a2.h"
  1852.  
  1853.  
  1854. unsigned char mem[65536];        /* 64K memory image */
  1855. unsigned char jmp_tbl[65536];        /* jmp & jsr interceptor functions */
  1856. int (*mem_set[256])();            /* memory store interceptors */
  1857.  
  1858. unsigned char rom[0x3000];
  1859. unsigned char ram[0x2000];
  1860. unsigned char bank1[0x1000];
  1861. unsigned char bank2[0x1000];
  1862.  
  1863.  
  1864. int ram_read = 0;
  1865. int ram_write = 0;
  1866. int bank2_enable = 0;
  1867.  
  1868.  
  1869. memory_setup() {
  1870. long i;
  1871. int set_writep();
  1872.  
  1873.     for (i = 0; i < 256; i++)
  1874.         mem_set[i] = NULL;
  1875.  
  1876.     for (i = 0; i < 65536; i++)
  1877.         jmp_tbl[i] = 0;
  1878.  
  1879.     writep(set_writep);
  1880.     ram_copy(&mem[0xD000], rom, 0x3000);
  1881. }
  1882.  
  1883.  
  1884. ram_copy(from, to, len)
  1885. unsigned char *from;
  1886. unsigned char *to;
  1887. int len;
  1888. {
  1889.  
  1890.     while (len--)
  1891.         *to++ = *from++;
  1892. }
  1893.  
  1894.  
  1895. /*
  1896.  *  Write protect/unprotect D000-FFFF
  1897.  */
  1898. writep(fn)
  1899. int (*fn)();
  1900. {
  1901. int i;
  1902.  
  1903.     for (i = 0xD0; i <= 0xFF; i++)
  1904.         mem_set[i] = fn;
  1905. }
  1906.  
  1907.  
  1908. set_writep(a, n)
  1909. unsigned short a;
  1910. unsigned char n;
  1911. {
  1912.     /* Just eat it. */
  1913. }
  1914.  
  1915.  
  1916. set_ramwrite(a, n)
  1917. unsigned short a;
  1918. unsigned char n;
  1919. {
  1920.  
  1921.     if (a >= 0xE000)
  1922.         ram[a - 0xE000] = n;
  1923.     else if (bank2_enable)
  1924.         bank2[a - 0xD000] = n;
  1925.     else
  1926.         bank1[a - 0xD000] = n;
  1927. }
  1928.  
  1929.  
  1930.  
  1931.  
  1932. ram_card(addr)
  1933. unsigned short addr;
  1934. {
  1935.  
  1936.     if (ram_read) {
  1937.         ram_copy(&mem[0xE000], ram, 0x2000);
  1938.         if (bank2_enable)
  1939.             ram_copy(&mem[0xD000], bank2, 0x1000);
  1940.         else
  1941.             ram_copy(&mem[0xD000], bank1, 0x1000);
  1942.     }
  1943.  
  1944.     switch (addr & 0x000F) {
  1945.     case 0x00:             /* C080 */
  1946.         ram_read  = 1;
  1947.         ram_write = 0;
  1948.         bank2_enable = 1;
  1949.  
  1950.         ram_copy(ram, &mem[0xE000], 0x2000);
  1951.         ram_copy(bank2, &mem[0xD000], 0x1000);
  1952.         writep(set_writep);
  1953.         break;
  1954.  
  1955.     case 0x01:            /* C081 */
  1956.         ram_read  = 0;
  1957.         ram_write = 1;
  1958.         bank2_enable = 1;
  1959.  
  1960.         ram_copy(rom, &mem[0xD000], 0x3000);
  1961.         writep(set_ramwrite);
  1962.         break;
  1963.  
  1964.     case 0x02:            /* C082 */
  1965.         ram_read  = 0;
  1966.         ram_write = 0;
  1967.         bank2_enable = 1;
  1968.  
  1969.         ram_copy(rom, &mem[0xD000], 0x3000);
  1970.         writep(set_writep);
  1971.         break;
  1972.  
  1973.     case 0x03:            /* C083 */
  1974.         ram_read  = 1;
  1975.         ram_write = 1;
  1976.         bank2_enable = 1;
  1977.  
  1978.         ram_copy(ram, &mem[0xE000], 0x2000);
  1979.         ram_copy(bank2, &mem[0xD000], 0x1000);
  1980.         writep(NULL);
  1981.         break;
  1982.  
  1983.     case 0x08:             /* C088 */
  1984.         ram_read  = 1;
  1985.         ram_write = 0;
  1986.         bank2_enable = 0;
  1987.  
  1988.         ram_copy(ram, &mem[0xE000], 0x2000);
  1989.         ram_copy(bank1, &mem[0xD000], 0x1000);
  1990.         writep(set_writep);
  1991.         break;
  1992.  
  1993.     case 0x09:            /* C089 */
  1994.         ram_read  = 0;
  1995.         ram_write = 1;
  1996.         bank2_enable = 0;
  1997.         ram_copy(rom, &mem[0xD000], 0x3000);
  1998.         writep(set_ramwrite);
  1999.         break;
  2000.  
  2001.     case 0x0a:            /* C08A */
  2002.         ram_read  = 0;
  2003.         ram_write = 0;
  2004.         bank2_enable = 0;
  2005.         ram_copy(rom, &mem[0xD000], 0x3000);
  2006.         writep(set_writep);
  2007.         break;
  2008.  
  2009.     case 0x0b:            /* C08B */
  2010.         ram_read  = 1;
  2011.         ram_write = 1;
  2012.         bank2_enable = 0;
  2013.         ram_copy(ram, &mem[0xE000], 0x2000);
  2014.         ram_copy(bank1, &mem[0xD000], 0x1000);
  2015.         writep(NULL);
  2016.         break;
  2017.     }
  2018. }
  2019.  
  2020. @EOF
  2021.  
  2022. chmod 644 mem.c
  2023.  
  2024. echo x - parse.c
  2025. cat >parse.c <<'@EOF'
  2026. /*
  2027.  *  a2, an Apple II emulator in C
  2028.  *  (c) Copyright 1990 by Rich Skrenta
  2029.  *
  2030.  *  Command line interface written by Tom Markson
  2031.  *
  2032.  *  Distribution agreement:
  2033.  *
  2034.  *    You may freely copy or redistribute this software, so long
  2035.  *    as there is no profit made from its use, sale, trade or
  2036.  *    reproduction.  You may not change this copyright notice,
  2037.  *    and it must be included prominently in any copy made.
  2038.  *
  2039.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2040.  *                    skrenta@blekko.uucp
  2041.  */
  2042.  
  2043.  
  2044.  
  2045. #include    <stdio.h>
  2046. #include    <signal.h>
  2047. #include    <ctype.h>
  2048. #include    "a2.h"
  2049. #include    "cli.h"
  2050.  
  2051.  
  2052. char    *
  2053. split(s)
  2054. char    *s;
  2055. {
  2056.     char    *t;
  2057.     extern char    *strchr();
  2058.  
  2059.     assert(s != NULL);
  2060.  
  2061.     t = strchr(s, ' ');
  2062.     if (t == NULL)
  2063.         return("");
  2064.  
  2065.     assert(*t == ' ');
  2066.  
  2067.     *t++ = '\0';
  2068.  
  2069.     while (*t && *t == ' ')
  2070.         t++;
  2071.  
  2072.     return(t);
  2073. }
  2074.  
  2075.  
  2076. match(a, b)
  2077. char    *a;
  2078. char    *b;
  2079. {
  2080.  
  2081.     assert(a != NULL);
  2082.     assert(b != NULL);
  2083.  
  2084.     if (*b == '.' && strlen(b) > 1)
  2085.         b++;
  2086.     while (*a && *b) {
  2087.         if (toupper(*a) != toupper(*b))
  2088.             return(NO_MATCH);
  2089.         a++;
  2090.         b++;
  2091.     }
  2092.  
  2093.     if (!*a) {
  2094.         if (!*b)
  2095.             return(IDENTICAL);
  2096.         else
  2097.             return(PARTIAL);
  2098.     } else
  2099.         return(NO_MATCH);
  2100. }
  2101.  
  2102.  
  2103. is_hex_number(s)
  2104. char    *s;
  2105. {
  2106.     char    *temp;
  2107.     temp = s;
  2108.     assert(s != NULL);
  2109.     while (*s)
  2110.         if (!isxdigit(*s++))
  2111.             return(FALSE);
  2112.     if (temp != s)
  2113.         return TRUE;
  2114.     else
  2115.         return FALSE;
  2116. }
  2117.  
  2118.  
  2119. long    get_hex_number(s)
  2120. char    *s;
  2121. {
  2122.     unsigned int    x;
  2123.     if (is_hex_number(s))
  2124.         sscanf(s, "%x", &x);
  2125.     else
  2126.         return(-1);
  2127.     return( (long) x );
  2128. }
  2129.  
  2130.  
  2131. parse_str(tbl, s, t)
  2132. struct cmdtbl tbl[];
  2133. char    *s;
  2134. char    *t;            /* to be passed to handler functions */
  2135. {
  2136. int i;
  2137. int ret;
  2138. int partial = -1;
  2139. int count = 0;
  2140.  
  2141.     i = 0;
  2142.     while (tbl[i].name != NULL) {
  2143.         ret = match(s, tbl[i].name);
  2144.         if (ret == IDENTICAL) {
  2145.             partial = i;
  2146.             count = 0;
  2147.             break;
  2148.         } else if (ret == PARTIAL) {
  2149.             partial = i;
  2150.             count++;
  2151.         }
  2152.  
  2153.         i++;
  2154.     }
  2155.  
  2156.     if (partial == -1)
  2157.         return(NO_MATCH);
  2158.  
  2159.     if (count > 1)
  2160.         return(AMBIGUOUS);
  2161.  
  2162.     if (tbl[partial].func == NULL)
  2163.         return(NOT_IMPLEMENTED);
  2164.  
  2165.     assert(t != NULL);
  2166.     return  (*tbl[partial].func)(t);
  2167. }
  2168.  
  2169.  
  2170.  
  2171. parse(tbl, s)
  2172. struct cmdtbl tbl[];
  2173. char    *s;
  2174. {
  2175.     int    ret;
  2176.     char    buf[1024];
  2177.     char    *t;
  2178.  
  2179.     if (*s == '!') {            /* shell escape-ish thing */
  2180.         shell_escape(++s);
  2181.         return(FALSE);
  2182.     }
  2183.  
  2184.     t = split(s);
  2185.  
  2186.     if (*s == '\0') {
  2187.         return(TRUE);                /* single step */
  2188.  
  2189.     } else if (strcmp(s, "?") == 0) {
  2190.         dump_list(tbl, "Command, one of the following:\n\n");
  2191.  
  2192.     } else switch (parse_str(tbl, s, t)) {
  2193.         case AMBIGUOUS:
  2194.             printf("Ambiguous command '%s'.\n", s);
  2195.             break;
  2196.  
  2197.         case NO_MATCH:
  2198.             printf("Unknown command.  Type ? for a list.\n");
  2199.             break;
  2200.  
  2201.         case NOT_IMPLEMENTED:
  2202.             printf("Sorry, command not implemented yet.\n");
  2203.             break;
  2204.  
  2205.         case OK:
  2206.             break;
  2207.  
  2208.         case DISPLAY:
  2209.             status(stdout);
  2210.             break;
  2211.  
  2212.         default:
  2213.             assert(FALSE);
  2214.     }
  2215.  
  2216.     return(FALSE);
  2217. }
  2218.  
  2219.  
  2220. dump_list(tbl, header)
  2221. struct cmdtbl tbl[];
  2222. char    *header;
  2223. {
  2224.     int    i, count;
  2225.     char    buf[1024];
  2226.  
  2227.     printf(header);
  2228.     i = 0;
  2229.     count = 0;
  2230.     while (tbl[i].name != NULL) {
  2231.         if (*tbl[i].name != '.' || strlen(tbl[i].name) == 1) {
  2232.             if (count % 4 == 3)
  2233.                 printf("    %-15s\n", tbl[i].name);
  2234.             else
  2235.                 printf("    %-15s", tbl[i].name);
  2236.  
  2237.             count++;
  2238.         }
  2239.         i++;
  2240.     }
  2241.  
  2242.     if (count % 4 != 0)
  2243.         printf("\n");
  2244. }
  2245.  
  2246.  
  2247. @EOF
  2248.  
  2249. chmod 644 parse.c
  2250.  
  2251. echo x - prodos.c
  2252. cat >prodos.c <<'@EOF'
  2253. /*
  2254.  *  a2, an Apple II emulator in C
  2255.  *  (c) Copyright 1990 by Rich Skrenta
  2256.  *
  2257.  *  Command line interface written by Tom Markson
  2258.  *
  2259.  *  Distribution agreement:
  2260.  *
  2261.  *    You may freely copy or redistribute this software, so long
  2262.  *    as there is no profit made from its use, sale, trade or
  2263.  *    reproduction.  You may not change this copyright notice,
  2264.  *    and it must be included prominently in any copy made.
  2265.  *
  2266.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2267.  *                    skrenta@blekko.uucp
  2268.  */
  2269.  
  2270.  
  2271. #include    <stdio.h>
  2272. #include    "a2.h"
  2273.  
  2274.  
  2275. #define        BSIZE    512        /* block size */
  2276. #define        D1SIZE    280        /* Size of disk 1 */
  2277. #define        D2SIZE    1024        /* Size of disk 2 */
  2278.  
  2279.  
  2280. /*
  2281.  *  Prodos to DOS 3.3 block mapping
  2282.  */
  2283.  
  2284. int conv1[] = { 0x00, 0x0D, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01 };
  2285. int conv2[] = { 0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x0F };
  2286.  
  2287.  
  2288.  
  2289. proformat()
  2290. {
  2291.  
  2292.     if (write_prot[drive]) {
  2293.         C = 1;
  2294.         A = 0x2B;        /* Write protected */
  2295.         return;
  2296.     }
  2297.  
  2298.     C = 0;
  2299.     A = 0;
  2300. }
  2301.  
  2302.  
  2303. proread()
  2304. {
  2305. int block;
  2306. unsigned short ptr;
  2307. int track, sector;
  2308. char s[50];
  2309.  
  2310.     block = join(mem[0x46], mem[0x47]);
  2311.     ptr = join(mem[0x44], mem[0x45]);
  2312.  
  2313.     sprintf(s, "proread b=%d", block);
  2314.     info(s);
  2315.  
  2316.     track = block / 8;
  2317.     sector = conv1[block % 8];
  2318.  
  2319.     read_disk(track, sector, &mem[ptr]);
  2320.     ptr += 0x100;
  2321.  
  2322.     sector = conv2[block % 8];
  2323.     read_disk(track, sector, &mem[ptr]);
  2324.  
  2325.     C = 0;
  2326.     A = 0;
  2327. }
  2328.  
  2329.  
  2330. prowrite()
  2331. {
  2332. int block;
  2333. unsigned short ptr;
  2334. int track;
  2335. int sector;
  2336. char s[50];
  2337.  
  2338.     if (write_prot[drive]) {
  2339.         C = 1;
  2340.         A = 0x2B;        /* Write protected */
  2341.         return;
  2342.     }
  2343.  
  2344.     block = join(mem[0x46], mem[0x47]);
  2345.     ptr = join(mem[0x44], mem[0x45]);
  2346.  
  2347.     sprintf(s, "prowrite b=%d", block);
  2348.     info(s);
  2349.  
  2350.     track = block / 8;
  2351.     sector = conv1[block % 8];
  2352.  
  2353.     write_disk(track, sector, &mem[ptr]);
  2354.     ptr += 0x100;
  2355.  
  2356.     sector = conv2[block % 8];
  2357.     write_disk(track, sector, &mem[ptr]);
  2358.  
  2359.     C = 0;
  2360.     A = 0;
  2361. }
  2362.  
  2363.  
  2364. prostatus()
  2365. {
  2366.  
  2367.     C = 0;
  2368.     A = 0;
  2369.     Y = high(D1SIZE);
  2370.     X = low(D1SIZE);
  2371. }
  2372.  
  2373.  
  2374. prodos()
  2375. {
  2376.  
  2377.     if (mem[0x43] < 0x80)
  2378.         drive = 0;
  2379.     else
  2380.         drive = 1;
  2381.  
  2382.     if (disk[drive] < 0) {
  2383.         C = 1;
  2384.         A = 0x27;        /* IO Error */
  2385.  
  2386.     } else switch (mem[0x42]) {
  2387.         case 0: 
  2388.             prostatus();
  2389.             break;
  2390.         case 1:
  2391.             proread();
  2392.             break;
  2393.         case 2:
  2394.             prowrite();
  2395.             break;
  2396.         case 3:
  2397.             proformat();
  2398.             break;
  2399.     }
  2400.  
  2401.     DO_RTS;
  2402. }
  2403.  
  2404. @EOF
  2405.  
  2406. chmod 644 prodos.c
  2407.  
  2408. echo x - screen.c
  2409. cat >screen.c <<'@EOF'
  2410. /*
  2411.  *  a2, an Apple II emulator in C
  2412.  *  (c) Copyright 1990 by Rich Skrenta
  2413.  *
  2414.  *  Command line interface written by Tom Markson
  2415.  *
  2416.  *  Distribution agreement:
  2417.  *
  2418.  *    You may freely copy or redistribute this software, so long
  2419.  *    as there is no profit made from its use, sale, trade or
  2420.  *    reproduction.  You may not change this copyright notice,
  2421.  *    and it must be included prominently in any copy made.
  2422.  *
  2423.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2424.  *                    skrenta@blekko.uucp
  2425.  */
  2426.  
  2427.  
  2428.  
  2429. #include    <stdio.h>
  2430. #include    "a2.h"
  2431.  
  2432.  
  2433. extern char screen_map[];        /* at the bottom of this file */
  2434. extern int text1[];
  2435.  
  2436.  
  2437. int line1[0x400];
  2438. int col1[0x400];
  2439.  
  2440.  
  2441. info(s)
  2442. char *s;
  2443. {
  2444.  
  2445.     MoveCursor(0, 57);
  2446.     printf("%-20s", s);
  2447.  
  2448.     last_line = -1;
  2449.     last_col = -1;
  2450.     fflush(stdout);
  2451. }
  2452.  
  2453.  
  2454. screen_setup() {
  2455. extern int set_text1f();
  2456. int line, col;
  2457. int addr, base;
  2458. int i;
  2459.  
  2460.     for (i = 0; i < 0x400; i++) {
  2461.         line1[i] = -1;
  2462.         col1[i] = -1;
  2463.     }
  2464.  
  2465.     mem_set[0x04] = set_text1f;
  2466.     mem_set[0x05] = set_text1f;
  2467.     mem_set[0x06] = set_text1f;
  2468.     mem_set[0x07] = set_text1f;
  2469.  
  2470.     for (line = 0; line < 24; line++) {
  2471.         base = text1[line];
  2472.         for (col = 0; col < 40; col++) {
  2473.             addr = base + col;
  2474.             mem[addr] = 0xA0;
  2475.             line1[addr - 0x400] = line;
  2476.             col1[addr - 0x400] = col;
  2477.         }
  2478.     }
  2479. }
  2480.  
  2481.  
  2482. int last_line = -1;
  2483. int last_col = -1;
  2484.  
  2485.  
  2486. #define appleout(n)    if (n >= 0x80) putchar(screen_map[n]); else { StartInverse(); putchar(screen_map[n]); EndInverse(); }
  2487.  
  2488.  
  2489. set_text1f(addr, n)
  2490. unsigned short addr;
  2491. unsigned char n;
  2492. {
  2493. int line, col;
  2494. unsigned char c;
  2495.  
  2496.     if (mem[addr] == n)        /* no change, don't do anything */
  2497.         return;
  2498.  
  2499.     mem[addr] = n;
  2500.     line = line1[addr - 0x400];
  2501.     col = col1[addr - 0x400];
  2502.  
  2503.     if (line == -1)
  2504.         return;
  2505.  
  2506. /*
  2507.  *  Stuff to try to make updating more efficient
  2508.  *  Is it really worth it?
  2509.  */
  2510.  
  2511.     if (line == last_line) {
  2512.         if (col == 0)
  2513.             putchar('\r');
  2514.         else switch (col - last_col) {
  2515.         case 4:
  2516.             c = mem[addr - 3]; appleout(c);
  2517.             c = mem[addr - 2]; appleout(c);
  2518.             c = mem[addr - 1]; appleout(c);
  2519.             break;
  2520.         case 3:
  2521.             c = mem[addr - 2]; appleout(c);
  2522.             c = mem[addr - 1]; appleout(c);
  2523.             break;
  2524.         case 2:
  2525.             c = mem[addr - 1]; appleout(c);
  2526.             break;
  2527.         case 1:            /* already there */
  2528.             break;
  2529.         case 0:
  2530.             putchar('\b');
  2531.             break;
  2532.         case -1:
  2533.             putchar('\b'); putchar('\b');
  2534.             break;
  2535.         case -2:
  2536.             putchar('\b'); putchar('\b'); putchar('\b');
  2537.             break;
  2538.         case -3:
  2539.             putchar('\b'); putchar('\b'); putchar('\b');
  2540.             putchar('\b');
  2541.             break;
  2542.         default:
  2543.             MoveCursor(line, col);
  2544.         }
  2545.     } else
  2546.         MoveCursor(line, col);
  2547.  
  2548.     appleout(n);
  2549.     fflush(stdout);
  2550.  
  2551.     last_line = line;
  2552.     last_col = col;
  2553. }
  2554.  
  2555.  
  2556. set_text1(addr, n)
  2557. unsigned short addr;
  2558. unsigned char n;
  2559. {
  2560. int line, col;
  2561. unsigned char c;
  2562.  
  2563.     if (mem[addr] == n)        /* no change, don't do anything */
  2564.         return;
  2565.  
  2566.     mem[addr] = n;
  2567.     line = line1[addr - 0x400];
  2568.     col = col1[addr - 0x400];
  2569.  
  2570.     if (line == -1)
  2571.         return;
  2572.  
  2573. /*
  2574.  *  Stuff to try to make updating more efficient
  2575.  *  Is it really worth it?
  2576.  */
  2577.  
  2578.     if (line == last_line) {
  2579.         if (col == 0)
  2580.             putchar('\r');
  2581.         else switch (col - last_col) {
  2582.         case 4:
  2583.             c = mem[addr - 3]; appleout(c);
  2584.             c = mem[addr - 2]; appleout(c);
  2585.             c = mem[addr - 1]; appleout(c);
  2586.             break;
  2587.         case 3:
  2588.             c = mem[addr - 2]; appleout(c);
  2589.             c = mem[addr - 1]; appleout(c);
  2590.             break;
  2591.         case 2:
  2592.             c = mem[addr - 1]; appleout(c);
  2593.             break;
  2594.         case 1:            /* already there */
  2595.             break;
  2596.         case 0:
  2597.             putchar('\b');
  2598.             break;
  2599.         case -1:
  2600.             putchar('\b'); putchar('\b');
  2601.             break;
  2602.         case -2:
  2603.             putchar('\b'); putchar('\b'); putchar('\b');
  2604.             break;
  2605.         case -3:
  2606.             putchar('\b'); putchar('\b'); putchar('\b');
  2607.             putchar('\b');
  2608.             break;
  2609.         default:
  2610.             MoveCursor(line, col);
  2611.         }
  2612.     } else
  2613.         MoveCursor(line, col);
  2614.  
  2615.     appleout(n);
  2616.  
  2617.     last_line = line;
  2618.     last_col = col;
  2619. }
  2620.  
  2621.  
  2622. redraw_screen() {
  2623. int i, j;
  2624. unsigned short base;
  2625. unsigned char c;
  2626.  
  2627.     ClearScreen();
  2628.     for (i = 0; i < 24; i++) {
  2629.         base = text1[i];
  2630.         for (j = 0; j < 40; j++) {
  2631.             c = mem[base + j];
  2632.             appleout(c);
  2633.         }
  2634.         if (i < 23)
  2635.             putchar('\n');
  2636.     }
  2637.  
  2638.     last_line = -1;
  2639.     last_col = -1;
  2640.  
  2641.     fflush(stdout);
  2642. }
  2643.  
  2644.  
  2645. /*
  2646.  *  Screen display mapping table
  2647.  */
  2648.  
  2649. char screen_map[] = {
  2650.  
  2651.     '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',        /* $00    */
  2652.     'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',        /* $08    */
  2653.     'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',        /* $10    */
  2654.     'X', 'Y', 'Z', '[', '\\',']', '^', '_',        /* $18    */
  2655.     ' ', '!', '"', '#', '$', '%', '&', '\'',    /* $20    */
  2656.     '(', ')', '*', '+', ',', '-', '.', '/',        /* $28    */
  2657.     '0', '1', '2', '3', '4', '5', '6', '7',        /* $30    */
  2658.     '8', '9', ':', ';', '<', '=', '>', '?',        /* $38    */
  2659.  
  2660.     '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',        /* $40    */
  2661.     'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',        /* $48    */
  2662.     'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',        /* $50    */
  2663.     'X', 'Y', 'Z', '[', '\\',']', '^', '_',        /* $58    */
  2664.     ' ', '!', '"', '#', '$', '%', '&', '\'',    /* $60    */
  2665.     '(', ')', '*', '+', ',', '-', '.', '/',        /* $68    */
  2666.     '0', '1', '2', '3', '4', '5', '6', '7',        /* $70    */
  2667.     '8', '9', ':', ';', '<', '=', '>', '?',        /* $78    */
  2668.  
  2669.     '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',        /* $80    */
  2670.     'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',        /* $88    */
  2671.     'p', 'q', 'r', 's', 't', 'u', 'v', 'w',        /* $90    */
  2672.     'x', 'y', 'z', '[', '\\',']', '^', '_',        /* $98    */
  2673.     ' ', '!', '"', '#', '$', '%', '&', '\'',    /* $A0    */
  2674.     '(', ')', '*', '+', ',', '-', '.', '/',        /* $A8    */
  2675.     '0', '1', '2', '3', '4', '5', '6', '7',        /* $B0    */
  2676.     '8', '9', ':', ';', '<', '=', '>', '?',        /* $B8    */
  2677.  
  2678.     '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',        /* $C0    */
  2679.     'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',        /* $C8    */
  2680.     'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',        /* $D0    */
  2681.     'X', 'Y', 'Z', '[', '\\',']', '^', '_',        /* $D8    */
  2682.     ' ', '!', '"', '#', '$', '%', '&', '\'',    /* $E0    */
  2683.     '(', ')', '*', '+', ',', '-', '.', '/',        /* $E8    */
  2684.     '0', '1', '2', '3', '4', '5', '6', '7',        /* $F0    */
  2685.     '8', '9', ':', ';', '<', '=', '>', '?',        /* $F8    */
  2686.  
  2687. };
  2688.  
  2689. int text1[] = {
  2690.     0x400, 0x480, 0x500, 0x580, 0x600, 0x680, 0x700, 0x780,
  2691.     0x428, 0x4A8, 0x528, 0x5A8, 0x628, 0x6A8, 0x728, 0x7A8,
  2692.     0x450, 0x4D0, 0x550, 0x5D0, 0x650, 0x6D0, 0x750, 0x7D0,
  2693.     0x478, 0x4F8, 0x578, 0x5F8, 0x678, 0x6F8, 0x778, 0x7F8
  2694. };
  2695.  
  2696. @EOF
  2697.  
  2698. chmod 644 screen.c
  2699.  
  2700. echo x - table.c
  2701. cat >table.c <<'@EOF'
  2702. /*
  2703.  *  a2, an Apple II emulator in C
  2704.  *  (c) Copyright 1990 by Rich Skrenta
  2705.  *
  2706.  *  Command line interface written by Tom Markson
  2707.  *
  2708.  *  Distribution agreement:
  2709.  *
  2710.  *    You may freely copy or redistribute this software, so long
  2711.  *    as there is no profit made from its use, sale, trade or
  2712.  *    reproduction.  You may not change this copyright notice,
  2713.  *    and it must be included prominently in any copy made.
  2714.  *
  2715.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  2716.  *                    skrenta@blekko.uucp
  2717.  */
  2718.  
  2719.  
  2720.  
  2721. #include    <stdio.h>
  2722. #include    "a2.h"
  2723.  
  2724.  
  2725.  
  2726. struct op_info opcode[] = {
  2727.     {"brk",    M_NONE},    /* 0x0 */
  2728.     {"ora",    M_INDX},    /* 0x1 */
  2729.     {"",    M_NONE},    /* 0x2 */
  2730.     {"",    M_NONE},    /* 0x3 */
  2731.     {"tsb",    M_ZP},        /* 0x4 */    /* 65C02 */
  2732.     {"ora",    M_ZP},        /* 0x5 */
  2733.     {"asl",    M_ZP},        /* 0x6 */
  2734.     {"",    M_NONE},    /* 0x7 */
  2735.     {"php",    M_NONE},    /* 0x8 */
  2736.     {"ora",    M_IMM},        /* 0x9 */
  2737.     {"asl",    M_NONE},    /* 0xa */
  2738.     {"",    M_NONE},    /* 0xb */
  2739.     {"tsb",    M_ABS},        /* 0xc */    /* 65C02 */
  2740.     {"ora",    M_ABS},        /* 0xd */
  2741.     {"asl",    M_ABS},        /* 0xe */
  2742.     {"",    M_NONE},    /* 0xf */
  2743.     {"bpl",    M_REL},        /* 0x10 */
  2744.     {"ora",    M_INDY},    /* 0x11 */
  2745.     {"ora",    M_ZIND},    /* 0x12 */    /* 65C02 */
  2746.     {"",    M_NONE},    /* 0x13 */
  2747.     {"trb",    M_ZP},        /* 0x14 */    /* 65C02 */
  2748.     {"ora",    M_ZPX},        /* 0x15 */
  2749.     {"asl",    M_ZPX},        /* 0x16 */
  2750.     {"",    M_NONE},    /* 0x17 */
  2751.     {"clc",    M_NONE},    /* 0x18 */
  2752.     {"ora",    M_ABSY},    /* 0x19 */
  2753.     {"ina",    M_NONE},    /* 0x1a */    /* 65C02 */
  2754.     {"",    M_NONE},    /* 0x1b */
  2755.     {"trb",    M_ABS},        /* 0x1c */    /* 65C02 */
  2756.     {"ora",    M_ABSX},    /* 0x1d */
  2757.     {"asl",    M_ABSX},    /* 0x1e */
  2758.     {"",    M_NONE},    /* 0x1f */
  2759.     {"jsr",    M_ABS},        /* 0x20 */
  2760.     {"and",    M_INDX},    /* 0x21 */
  2761.     {"",    M_NONE},    /* 0x22 */
  2762.     {"",    M_NONE},    /* 0x23 */
  2763.     {"bit",    M_ZP},        /* 0x24 */
  2764.     {"and",    M_ZP},        /* 0x25 */
  2765.     {"rol",    M_ZP},        /* 0x26 */
  2766.     {"",    M_NONE},    /* 0x27 */
  2767.     {"plp",    M_NONE},    /* 0x28 */
  2768.     {"and",    M_IMM},        /* 0x29 */
  2769.     {"rol",    M_NONE},    /* 0x2a */
  2770.     {"",    M_NONE},    /* 0x2b */
  2771.     {"bit",    M_ABS},        /* 0x2c */
  2772.     {"and",    M_ABS},        /* 0x2d */
  2773.     {"rol",    M_ABS},        /* 0x2e */
  2774.     {"",    M_NONE},    /* 0x2f */
  2775.     {"bmi",    M_REL},        /* 0x30 */
  2776.     {"and",    M_INDY},    /* 0x31 */
  2777.     {"and",    M_ZIND},    /* 0x32 */    /* 65C02 */
  2778.     {"",    M_NONE},    /* 0x33 */
  2779.     {"bit",    M_ZPX},        /* 0x34 */    /* 65C02 */
  2780.     {"and",    M_ZPX},        /* 0x35 */
  2781.     {"rol",    M_ZPX},        /* 0x36 */
  2782.     {"",    M_NONE},    /* 0x37 */
  2783.     {"sec",    M_NONE},    /* 0x38 */
  2784.     {"and",    M_ABSY},    /* 0x39 */
  2785.     {"dey",    M_NONE},    /* 0x3a */    /* 65C02 */
  2786.     {"",    M_NONE},    /* 0x3b */
  2787.     {"bit",    M_ABSX},    /* 0x3c */    /* 65C02 */
  2788.     {"and",    M_ABSX},    /* 0x3d */
  2789.     {"rol",    M_ABSX},    /* 0x3e */
  2790.     {"",    M_NONE},    /* 0x3f */
  2791.     {"rti",    M_NONE},    /* 0x40 */
  2792.     {"eor",    M_INDX},    /* 0x41 */
  2793.     {"",    M_NONE},    /* 0x42 */
  2794.     {"",    M_NONE},    /* 0x43 */
  2795.     {"",    M_NONE},    /* 0x44 */
  2796.     {"eor",    M_ZP},        /* 0x45 */
  2797.     {"lsr",    M_ZP},        /* 0x46 */
  2798.     {"",    M_NONE},    /* 0x47 */
  2799.     {"pha",    M_NONE},    /* 0x48 */
  2800.     {"eor",    M_IMM},        /* 0x49 */
  2801.     {"lsr",    M_NONE},    /* 0x4a */
  2802.     {"",    M_NONE},    /* 0x4b */
  2803.     {"jmp",    M_ABS},        /* 0x4c */
  2804.     {"eor",    M_ABS},        /* 0x4d */
  2805.     {"lsr",    M_ABS},        /* 0x4e */
  2806.     {"",    M_NONE},    /* 0x4f */
  2807.     {"bvc",    M_REL},        /* 0x50 */
  2808.     {"eor",    M_INDY},    /* 0x51 */
  2809.     {"eor",    M_ZIND},    /* 0x52 */    /* 65C02 */
  2810.     {"",    M_NONE},    /* 0x53 */
  2811.     {"",    M_NONE},    /* 0x54 */
  2812.     {"eor",    M_ZPX},        /* 0x55 */
  2813.     {"lsr",    M_ZPX},        /* 0x56 */
  2814.     {"",    M_NONE},    /* 0x57 */
  2815.     {"cli",    M_NONE},    /* 0x58 */
  2816.     {"eor",    M_ABSY},    /* 0x59 */
  2817.     {"phy",    M_NONE},    /* 0x5a */    /* 65C02 */
  2818.     {"",    M_NONE},    /* 0x5b */
  2819.     {"",    M_NONE},    /* 0x5c */
  2820.     {"eor",    M_ABSX},    /* 0x5d */
  2821.     {"lsr",    M_ABSX},    /* 0x5e */
  2822.     {"",    M_NONE},    /* 0x5f */
  2823.     {"rts",    M_NONE},    /* 0x60 */
  2824.     {"adc",    M_INDX},    /* 0x61 */
  2825.     {"",    M_NONE},    /* 0x62 */
  2826.     {"",    M_NONE},    /* 0x63 */
  2827.     {"stz",    M_ZP},        /* 0x64 */    /* 65C02 */
  2828.     {"adc",    M_ZP},        /* 0x65 */
  2829.     {"ror",    M_ZP},        /* 0x66 */
  2830.     {"",    M_NONE},    /* 0x67 */
  2831.     {"pla",    M_NONE},    /* 0x68 */
  2832.     {"adc",    M_IMM},        /* 0x69 */
  2833.     {"ror",    M_NONE},    /* 0x6a */
  2834.     {"",    M_NONE},    /* 0x6b */
  2835.     {"jmp",    M_IND},        /* 0x6c */
  2836.     {"adc",    M_ABS},        /* 0x6d */
  2837.     {"ror",    M_ABS},        /* 0x6e */
  2838.     {"",    M_NONE},    /* 0x6f */
  2839.     {"bvs",    M_REL},        /* 0x70 */
  2840.     {"adc",    M_INDX},    /* 0x71 */
  2841.     {"adc",    M_ZIND},    /* 0x72 */    /* 65C02 */
  2842.     {"",    M_NONE},    /* 0x73 */
  2843.     {"stz",    M_ZPX},        /* 0x74 */    /* 65C02 */
  2844.     {"adc",    M_ZPX},        /* 0x75 */
  2845.     {"ror",    M_ZPX},        /* 0x76 */
  2846.     {"",    M_NONE},    /* 0x77 */
  2847.     {"sei",    M_NONE},    /* 0x78 */
  2848.     {"adc",    M_ABSY},    /* 0x79 */
  2849.     {"ply",    M_NONE},    /* 0x7a */    /* 65C02 */
  2850.     {"",    M_NONE},    /* 0x7b */
  2851.     {"jmp",    M_ABINDX},    /* 0x7c */    /* 65C02 */
  2852.     {"adc",    M_ABSX},    /* 0x7d */
  2853.     {"ror",    M_ABSX},    /* 0x7e */
  2854.     {"",    M_NONE},    /* 0x7f */
  2855.     {"bra",    M_REL},        /* 0x80 */    /* 65C02 */
  2856.     {"sta",    M_INDX},    /* 0x81 */
  2857.     {"",    M_NONE},    /* 0x82 */
  2858.     {"",    M_NONE},    /* 0x83 */
  2859.     {"sty",    M_ZP},        /* 0x84 */
  2860.     {"sta",    M_ZP},        /* 0x85 */
  2861.     {"stx",    M_ZP},        /* 0x86 */
  2862.     {"",    M_NONE},    /* 0x87 */
  2863.     {"dey",    M_NONE},    /* 0x88 */
  2864.     {"",    M_NONE},    /* 0x89 */
  2865.     {"txa",    M_NONE},    /* 0x8a */
  2866.     {"",    M_NONE},    /* 0x8b */
  2867.     {"sty",    M_ABS},        /* 0x8c */
  2868.     {"sta",    M_ABS},        /* 0x8d */
  2869.     {"stx",    M_ABS},        /* 0x8e */
  2870.     {"",    M_NONE},    /* 0x8f */
  2871.     {"bcc",    M_REL},        /* 0x90 */
  2872.     {"sta",    M_INDY},    /* 0x91 */
  2873.     {"sta",    M_ZIND},    /* 0x92 */    /* 65C02 */
  2874.     {"",    M_NONE},    /* 0x93 */
  2875.     {"sty",    M_ZPX},        /* 0x94 */
  2876.     {"sta",    M_ZPX},        /* 0x95 */
  2877.     {"stx",    M_ZPX},        /* 0x96 */
  2878.     {"",    M_NONE},    /* 0x97 */
  2879.     {"tya",    M_NONE},    /* 0x98 */
  2880.     {"sta",    M_ABSY},    /* 0x99 */
  2881.     {"txs",    M_NONE},    /* 0x9a */
  2882.     {"",    M_NONE},    /* 0x9b */
  2883.     {"stz",    M_ABS},        /* 0x9c */    /* 65C02 */
  2884.     {"sta",    M_ABSX},    /* 0x9d */
  2885.     {"stz",    M_ABSX},    /* 0x9e */    /* 65C02 */
  2886.     {"",    M_NONE},    /* 0x9f */
  2887.     {"ldy",    M_IMM},        /* 0xa0 */
  2888.     {"lda",    M_INDX},    /* 0xa1 */
  2889.     {"ldx",    M_IMM},        /* 0xa2 */
  2890.     {"",    M_NONE},    /* 0xa3 */
  2891.     {"ldy",    M_ZP},        /* 0xa4 */
  2892.     {"lda",    M_ZP},        /* 0xa5 */
  2893.     {"ldx",    M_ZP},        /* 0xa6 */
  2894.     {"",    M_NONE},    /* 0xa7 */
  2895.     {"tay",    M_NONE},    /* 0xa8 */
  2896.     {"lda",    M_IMM},        /* 0xa9 */
  2897.     {"tax",    M_NONE},    /* 0xaa */
  2898.     {"",    M_NONE},    /* 0xab */
  2899.     {"ldy",    M_ABS},        /* 0xac */
  2900.     {"lda",    M_ABS},        /* 0xad */
  2901.     {"ldx",    M_ABS},        /* 0xae */
  2902.     {"",    M_NONE},    /* 0xaf */
  2903.     {"bcs",    M_REL},        /* 0xb0 */
  2904.     {"lda",    M_INDY},    /* 0xb1 */
  2905.     {"lda",    M_ZIND},    /* 0xb2 */    /* 65C02 */
  2906.     {"",    M_NONE},    /* 0xb3 */
  2907.     {"ldy",    M_ZPX},        /* 0xb4 */
  2908.     {"lda",    M_ZPX},        /* 0xb5 */
  2909.     {"ldx",    M_ZPY},        /* 0xb6 */
  2910.     {"",    M_NONE},    /* 0xb7 */
  2911.     {"clv",    M_NONE},    /* 0xb8 */
  2912.     {"lda",    M_ABSY},    /* 0xb9 */
  2913.     {"tsx",    M_NONE},    /* 0xba */
  2914.     {"",    M_NONE},    /* 0xbb */
  2915.     {"ldy",    M_ABSX},    /* 0xbc */
  2916.     {"lda",    M_ABSX},    /* 0xbd */
  2917.     {"ldx",    M_ABSY},    /* 0xbe */
  2918.     {"",    M_NONE},    /* 0xbf */
  2919.     {"cpy",    M_IMM},        /* 0xc0 */
  2920.     {"cmp",    M_INDX},    /* 0xc1 */
  2921.     {"",    M_NONE},    /* 0xc2 */
  2922.     {"",    M_NONE},    /* 0xc3 */
  2923.     {"cpy",    M_ZP},        /* 0xc4 */
  2924.     {"cmp",    M_ZP},        /* 0xc5 */
  2925.     {"dec",    M_ZP},        /* 0xc6 */
  2926.     {"",    M_NONE},    /* 0xc7 */
  2927.     {"iny",    M_NONE},    /* 0xc8 */
  2928.     {"cmp",    M_IMM},        /* 0xc9 */
  2929.     {"dex",    M_NONE},    /* 0xca */
  2930.     {"",    M_NONE},    /* 0xcb */
  2931.     {"cpy",    M_ABS},        /* 0xcc */
  2932.     {"cmp",    M_ABS},        /* 0xcd */
  2933.     {"dec",    M_ABS},        /* 0xce */
  2934.     {"",    M_NONE},    /* 0xcf */
  2935.     {"bne",    M_REL},        /* 0xd0 */
  2936.     {"cmp",    M_INDY},    /* 0xd1 */
  2937.     {"cmp",    M_ZIND},    /* 0xd2 */    /* 65C02 */
  2938.     {"",    M_NONE},    /* 0xd3 */
  2939.     {"",    M_NONE},    /* 0xd4 */
  2940.     {"cmp",    M_ZPX},        /* 0xd5 */
  2941.     {"dec",    M_ZPX},        /* 0xd6 */
  2942.     {"",    M_NONE},    /* 0xd7 */
  2943.     {"cld",    M_NONE},    /* 0xd8 */
  2944.     {"cmp",    M_ABSY},    /* 0xd9 */
  2945.     {"phx",    M_NONE},    /* 0xda */    /* 65C02 */
  2946.     {"",    M_NONE},    /* 0xdb */
  2947.     {"",    M_NONE},    /* 0xdc */
  2948.     {"cmp",    M_ABSX},    /* 0xdd */
  2949.     {"dec",    M_ABSX},    /* 0xde */
  2950.     {"",    M_NONE},    /* 0xdf */
  2951.     {"cpx",    M_IMM},        /* 0xe0 */
  2952.     {"sbc",    M_INDX},    /* 0xe1 */
  2953.     {"",    M_NONE},    /* 0xe2 */
  2954.     {"",    M_NONE},    /* 0xe3 */
  2955.     {"cpx",    M_ZP},        /* 0xe4 */
  2956.     {"sbc",    M_ZP},        /* 0xe5 */
  2957.     {"inc",    M_ZP},        /* 0xe6 */
  2958.     {"",    M_NONE},    /* 0xe7 */
  2959.     {"inx",    M_NONE},    /* 0xe8 */
  2960.     {"sbc",    M_IMM},        /* 0xe9 */
  2961.     {"nop",    M_NONE},    /* 0xea */
  2962.     {"",    M_NONE},    /* 0xeb */
  2963.     {"cpx",    M_ABS},        /* 0xec */
  2964.     {"sbc",    M_ABS},        /* 0xed */
  2965.     {"inc",    M_ABS},        /* 0xee */
  2966.     {"",    M_NONE},    /* 0xef */
  2967.     {"beq",    M_REL},        /* 0xf0 */
  2968.     {"sbc",    M_INDY},    /* 0xf1 */
  2969.     {"sbc",    M_ZIND},    /* 0xf2 */    /* 65C02 */
  2970.     {"",    M_NONE},    /* 0xf3 */
  2971.     {"",    M_NONE},    /* 0xf4 */
  2972.     {"sbc",    M_ZPX},        /* 0xf5 */
  2973.     {"inc",    M_ZPX},        /* 0xf6 */
  2974.     {"",    M_NONE},    /* 0xf7 */
  2975.     {"sed",    M_NONE},    /* 0xf8 */
  2976.     {"sbc",    M_ABSY},    /* 0xf9 */
  2977.     {"plx",    M_NONE},    /* 0xfa */    /* 65C02 */
  2978.     {"",    M_NONE},    /* 0xfb */
  2979.     {"",    M_NONE},    /* 0xfc */
  2980.     {"sbc",    M_ABSX},    /* 0xfd */
  2981.     {"inc",    M_ABSX},    /* 0xfe */
  2982.     {"",    M_NONE},    /* 0xff */
  2983. };
  2984.  
  2985.  
  2986. diss(pc, fp)
  2987. unsigned short pc;
  2988. FILE *fp;
  2989. {
  2990. char *s;
  2991. int count;
  2992. int tmp;
  2993. unsigned short addr;
  2994. unsigned char one, two, three;
  2995.  
  2996.     fprintf(fp, "%.4X:  ", pc);
  2997.  
  2998.     addr = pc;
  2999.     one = mem[pc++];
  3000.     two = mem[pc++];
  3001.     three = mem[pc++];
  3002.  
  3003.     s = opcode[one].name;
  3004.  
  3005.     if (s == NULL || *s == '\0')
  3006.         s = "???";
  3007.  
  3008.     switch (opcode[one].add_mode) {
  3009.         case 0:
  3010.             fprintf(fp, "%.2x        %s           ", one, s);
  3011.             count = 1;
  3012.             break;
  3013.  
  3014.         case M_ZP:
  3015.             fprintf(fp, "%.2x %.2x     %s  $%.2x      ",
  3016.                             one, two, s, two);
  3017.             count = 2;
  3018.             break;
  3019.  
  3020.         case M_ZPX:
  3021.             fprintf(fp, "%.2x %.2x     %s  $%.2x,X    ",
  3022.                             one, two, s, two);
  3023.             count = 2;
  3024.             break;
  3025.  
  3026.         case M_ZPY:
  3027.             fprintf(fp, "%.2x %.2x     %s  $%.2x,Y    ",
  3028.                             one, two, s, two);
  3029.             count = 2;
  3030.             break;
  3031.  
  3032.         case M_IND:
  3033.             fprintf(fp, "%.2x %.2x %.2x  %s  ($%.4x)  ",
  3034.                         one, two, three, s,
  3035.                         join(two, three));
  3036.             count = 3;
  3037.             break;
  3038.  
  3039.         case M_INDX:
  3040.             fprintf(fp, "%.2x %.2x     %s  ($%.2x,X)  ",
  3041.                         one, two, s, two);
  3042.             count = 2;
  3043.             break;
  3044.  
  3045.         case M_INDY:
  3046.             fprintf(fp, "%.2x %.2x     %s  ($%.2x),Y  ",
  3047.                         one, two, s, two);
  3048.             count = 2;
  3049.             break;
  3050.  
  3051.         case M_ABS:
  3052.             fprintf(fp, "%.2x %.2x %.2x  %s  $%.4x    ",
  3053.                         one, two, three, s,
  3054.                         join(two, three));
  3055.             count = 3;
  3056.             break;
  3057.  
  3058.         case M_ABSX:
  3059.             fprintf(fp, "%.2x %.2x %.2x  %s  $%.4x,X  ",
  3060.                         one, two, three, s,
  3061.                         join(two, three));
  3062.             count = 3;
  3063.             break;
  3064.  
  3065.         case M_ABSY:
  3066.             fprintf(fp, "%.2x %.2x %.2x  %s  $%.4x,Y  ",
  3067.                         one, two, three, s,
  3068.                         join(two, three));
  3069.             count = 3;
  3070.             break;
  3071.  
  3072.         case M_IMM:
  3073.             fprintf(fp, "%.2x %.2x     %s  #$%.2x     ",
  3074.                         one, two, s, two);
  3075.             count = 2;
  3076.             break;
  3077.  
  3078.         case M_REL:
  3079.             tmp = two;
  3080.             if (tmp > 127)
  3081.                 tmp = tmp - 256;
  3082.             tmp += addr + 2;
  3083.             tmp &= 0xFFFF;
  3084.  
  3085.             fprintf(fp, "%.2x %.2x     %s  $%.4x    ",
  3086.                         one, two, s, tmp);
  3087.             count = 2;
  3088.             break;
  3089.  
  3090.         case M_ZIND:
  3091.             fprintf(fp, "%.2x %.2x     %s  ($%.2x)    ",
  3092.                         one, two, s, two);
  3093.             count = 2;
  3094.             break;
  3095.  
  3096.         case M_ABINDX:
  3097.             fprintf(fp, "%.2x %.2x %.2x  %s  ($%.4x,X)",
  3098.                         one, two, three, s,
  3099.                         join(two, three));
  3100.             count = 3;
  3101.             break;
  3102.  
  3103.         default:
  3104.             fprintf(fp, "%.2x        %s             ", "???", one);
  3105.             count = 1;
  3106.     }
  3107.  
  3108.     return(count);
  3109. }
  3110.  
  3111. flags(fp)
  3112. FILE *fp;
  3113. {
  3114.     fprintf(fp, " A=%.2X X=%.2X Y=%.2X SP=%.2X", A, X, Y, Sp);
  3115.     fprintf(fp, "  N%d V%d B%d D%d I%d Z%d C%d\n",
  3116.                 !!N, !!V, !!B, !!D, !!I, !NZ, !!C);
  3117. }
  3118.  
  3119. @EOF
  3120.  
  3121. chmod 644 table.c
  3122.  
  3123. echo x - vidout.c
  3124. cat >vidout.c <<'@EOF'
  3125. /*
  3126.  *  a2, an Apple II emulator in C
  3127.  *  (c) Copyright 1990 by Rich Skrenta
  3128.  *
  3129.  *  Command line interface written by Tom Markson
  3130.  *
  3131.  *  Distribution agreement:
  3132.  *
  3133.  *    You may freely copy or redistribute this software, so long
  3134.  *    as there is no profit made from its use, sale, trade or
  3135.  *    reproduction.  You may not change this copyright notice,
  3136.  *    and it must be included prominently in any copy made.
  3137.  *
  3138.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  3139.  *                    skrenta@blekko.uucp
  3140.  */
  3141.  
  3142.  
  3143.  
  3144. #include    <stdio.h>
  3145. #include    "a2.h"
  3146.  
  3147.  
  3148. #define        WNDLFT        0x20
  3149. #define        WNDWDTH        0x21
  3150. #define        WNDTOP        0x22
  3151. #define        WNDBTM        0x23
  3152. #define        CH        0x24
  3153. #define        CV        0x25
  3154. #define        BASL        0x28
  3155. #define        BASH        0x29
  3156. #define        BAS2L        0x2A
  3157. #define        BAS2H        0x2B
  3158.  
  3159.  
  3160.  
  3161. /*
  3162.  *  VIDOUT at $FBFD
  3163.  */
  3164.  
  3165. vidout() {
  3166. unsigned short ptr;
  3167.  
  3168.     if (A >= 0xA0 || A < 0x80) {
  3169.         ptr = join(mem[BASL], mem[BASH]) + mem[CH];
  3170.         set_text1f(ptr, A);
  3171.         mem[CH]++;
  3172.         if (mem[CH] >= mem[WNDWDTH])
  3173.             mem[CH] = 0;
  3174.         else {
  3175.             DO_RTS;
  3176.             return;
  3177.         }
  3178.     } else if (A == 0x8D)
  3179.         mem[CH] = 0;
  3180.     else if (A != 0x8A) {
  3181.         Pc = 0xFC0C;
  3182.         return;
  3183.     }
  3184.  
  3185.     A = ++mem[CV];
  3186.     if (A < mem[WNDBTM]) {
  3187.         Pc = 0xFC24;
  3188.         return;
  3189.     }
  3190.     mem[CV]--;
  3191.  
  3192.     scroll();
  3193. }
  3194.  
  3195.  
  3196. /*
  3197.  *  SCROLL at $FC70
  3198.  */
  3199.  
  3200. scroll() {
  3201. int top;
  3202. unsigned short bas, bas2, ptr;
  3203. int width;
  3204. int i;
  3205. int scrl2_normal;
  3206.  
  3207.     if (mem[0x21] == 40 && mem[0x22] == 0 && mem[0x23] == 24) {
  3208.         MoveCursor(term_lines, 0);
  3209.         putchar('\n');
  3210.         last_line = -1;
  3211.         last_col = -1;
  3212.         fflush(stdout);
  3213.         scrl2_normal = FALSE;
  3214.     } else
  3215.         scrl2_normal = TRUE;
  3216.  
  3217.     top = mem[WNDTOP];
  3218.     width = mem[WNDWDTH] - 1;
  3219.     bas = text1[top % 32] + mem[WNDLFT];
  3220.  
  3221.     while (1) {
  3222.         bas2 = bas;
  3223.  
  3224.         if (++top >= mem[WNDBTM]) {
  3225.             mem[BASL] = low(bas);
  3226.             mem[BASH] = high(bas);
  3227.             Pc = 0xFC95;
  3228.             fflush(stdout);
  3229.             return;
  3230.         }
  3231.  
  3232.         bas = text1[top % 32] + mem[WNDLFT];
  3233.         ptr = bas;
  3234.  
  3235.         if (scrl2_normal)
  3236.             for (i = 0; i <= width; i++)
  3237.                 set_text1(bas2++, mem[ptr++]);
  3238.         else
  3239.             for (i = 0; i <= width; i++)
  3240.                 mem[bas2++] = mem[ptr++];
  3241.     }
  3242. }
  3243.  
  3244.  
  3245. @EOF
  3246.  
  3247. chmod 644 vidout.c
  3248.  
  3249. exit 0
  3250. -- 
  3251. skrenta@blekko.commodore.com
  3252.