home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Misc / a2 / Source / commands.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-21  |  13.5 KB  |  837 lines

  1. /*
  2.  *  a2, an Apple II emulator in C
  3.  *  (c) Copyright 1990 by Rich Skrenta
  4.  *
  5.  *  Command line interface written by Tom Markson
  6.  *
  7.  *  Distribution agreement:
  8.  *
  9.  *    You may freely copy or redistribute this software, so long
  10.  *    as there is no profit made from its use, sale, trade or
  11.  *    reproduction.  You may not change this copyright notice,
  12.  *    and it must be included prominently in any copy made.
  13.  *
  14.  *  Send emulator related mail to:  skrenta@blekko.commodore.com
  15.  *                    skrenta@blekko.uucp
  16.  */
  17.  
  18.  
  19. #import    <stdio.h>
  20. #import    <libc.h>
  21. #import    <ctype.h>
  22. #import    <signal.h>
  23. #import    "a2.h"
  24. #import    "cli.h"
  25.  
  26.  
  27. extern unsigned short lpoint;
  28. extern long phantom_location;
  29. extern char *getcwd();
  30. extern int map_to_upper;
  31. extern char escape_char;
  32. long get_hex_number();
  33.  
  34. char diskname[2][200];        /* disk names stored here */
  35.  
  36. struct point_stack {
  37.     unsigned short data[MAXSTACK];
  38.     int sp;
  39. } pstack;
  40.  
  41. void init_point(void)
  42. {
  43.     pstack.sp = -1;
  44. }
  45.  
  46. int pop_point(char *rest)
  47. {
  48.     if (pstack.sp < 0 ) {
  49.         printf("stack empty\n");
  50.         return OK;
  51.     }
  52.     switch (*rest){
  53.         case 'l':
  54.         case 'L':
  55.             printf("%x\n", lpoint = pstack.data[pstack.sp--]);
  56.             break;
  57.         case 'p':
  58.         case 'P':
  59.             printf("%x\n", lpoint = pstack.data[pstack.sp--]);
  60.             break;
  61.         default : 
  62.             printf("pop [lp]\n");
  63.             break;
  64.     }
  65.     return(OK);
  66. }
  67.  
  68. int dup_point(char *rest)
  69. {
  70.     if (pstack.sp < 0 ) {
  71.         printf("stack empty\n");
  72.         return OK;
  73.     }
  74.     switch (*rest){
  75.         case 'l':
  76.         case 'L':
  77.             lpoint = pstack.data[pstack.sp];
  78.             break;
  79.         case 'p':
  80.         case 'P':
  81.             lpoint = pstack.data[pstack.sp];
  82.             break;
  83.         default : 
  84.             printf("dup [lp]\n");
  85.             break;
  86.     }
  87.     return(OK);
  88. }
  89.  
  90. int push_point(char *rest)
  91. {
  92.     long value;
  93.     char *addr;
  94.  
  95.     assert (pstack.sp < MAXSTACK);
  96.     switch (*rest){
  97.         case 'l':
  98.         case 'L':
  99.             pstack.data[++pstack.sp] = lpoint;
  100.             break;
  101.         case 'p':
  102.         case 'P':
  103.             pstack.data[++pstack.sp] = Pc;
  104.             break;
  105.         default:
  106.             addr = rest;
  107.             rest = split(rest);
  108.             value = get_hex_number(addr);
  109.             if (value == -1L) 
  110.                 printf("push [l|p|<addr>]\n");
  111.             else 
  112.                 pstack.data[++pstack.sp]=(unsigned short)value;
  113.             break;
  114.     }
  115.     return(OK);
  116. }
  117.  
  118.  
  119. int clb(char *junk)
  120. {
  121.  
  122.     B = 0;
  123.     return(DISPLAY);
  124. }
  125.  
  126.  
  127. int seb(char *junk)
  128. {
  129.  
  130.     B = 1;
  131.     return(DISPLAY);
  132. }
  133.  
  134.  
  135. int clc(char    *junk)
  136. {
  137.     C = 0;
  138.     return(DISPLAY);
  139. }
  140.  
  141.  
  142. int sec(char    *junk)
  143. {
  144.     C = 1;
  145.     return(DISPLAY);
  146. }
  147.  
  148.  
  149. int sev(char    *junk)
  150. {
  151.     V = 1;
  152.     return(DISPLAY);
  153. }
  154.  
  155.  
  156. int clv(char    *junk)
  157. {
  158.     V = 0;
  159.     return(DISPLAY);
  160. }
  161.  
  162.  
  163. int sed(char    *junk)
  164. {
  165.     D = 1;
  166.     return(DISPLAY);
  167. }
  168.  
  169.  
  170. int cld(char *junk)
  171. {
  172.     D = 0;
  173.     return(DISPLAY);
  174. }
  175.  
  176.  
  177. int sei(char    *junk)
  178. {
  179.     I = 1;
  180.     return(DISPLAY);
  181. }
  182.  
  183.  
  184. int clri(char    *junk)
  185. {
  186.     I = 0;
  187.     return(DISPLAY);
  188. }
  189.  
  190.  
  191. int sen(char    *junk)
  192. {
  193.     N = 1;
  194.     return(DISPLAY);
  195. }
  196.  
  197.  
  198. int cln(char    *junk)
  199. {
  200.     N = 0;
  201.     return(DISPLAY);
  202. }
  203.  
  204.  
  205. int sez(char    *junk)
  206. {
  207.     NZ = 0;
  208.     return(DISPLAY);
  209. }
  210.  
  211.  
  212. int clz(char    *junk)
  213. {
  214.     NZ = 1;
  215.     return(DISPLAY);
  216. }
  217.  
  218.  
  219. void quit_emulator(char    *junk)
  220. {
  221.   exit(0);
  222. }
  223.  
  224.  
  225.  
  226. int ver(char    *junk)
  227. {
  228.     printf("a2 - Apple II emulator  (c) Copyright 1990 by Rich Skrenta & Tom Markson\n");
  229.     return(OK);
  230. }
  231.  
  232.  
  233. int refresh(char    *junk)
  234. {
  235.  
  236.     in_cli = FALSE;
  237.     return(OK);
  238. }
  239.  
  240.  
  241. int shell_escape(char    *rest)
  242. {
  243.     char    line[100];
  244.     char *s;
  245.  
  246.     s = getenv("SHELL");
  247.     if (s == NULL)
  248.         s = "/bin/sh";
  249.  
  250.     strcpy(line, s);
  251.  
  252.     if (*rest != '\0') {
  253.         strcat(line, " -c '");
  254.         strcat(line, rest);
  255.         strcat(line, "'");
  256.     }
  257.     system(line);
  258.  
  259.     printf("\n");
  260.     return(OK);
  261. }
  262.  
  263.  
  264. int do_soft_reset(char    *rest)
  265. {
  266.  
  267.     Pc = mem[0xFFFC] | (mem[0xFFFD] << 8);
  268.     return(DISPLAY);
  269. }
  270.  
  271.  
  272. int do_bload(char    *rest)
  273. {
  274.     char    *first;
  275.     char    *file;
  276.     unsigned short    start;
  277.     long    foo;
  278.  
  279.     file = rest;
  280.     rest = split(rest);
  281.     first = rest;
  282.     rest = split(rest);
  283.     foo = get_hex_number(first);
  284.     if (foo == -1) {
  285.         printf("usage: bload file hex-address\n");
  286.         return(OK);
  287.     }
  288.     start = (unsigned int) foo;
  289.     bload(file, start);
  290.  
  291.     return(OK);
  292. }
  293.  
  294.  
  295. int do_bsave(char    *rest)
  296. {
  297.     char    *startc, *sizec, *file;
  298.     unsigned short    start, size;
  299.     long    istart, iend;
  300.     file = rest;
  301.     rest = split(rest);
  302.     startc = rest;
  303.     rest = split(rest);
  304.     sizec = rest;
  305.     rest = split(rest);
  306.     istart = get_hex_number(startc);
  307.     iend = get_hex_number(sizec);
  308.     if ((istart == -1) || (iend == -1))
  309.         printf("usage: bsave file hex-address hex-length\n");
  310.     else {
  311.         start = (unsigned short) istart;
  312.         size  = (unsigned short) iend;
  313.         bsave(file, start, size);
  314.     }
  315.  
  316.     return(OK);
  317. }
  318.  
  319.  
  320.  
  321. int show_point(char    *rest)
  322. {
  323.  
  324.     lpoint = Pc;
  325.     return(DISPLAY);
  326. }
  327.  
  328.  
  329. int hack(char *rest)
  330. {
  331. extern int cur_track;
  332.  
  333.     cur_track = get_hex_number(rest);
  334.     return(OK);
  335. }
  336.  
  337.  
  338. int do_jump(char    *rest)
  339. {
  340.     char    *start;
  341.     long    istart;
  342.     start = rest;
  343.     rest = split(rest);
  344.     istart = get_hex_number(start);
  345.  
  346.     if (istart == -1) {
  347.         printf("usage: jmp <hex address>\n");
  348.         return(OK);
  349.     } else {
  350.         Pc = istart & 0xFFFF;
  351.         return(DISPLAY);
  352.     }
  353. }
  354.  
  355.  
  356.  
  357. int trace(char    *rest)
  358. {
  359.     char    *addr1, *addr2, *file;
  360.     long    addr1i, addr2i;
  361.  
  362.     addr1 = rest;
  363.     rest = split(rest);
  364.     addr2 = rest;
  365.     rest = split(rest);
  366.     file = rest;
  367.     rest = split(rest);
  368.     addr1i = get_hex_number(addr1);
  369.     addr2i = get_hex_number(addr2);
  370.     if (addr1i == -1 && addr2i == -1) {
  371.         if (trace_lo == -1)
  372.             printf("No trace region set\n");
  373.         else
  374.             printf("Tracing between $%.4X and $%.4x\n",
  375.                             trace_lo, trace_hi);
  376.         return(OK);
  377.     }
  378.  
  379.     if (addr1i == -1 || addr2i == -1) {
  380.         printf("usage: trace [low high]\n");
  381.         return(OK);
  382.     }
  383.  
  384.     if (logging_fp == NULL) {
  385.         if (*file == '\0' || file == NULL) {
  386.             printf("Trace log will go to file 'trace'.\n");
  387.             file = "trace";
  388.         }
  389.         logging_fp = fopen(file, "w");
  390.         if (logging_fp == NULL) {
  391.             perror("can't open trace file");
  392.             trace_lo = -1;
  393.             return(OK);
  394.         }
  395.     }
  396.  
  397.     trace_lo = addr1i & 0xFFFF;
  398.     trace_hi = addr2i & 0xFFFF;
  399.  
  400.     return(OK);
  401. }
  402.  
  403.  
  404. int ldx(char    *rest)
  405. {
  406.     long    number;
  407.     char    *first;
  408.  
  409.     first = rest;
  410.     rest = split(rest);
  411.     number = get_hex_number(first);
  412.  
  413.     number &= 0xFF;
  414.     if (number < 0) {
  415.         printf("usage: ldx <hex number>\n");
  416.         return(OK);
  417.     }
  418.  
  419.     X = number & 0xFF;
  420.     return(DISPLAY);
  421. }
  422.  
  423.  
  424. int ldy(char    *rest)
  425. {
  426.     long    number;
  427.     char    *first;
  428.     first = rest;
  429.     rest = split(rest);
  430.     number = get_hex_number(first);
  431.  
  432.     if (number < 0) {
  433.         printf("usage: ldy <hex number>\n");
  434.         return(OK);
  435.     }
  436.  
  437.     Y = number & 0xFF;
  438.     return(DISPLAY);
  439. }
  440.  
  441.  
  442. int lda(char    *rest)
  443. {
  444.     long    number;
  445.     char    *first;
  446.     first = rest;
  447.     rest = split(rest);
  448.     number = get_hex_number(first);
  449.     if (number < 0) {
  450.         printf("usage: lda <hex number>\n");
  451.         return(OK);
  452.     }
  453.  
  454.     A = number & 0xFF;
  455.     return(DISPLAY);
  456. }
  457.  
  458.  
  459. int lds(char    *rest)
  460. {
  461.     long    number;
  462.     char    *first;
  463.     first = rest;
  464.     rest = split(rest);
  465.     number = get_hex_number(first);
  466.     if (number < 0) {
  467.         printf("usage: lds <hex number>\n");
  468.         return(OK);
  469.     }
  470.  
  471.     Sp = number & 0xFF;
  472.     return(DISPLAY);
  473. }
  474.  
  475.  
  476. int set_break_point(char    *rest)
  477. {    
  478.     long    addr;
  479.     char    *first;
  480.     first = rest;
  481.     rest = split(rest);
  482.     addr = get_hex_number(first);
  483.     if (addr == -1)
  484.         if (breakpoint == -1)
  485.             printf("no breakpoint set\n");
  486.             else
  487.             printf("break point set at %x\n",
  488.                 (unsigned short)breakpoint);
  489.             else
  490.         breakpoint = addr;
  491.     running = FALSE;
  492.     return(OK);
  493. }
  494.  
  495.  
  496. int clear_break_point(char    *rest)
  497. {
  498.     breakpoint = -1;
  499.     return(OK);
  500. }
  501.  
  502.  
  503. int notrace(char    *junk)
  504. {
  505.  
  506.     trace_lo = -1;
  507.     if (logging_fp == NULL)
  508.         return(OK);
  509.     else
  510.         fclose(logging_fp);
  511.     logging_fp = NULL;
  512.     return(OK);
  513. }
  514.  
  515.  
  516. int insert_disk(char *rest)
  517. {
  518.     char    *name;
  519.     char    *which;
  520.     int    fd;
  521.     int    read_only = 0;
  522.  
  523.     name = rest;
  524.     rest = split(rest);
  525.     which = rest;
  526.     rest = split(rest);
  527.  
  528.     if (name == NULL || *name == '\0') {
  529.         printf("usage: insert <file name> [drive]\n");
  530.         return(OK);
  531.     }
  532.  
  533.     fd = open(name, 2);        /* attempt open for read/write */
  534.     if (fd >= 0)
  535.         read_only = 0;
  536.     else  {                /* attempt open read only */
  537.         read_only = 1;
  538.         fd = open(name, 0);
  539.     }
  540.     if (fd < 0) {
  541.         fprintf(stderr, "can't open %s: ", name);
  542.         perror("");
  543.         return(OK);
  544.     }
  545.  
  546.     if (*which == '2')
  547.         drive = 1;
  548.     else
  549.         drive = 0;
  550.  
  551.     if (disk[drive] >= 0)
  552.         close(disk[drive]);
  553.  
  554.     strcpy(diskname[drive], name);
  555.  
  556.     disk[drive] = fd;
  557.     write_prot[drive] = read_only;
  558.  
  559.     printf("disk %d inserted, %swrite protected\n", drive + 1,
  560.                 read_only ? "" : "not ");
  561.  
  562.     return(OK);
  563. }
  564.  
  565.  
  566. int dissassemble(char *rest)
  567. {
  568.     long istart;
  569.     long iend;
  570.     int count = 0;
  571.     char *first,*last;
  572.  
  573.     first = rest;
  574.     rest = split(rest);
  575.     last = rest;
  576.     rest = split(rest);
  577.  
  578.     istart = get_hex_number(first);
  579.     iend   = get_hex_number(last);
  580.     if (istart != -1)
  581.         lpoint = istart;
  582.     if (iend == -1)
  583.         iend=65537;
  584.     while ( (long) lpoint < iend) {
  585.         lpoint += diss(lpoint, stdout);
  586.         printf("\n");
  587.         count++;
  588.         if (iend == 65537)
  589.             if (count > term_lines-3)
  590.                 break;
  591.     }
  592.     return OK;
  593. }
  594.  
  595. void ascii_dump(unsigned short l, unsigned short h)
  596. {
  597.     while (l < h) {
  598.         if (isprint(mem[l]))
  599.             printf("%c",mem[l]);
  600.         else 
  601.             printf(".");
  602.         l++;
  603.     }
  604. }
  605.  
  606. int hex_dump(char *rest)
  607. {
  608.     char *start,*end;
  609.     unsigned short last, addr,oaddr;
  610.     long iaddr1,iaddr2;
  611.     int count;
  612.  
  613.     start = rest;
  614.     rest = split(rest);
  615.     end = rest;
  616.     rest = split(rest);
  617.     iaddr1 = get_hex_number( start );
  618.     iaddr2 = get_hex_number( end );
  619.  
  620.     if (iaddr2 != -1 && iaddr1 > iaddr2)
  621.         return(OK);
  622.  
  623.     if (iaddr1 != -1)
  624.         lpoint = (unsigned short) iaddr1;
  625.     if (iaddr2 == -1)
  626.         last = lpoint + 1;
  627.     else
  628.         last = (unsigned short) iaddr2 + 1;
  629.  
  630.     last &= 0xFFFF;
  631.  
  632.     addr = lpoint;
  633.     count = 0;
  634.     printf("%.4X:  ", addr);
  635.     oaddr = addr;
  636.     do {
  637.         if (count % 16 == 0 && count != 0) {
  638.             ascii_dump(oaddr,addr);
  639.             oaddr = addr;
  640.             printf("\n%.4X:  ", addr);
  641.         }
  642.         printf("%.2X ", mem[addr]);
  643.         addr++;
  644.         count++;
  645.     } while (addr != last);
  646.     while ((count % 16) != 0) {
  647.         printf("   ");  /* 3 spaces dd_ */
  648.         count++;
  649.     }
  650.     ascii_dump(oaddr,addr);
  651.     printf("\n");
  652.     return(OK);
  653. }
  654.  
  655. int deposit(char *rest)
  656. {
  657.     char *addr;
  658.     char *value;
  659.     unsigned short location;
  660.     long iloc;
  661.     unsigned char val;
  662.     int fired_once;
  663.  
  664.     addr = rest;
  665.     rest = split(rest);
  666.     fired_once = 0;
  667.     iloc = get_hex_number(addr);
  668.     if (iloc == -1) {
  669.         printf("usage: deposit <addr> <value> [<value>...]\n");
  670.         return(OK);
  671.     }
  672.  
  673.     location = (unsigned short) iloc;
  674.     do {
  675.         value = rest;
  676.         rest = split(rest);
  677.         val = get_hex_number(value);
  678.         if (val == -1) {
  679.             if (!fired_once)
  680.                 printf("Invalid or Missing Hex address\n");
  681.             return OK;
  682.         }
  683.         mem[location++] = val;
  684.         fired_once = 1;
  685.     } while (*rest != '\0');
  686.  
  687.     return(OK);
  688. }
  689.  
  690. int phantom_trace(char *rest)
  691. {
  692.     char *phantoms;
  693.     char *addr1s;
  694.     char *addr2s;
  695.     char *file;
  696.     long  phantom;
  697.     long low_val,high_val;
  698.  
  699.     phantoms = rest;
  700.     rest = split(rest);
  701.     addr1s = rest;
  702.     rest = split(rest);
  703.     addr2s = rest;
  704.     rest = split(rest);
  705.     file = rest;
  706.     rest = split(rest);
  707.  
  708.     phantom = (unsigned short)get_hex_number(phantoms);
  709.     low_val = get_hex_number(addr1s);
  710.     high_val = get_hex_number(addr2s);
  711.     if (*phantoms == '\0') {
  712.         if (phantom_location == -1) {
  713.             printf("The phantom sleeps.");
  714.             if (trace_lo != -1 && trace_hi != -1)
  715.                 printf("however, a trace is active.");
  716.             printf("\n");
  717.         } else 
  718.         printf("the phantom waits until Pc = %.4X and then traces from %.4X to %.4X\n",phantom_location,trace_lo,trace_hi);
  719.         return(OK);
  720.     }
  721.     if (low_val == -1 || high_val == -1 || phantom == -1) {
  722.         printf("usage: phantom <addr> <addr> <addr> [file]\n");
  723.         return OK;
  724.     } phantom_location = phantom; trace_lo = low_val; trace_hi = high_val; if (logging_fp == NULL) {
  725.         if (*file == '\0' || file == NULL) {
  726.             printf("the phantom will trace to file 'trace'.\n");
  727.             file = "trace";
  728.         }
  729.         logging_fp = fopen(file, "w");
  730.         if (logging_fp == NULL) {
  731.             perror("can't open trace file");
  732.             trace_lo = -1;
  733.             return(OK);
  734.         }
  735.     }
  736.     return OK;
  737. }
  738.  
  739. int no_phantom_trace(char *rest)
  740. {
  741.     phantom_location = -1;
  742.     trace_lo = -1;
  743.     printf("the phantom goes to sleep.\n");
  744.     if (logging_fp == NULL)
  745.         return OK;
  746.     fclose(logging_fp);
  747.     logging_fp = NULL;
  748.     return OK;
  749. }
  750.  
  751. int cd(char *rest)
  752. {
  753.  
  754.     char *first;
  755.     char path[200];
  756.  
  757.     first = rest;
  758.     rest = split(rest);
  759.     if (*first != '\0') {
  760.         if (chdir(first)) {
  761.             perror("cd");
  762.             printf("CWD remains ");
  763.         }
  764.     }
  765. #ifdef NeXT
  766.     printf("%s\n",getwd(path));
  767. #else
  768.     printf("%s\n",getcwd(path,198));
  769. #endif
  770.  
  771.     return OK;
  772. }
  773.  
  774. int map(char *rest)
  775. {
  776.     map_to_upper = !map_to_upper;
  777.     printf("Uppercase Mapping is %s\n",(map_to_upper)?"On":"Off");
  778.     return OK;
  779. }
  780.  
  781. int sex(char *rest)
  782. {
  783.     printf("You'll need a real Apple for that sort of thing\n");
  784.     return OK;
  785. }
  786.  
  787.  
  788. int help(char *rest)
  789. {
  790.     printf("![command]        Escape to Unix\n");
  791.     printf(".            Display Current Pc Point\n");
  792.     printf("bload file addr        load binary file into mem at addr\n");
  793.     printf("breakpoint [addr]    Set the Breakpoint to addr\n");
  794.     printf("bsave file start end    Save Memory from start to end in file\n");
  795.     printf("cd [directory]        Set/Show Current Working Directory\n");
  796.     printf("cl[cdinvz]        Clear appropriate Status Bit\n");
  797.     printf("continue        Resume Execution of Emulator\n");
  798.     printf("deposit addr [val]+    Put val(s) into addr\n");
  799.     printf("dup [l|p]        duplicate top of stack into l or p\n");
  800.     printf("escape char        set escape char to be char \n");
  801.     printf("examine addr        Display Value in addr\n");
  802.     printf("insert file drive#    Make file disk in drive#\n");
  803.     printf("jmp addr        Make Pc=addr\n");
  804.     printf("ld[asxy] val        Load Register with val\n");
  805.     printf("list [addr] [addr]    Dissassemble at point or addr\n");
  806.     printf("map            Toggle lower -> upper case mapping\n");
  807.     printf("nobreak            Turn off breakpoint\n");
  808.     printf("pop [l|p]        get p or l from top of stack\n");
  809.     printf("push [l|p|<addr>    push l,p, or hex addr on stack\n");
  810.     printf("reset            Pc = Apple Reset Vector\n");
  811.     printf("se[cdinvz]        Set appropriate Status Flag\n");
  812.     printf("trace [addr] [addr]    Trace Between addresses/display trace point\n");
  813.     return OK;
  814. }
  815.  
  816. int set_escape_char(char *rest)
  817. {
  818.     if (*rest != '\0')
  819.         escape_char = *rest;
  820.     printf("escape character is ");
  821.     if (isprint(escape_char))
  822.         printf("%c",(int)escape_char);
  823.     else 
  824.         printf("^%c",(char)escape_char+64);
  825.     printf(" (0x%.2X)",(int)escape_char);
  826.     printf("\n");
  827.     return(OK);
  828. }
  829.  
  830. int disk_names(char *rest)
  831. {
  832.  
  833.     printf("drive 1: %s\n", disk[0] >= 0 ? diskname[0] : "empty");
  834.     printf("drive 2: %s\n", disk[1] >= 0 ? diskname[1] : "empty");
  835.     return(OK);
  836. }
  837.