This is jump.c in view mode; [Download] [Up]
/* * 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 intended 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; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.