home *** CD-ROM | disk | FTP | other *** search
- /*
- * a2, an Apple II emulator in C
- * (c) Copyright 1990 by Rich Skrenta
- *
- * Command line interface written by Tom Markson
- *
- * Distribution agreement:
- *
- * You may freely copy or redistribute this software, so long
- * as there is no profit made from its use, sale, trade or
- * reproduction. You may not change this copyright notice,
- * and it must be included prominently in any copy made.
- *
- * Send emulator related mail to: skrenta@blekko.commodore.com
- * skrenta@blekko.uucp
- */
-
-
- #include <stdio.h>
- #include <fcntl.h>
- #include "a2.h"
-
- #define jump_check(a,b,c,d) (mem[Pc]==a && mem[Pc+1]==b && mem[Pc+2]==c && mem[Pc+3]==d)
-
- /*
- * In order to improve performance, we intercept the PC on JSR's
- * and JMP's to certain locations and handled the intented function
- * in C instead of letting the emulator interpret 6502.
- *
- * This is done for video output, to produce an acceptable scroll;
- * for the boot prom, so it crashes if there is no disk in the drive;
- * and for other miscellaneous routines such as WAIT for speed.
- *
- * In most cases the interceptor routine checks to see if the code it's
- * intercepting looks like what it thinks should be there; it doesn't
- * snatch the PC if the first four bytes of the routine don't match.
- */
-
-
- #define I_WAIT 1 /* defeat ROM WAIT routine */
- #define I_PRODOS 2 /* Prodos high level intercept */
- #define I_RWTS 3 /* DOS 3.3 high-level intercept */
- #define I_BELL 4 /* don't toggle C030, output a bell */
- #define I_VIDOUT 5 /* speeds up scrolling tremendously */
- #define I_BOOT 6 /* crash if no disk on boot */
- #define I_BOOTWAIT 7 /* defeat delay loops in DOS boot */
- #define I_BOOTPATCH 8 /* patch dos for fast raw access */
-
-
- extern int map_to_upper;
- extern unsigned char disk_ref();
-
-
- set_special_jumps() {
- extern int set_c0();
- extern int set_writep();
-
- mem[0x43] = 0x60; /* for ProDos boot */
-
- jmp_tbl[0xBD00] = I_RWTS;
- jmp_tbl[0xC600] = I_BOOT;
- jmp_tbl[0xC680] = I_PRODOS; /* patched into boot prom below */
- jmp_tbl[0x9D84] = I_BOOTPATCH; /* fast raw dos access */
- jmp_tbl[0xFBD9] = I_BELL;
- jmp_tbl[0xFBFD] = I_VIDOUT;
- jmp_tbl[0xFCA8] = I_WAIT;
-
- jmp_tbl[0x3A00] = I_BOOTWAIT;
-
- mem_set[0xC0] = set_c0;
- mem_set[0xC6] = set_writep; /* write protect disk prom */
-
- #if 0
- mem[0xC600] = 0; /* flag for boot interception */
- mem[0xC601] = 0x20; /* disk prom magic number */
- mem[0xC603] = 0x00;
- mem[0xC605] = 0x03;
- mem[0xC607] = 0x3C;
- #endif
-
- /*
- * Patch boot rom for fake Prodos driver
- */
-
- mem[0xC6FF] = 0x80; /* C680 is driver address */
- mem[0xC6FE] = 0x1F; /* info about device */
-
- screen_setup();
- }
-
-
- jump(key)
- int key;
- {
- int i;
-
- switch (key) {
- case I_WAIT: /* FCA8 */
- if (jump_check(0x38, 0x48, 0xE9, 0x01)) {
- A = 0;
- N = 0;
- V = 0;
- C = 1;
- DO_RTS;
- }
- break;
-
- case I_PRODOS: /* C680 */
- prodos();
- break;
-
- case I_RWTS: /* BD00 */
- if (jump_check(0x84, 0x48, 0x85, 0x49))
- rwts();
- break;
-
- case I_BELL: /* FBD9 */
- if (jump_check(0x60, 0x87, 0xD0, 0x12)) {
- putchar(7);
- fflush(stdout);
- DO_RTS;
- }
- break;
-
- case I_VIDOUT: /* FBFD */
- if (jump_check(0xC9, 0xA0, 0xB0, 0xEF))
- vidout();
- break;
-
- case I_BOOT: /* C600 */
- if (disk[0] < 0) {
- info("boot: no disk");
- PCINC; /* BRK into the monitor */
- push(high(Pc));
- push(low(Pc));
- B = 1;
- push(get_status());
- Pc = mem[0xFFFE] | (mem[0xFFFF] << 8);
- return;
- }
- info("boot");
-
- /*
- * We read the second half of a 512 byte block in case we're
- * booting something that depends on this being a newer boot prom
- */
-
- drive = 0;
- read_disk(0, 14, &mem[0x900]);
- break;
-
- /*
- * Standard DOS 3.3 has some pretty gross delay loops in its
- * boot code. The following patches defeat two of them.
- * This could be dangerous; it seems to work, but DOS's original
- * side effects are not maintained. Comment out the jmp_tbl assignment
- * of I_BOOTWAIT above if you are distrustful.
- *
- * Interesting. Dos relocates the patches when it moves into higher
- * memory. If you boot with a fast-booting dos that doesn't have the
- * delays at 3A00, but still has them at BA00 & BD9E when it starts
- * up, it will be slow if you turn off RWTS interception and use the
- * raw interface. However, slow-booting real DOS that gets patched
- * while it's booting will have a faster raw interface, since it
- * relocated the patches...
- */
-
- case I_BOOTWAIT: /* 3A00 */
- if (jump_check(0xA2, 0x11, 0xCA, 0xD0)) {
- mem[0x3A00] = 0x60; /* RTS */
- if (mem[0x3D9E] == 0xA0
- && mem[0x3D9F] == 0x12
- && mem[0x3DA0] == 0x88) {
- mem[0x3D9E] = 0x4C; /* JMP past it */
- mem[0x3D9F] = 0xAB;
- mem[0x3DA0] = 0x3D; /* gets relocated */
- }
- }
- break;
-
- /*
- * This one is unnecessary since we do high-level RWTS interception
- */
-
- case I_BOOTPATCH: /* 9D84 */
- if (jump_check(0xAD, 0xE9, 0xB7, 0x4A)) {
- if (mem[0xBA00] == 0xA2
- && mem[0xBA01] == 0x11
- && mem[0xBA02] == 0xCA) {
- mem[0xBA00] = 0x60; /* RTS */
- if (mem[0xBD9E] == 0xA0
- && mem[0xBD9F] == 0x12
- && mem[0xBDA0] == 0x88) {
- mem[0xBD9E] = 0x4C;
- mem[0xBD9F] = 0xAB;
- mem[0xBDA0] = 0xBD;
- }
- }
- }
- break;
-
- default:
- fprintf(stderr, "bad jump intercept key: %d\n", key);
- assert(FALSE);
- }
- }
-
-
- static int key_clear = TRUE;
- static unsigned char last_key = 0;
- static unsigned char temp_key;
-
- extern int save_flags;
-
- unsigned char
- mem_map(a)
- unsigned short a;
- {
-
- switch (a) {
- case 0xC000:
- if (key_clear) {
- fcntl (0, F_SETFL, save_flags | O_NDELAY);
-
- if (read (0, &temp_key, 1) == 1) {
- key_clear = FALSE;
- if (temp_key == '\n')
- temp_key = '\r';
- else if (temp_key == 127)
- temp_key = 8;
- if (map_to_upper)
- temp_key = toupper(temp_key);
- last_key = temp_key | 0x80;
- }
-
- fcntl (0, F_SETFL, save_flags);
- }
- return(last_key);
-
- case 0xC010:
- key_clear = TRUE;
- last_key &= 0x7F;
- return(0); /* what should this be? */
-
- case 0xC011:
- if (bank2_enable)
- return(0xFF);
- return(0x00);
-
- case 0xC012:
- if (ram_read)
- return(0xFF);
- return(0x00);
-
- case 0xC080: case 0xC081: case 0xC082: case 0xC083:
- case 0xC088: case 0xC089: case 0xC08A: case 0xC08B:
- ram_card(a);
- return(0x00);
-
- /*
- * Slot 6 Disk II memory map
- */
-
- case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
- case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
- case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
- case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
- return( disk_ref(a, 0) );
-
- #if 0
- /*
- * Keep the boot prom magic number from appearing if there is
- * no disk in the drive
- */
-
- case 0xC600:
- case 0xC601:
- if (disk[0] < 0)
- return(0);
- break;
- #endif
-
- }
-
- return(mem[a]); /* default */
- }
-
-
- set_c0(a, n)
- unsigned short a;
- unsigned char n;
- {
-
- switch (a & 0xFF) {
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15:
- case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B:
- case 0x1C: case 0x1D: case 0x1E: case 0x1F:
- key_clear = TRUE;
- last_key &= 0x7F;
- break;
-
- case 0x80: case 0x81: case 0x82: case 0x83:
- case 0x88: case 0x89: case 0x8A: case 0x8B:
- ram_card(a);
- break;
-
- /*
- * Slot 6 Disk II memory map
- */
-
- case 0xC0E0: case 0xC0E1: case 0xC0E2: case 0xC0E3:
- case 0xC0E4: case 0xC0E5: case 0xC0E6: case 0xC0E7:
- case 0xC0E8: case 0xC0E9: case 0xC0EA: case 0xC0EB:
- case 0xC0EC: case 0xC0ED: case 0xC0EE: case 0xC0EF:
- disk_ref(a, n);
- break;
-
- default:
- mem[a] = n;
- }
- }
-
-
-