From dc46480aa4244c8053e35e593a910689394cfe12 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 23 Dec 2016 03:16:24 +0100 Subject: [PATCH] Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes. --- nvr/ami386dx_opti495.nvr | Bin 0 -> 128 bytes nvr/mr386dx_opti495.nvr | Bin 0 -> 128 bytes src/386.c | 3 +- src/386_dynarec.c | 154 ++++- src/386_dynarec_ops.c | 5 + src/386_ops.h | 8 + src/808x.c | 5 +- src/Makefile.mingw | 6 +- src/Makefile.mingw64 | 6 +- src/aha154x.c | 865 ++++++++++++++++---------- src/aha154x.h | 2 +- src/amstrad.c | 71 ++- src/amstrad.h | 4 +- src/cdrom-ioctl-linux.c | 20 +- src/cdrom-ioctl.c | 321 ++++++---- src/cdrom-iso.c | 31 +- src/cdrom-null.c | 8 +- src/cdrom.h | 5 +- src/codegen_ops.c | 36 +- src/codegen_ops_fpu.h | 36 ++ src/codegen_ops_misc.h | 15 +- src/codegen_ops_mov.h | 150 +++++ src/codegen_ops_stack.h | 33 + src/codegen_ops_x86-64.h | 108 +++- src/codegen_ops_x86.h | 175 ++++++ src/codegen_x86.c | 40 +- src/cpu.c | 594 ++++++++++-------- src/cpu.h | 12 + src/device.c | 65 +- src/device.h | 6 +- src/disc.c | 67 +- src/disc.h | 23 +- src/disc_86f.c | 504 ++++++++------- src/disc_86f.h | 2 + src/disc_fdi.c | 16 +- src/disc_imd.c | 2 +- src/disc_img.c | 33 +- src/disc_td0.c | 2 +- src/dma.c | 450 +++++++++----- src/dma.h | 4 +- src/dosbox/vid_cga_comp.c | 125 ++-- src/dosbox/vid_cga_comp.h | 10 +- src/fdc.c | 569 ++++++++++++----- src/fdc.h | 9 + src/fdc37c665.c | 4 +- src/fdc37c932fr.c | 13 +- src/fdd.c | 73 ++- src/gameport.c | 9 +- src/ibm.h | 81 +-- src/ide.c | 554 ++++++++++------- src/ide.h | 2 +- src/intel.c | 2 + src/intel_flash.c | 15 + src/keyboard_at.c | 23 +- src/keyboard_at.h | 2 +- src/keyboard_olim24.c | 141 +++-- src/keyboard_olim24.h | 5 +- src/mem.c | 190 ++++-- src/mem.h | 3 +- src/model.c | 243 ++++---- src/model.h | 14 +- src/mouse.c | 51 +- src/mouse.h | 28 +- src/mouse_amstrad.c | 63 -- src/mouse_amstrad.h | 4 - src/mouse_ps2.c | 211 ++++--- src/mouse_ps2.h | 6 +- src/mouse_serial.c | 95 +-- src/mouse_serial.h | 5 +- src/nvr.c | 24 +- src/{opti.c => opti495.c} | 45 +- src/opti495.h | 1 + src/pc.c | 87 ++- src/pc.rc | 242 +++++--- src/pc87306.c | 170 ++++-- src/pci.c | 12 +- src/pic.c | 30 +- src/piix.c | 124 +++- src/pit.c | 1 - src/plat-mouse.h | 2 +- src/ps1.c | 3 + src/resources.h | 85 ++- src/scat.c | 1 + src/scattergather.c | 37 +- src/scattergather.h | 2 +- src/scsi.c | 85 +-- src/scsi.h | 20 +- src/scsi_cdrom.c | 1019 ++++++++++++++++++++++--------- src/serial.c | 26 +- src/serial.h | 5 +- src/sio.c | 80 ++- src/sis85c471.c | 2 - src/sound.h | 2 - src/um8669f.c | 3 - src/vid_cga.c | 6 +- src/vid_ega.c | 3 - src/vid_et4000w32.c | 11 +- src/vid_nv_riva128.c | 383 +++++++++++- src/vid_nv_riva128.h | 1 + src/vid_paradise.c | 2 - src/vid_pcjr.c | 126 ++-- src/vid_pcjr.h | 4 +- src/vid_svga.c | 7 +- src/vid_tandy.c | 140 +++-- src/vid_tandy.h | 6 +- src/vid_voodoo.c | 280 ++++++--- src/vid_voodoo_codegen_x86-64.h | 42 +- src/vid_voodoo_codegen_x86.h | 38 +- src/vid_wy700.c | 994 ++++++++++++++++++++++++++++++ src/vid_wy700.h | 1 + src/video.c | 68 ++- src/video.h | 2 +- src/w83877f.c | 8 +- src/win-config.c | 253 +++++--- src/win-hdconf.c | 296 ++++++++- src/win-mouse.cc | 10 +- src/win-status.c | 2 +- src/win.c | 77 ++- src/x86_ops_arith.h | 89 ++- src/x86_ops_bcd.h | 9 +- src/x86_ops_bit.h | 16 + src/x86_ops_bitscan.h | 27 +- src/x86_ops_call.h | 65 +- src/x86_ops_flag.h | 24 +- src/x86_ops_inc_dec.h | 3 + src/x86_ops_int.h | 8 + src/x86_ops_io.h | 16 +- src/x86_ops_jump.h | 49 ++ src/x86_ops_misc.h | 59 +- src/x86_ops_mov.h | 98 ++- src/x86_ops_mov_ctrl.h | 28 + src/x86_ops_mov_seg.h | 18 + src/x86_ops_movx.h | 14 + src/x86_ops_mul.h | 12 + src/x86_ops_pmode.h | 55 +- src/x86_ops_prefix.h | 6 + src/x86_ops_ret.h | 35 ++ src/x86_ops_shift.h | 73 ++- src/x86_ops_stack.h | 36 +- src/x86_ops_string.h | 42 ++ src/x86_ops_xchg.h | 21 + src/x86seg.c | 1 + 142 files changed, 8778 insertions(+), 3331 deletions(-) create mode 100644 nvr/ami386dx_opti495.nvr create mode 100644 nvr/mr386dx_opti495.nvr delete mode 100644 src/mouse_amstrad.c delete mode 100644 src/mouse_amstrad.h rename src/{opti.c => opti495.c} (84%) create mode 100644 src/opti495.h create mode 100644 src/vid_wy700.c create mode 100644 src/vid_wy700.h diff --git a/nvr/ami386dx_opti495.nvr b/nvr/ami386dx_opti495.nvr new file mode 100644 index 0000000000000000000000000000000000000000..dca4bd2693dd57ef29ce97be3e2598e9cbbd3c62 GIT binary patch literal 128 zcmZQ#@MKVAU{x0sQ)3GF&&c4go56s$fr&wefuVvyfPsO7fx(^u2C|t27-S?@Fz_=p aK!jMiVN$qgCWj{sS3e3gGyt{y#{vKVt{*=D literal 0 HcmV?d00001 diff --git a/nvr/mr386dx_opti495.nvr b/nvr/mr386dx_opti495.nvr new file mode 100644 index 0000000000000000000000000000000000000000..9146987cb0319cca87dedd333b0d99c078f375fd GIT binary patch literal 128 zcmWGJ5PU%K0IRy7m>N^Te`W@Uo(~+X4NMF&`V18k3;zGNxBm|W3m61|^a2Ln(+o0_ i$;=;^KQu7@|F6Ix=*Ym#;MAb-fB^`s`~yL1Ndo}auT6CT literal 0 HcmV?d00001 diff --git a/src/386.c b/src/386.c index 526a659c5..2029c1afd 100644 --- a/src/386.c +++ b/src/386.c @@ -29,7 +29,6 @@ extern int cpl_override; int has_fpu; extern int fpucount; -int times; uint16_t rds; uint16_t ea_rseg; @@ -40,7 +39,6 @@ int cgate32; uint8_t romext[32768]; uint8_t *ram,*rom; -uint16_t biosmask; uint32_t rmdat32; #define rmdat rmdat32 @@ -289,6 +287,7 @@ dontprint=0; { cpu_state.abrt = 0; softresetx86(); + cpu_set_edx(); pclog("Triple fault - reset\n"); } } diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 9bad1d323..f5e327841 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -38,7 +38,6 @@ int cpl_override=0; int has_fpu; int fpucount=0; -int times; uint16_t rds; uint16_t ea_rseg; @@ -48,7 +47,6 @@ int cgate32; uint8_t romext[32768]; uint8_t *ram,*rom; -uint16_t biosmask; uint32_t rmdat32; uint32_t backupregs[16]; @@ -135,6 +133,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = cpu_state.eaaddr; } static inline void fetch_ea_16_long(uint32_t rmdat) @@ -177,6 +176,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = cpu_state.eaaddr; } #define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; } @@ -275,6 +275,89 @@ void x86illegal() x86_int(6); } +/*Prefetch emulation is a fairly simplistic model: + - All instruction bytes must be fetched before it starts. + - Cycles used for non-instruction memory accesses are counted and subtracted + from the total cycles taken + - Any remaining cycles are used to refill the prefetch queue. + + Note that this is only used for 286 / 386 systems. It is disabled when the + internal cache on 486+ CPUs is enabled. +*/ +static int prefetch_bytes = 0; +static int prefetch_prefixes = 0; + +static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32) +{ + int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l; + + if (instr_cycles < mem_cycles) + instr_cycles = mem_cycles; + + prefetch_bytes -= prefetch_prefixes; + prefetch_bytes -= bytes; + if (modrm != -1) + { + if (ea32) + { + if ((modrm & 7) == 4) + { + if ((modrm & 0x700) == 0x500) + prefetch_bytes -= 5; + else if ((modrm & 0xc0) == 0x40) + prefetch_bytes -= 2; + else if ((modrm & 0xc0) == 0x80) + prefetch_bytes -= 5; + } + else + { + if ((modrm & 0xc7) == 0x05) + prefetch_bytes -= 4; + else if ((modrm & 0xc0) == 0x40) + prefetch_bytes--; + else if ((modrm & 0xc0) == 0x80) + prefetch_bytes -= 4; + } + } + else + { + if ((modrm & 0xc7) == 0x06) + prefetch_bytes -= 2; + else if ((modrm & 0xc0) != 0xc0) + prefetch_bytes -= ((modrm & 0xc0) >> 6); + } + } + + /* Fill up prefetch queue */ + while (prefetch_bytes < 0) + { + prefetch_bytes += cpu_prefetch_width; + cycles -= cpu_prefetch_cycles; + } + + /* Subtract cycles used for memory access by instruction */ + instr_cycles -= mem_cycles; + + while (instr_cycles >= cpu_prefetch_cycles) + { + prefetch_bytes += cpu_prefetch_width; + instr_cycles -= cpu_prefetch_cycles; + } + + prefetch_prefixes = 0; +} + +static void prefetch_flush() +{ + prefetch_bytes = 0; +} + +#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \ + do { if (cpu_prefetch_cycles) prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); } while (0) + +#define PREFETCH_PREFIX() prefetch_prefixes++ +#define PREFETCH_FLUSH() prefetch_flush() + int rep386(int fv) { @@ -292,6 +375,7 @@ int rep386(int fv) that high frequency timers still work okay. This amount is different for interpreter and recompiler*/ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); + int reads = 0, reads_l = 0, writes = 0, writes_l = 0, total_cycles = 0; if (trap) cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ @@ -320,28 +404,36 @@ int rep386(int fv) break; case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/ cpu_state.ea_seg = &_es; + PREFETCH_PREFIX(); goto startrep; break; case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/ cpu_state.ea_seg = &_cs; + PREFETCH_PREFIX(); goto startrep; case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/ cpu_state.ea_seg = &_ss; + PREFETCH_PREFIX(); goto startrep; case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/ cpu_state.ea_seg = &_ds; + PREFETCH_PREFIX(); goto startrep; case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/ cpu_state.ea_seg = &_fs; + PREFETCH_PREFIX(); goto startrep; case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/ cpu_state.ea_seg = &_gs; + PREFETCH_PREFIX(); goto startrep; case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/ rep32 = (rep32 & 0x200) | ((use32 ^ 0x100) & 0x100); + PREFETCH_PREFIX(); goto startrep; case 0x67: case 0x167: case 0x267: case 0x367: /*Address size prefix*/ rep32 = (rep32 & 0x100) | ((use32 ^ 0x200) & 0x200); + PREFETCH_PREFIX(); goto startrep; case 0x6C: case 0x16C: /*REP INSB*/ // cpu_notreps++; @@ -355,6 +447,7 @@ int rep386(int fv) else DI++; c--; cycles-=15; + reads++; writes++; total_cycles += 15; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -371,6 +464,7 @@ int rep386(int fv) else EDI++; c--; cycles-=15; + reads++; writes++; total_cycles += 15; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -387,6 +481,7 @@ int rep386(int fv) else DI+=2; c--; cycles-=15; + reads++; writes++; total_cycles += 15; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -402,6 +497,7 @@ int rep386(int fv) else DI+=4; c--; cycles-=15; + reads_l++; writes_l++; total_cycles += 15; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -417,6 +513,7 @@ int rep386(int fv) else EDI+=2; c--; cycles-=15; + reads++; writes++; total_cycles += 15; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -432,6 +529,7 @@ int rep386(int fv) else EDI+=4; c--; cycles-=15; + reads_l++; writes_l++; total_cycles += 15; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -448,6 +546,7 @@ int rep386(int fv) else SI++; c--; cycles-=14; + reads++; writes++; total_cycles += 14; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -464,6 +563,7 @@ int rep386(int fv) else ESI++; c--; cycles-=14; + reads++; writes++; total_cycles += 14; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -480,6 +580,7 @@ int rep386(int fv) else SI+=2; c--; cycles-=14; + reads++; writes++; total_cycles += 14; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -495,6 +596,7 @@ int rep386(int fv) else SI += 4; c--; cycles -= 14; + reads_l++; writes_l++; total_cycles += 14; } if (c > 0) { firstrepcycle = 0; cpu_state.pc = ipc; } else firstrepcycle = 1; @@ -510,6 +612,7 @@ int rep386(int fv) else ESI+=2; c--; cycles-=14; + reads++; writes++; total_cycles += 14; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -525,6 +628,7 @@ int rep386(int fv) else ESI += 4; c--; cycles -= 14; + reads_l++; writes_l++; total_cycles += 14; } if (c > 0) { firstrepcycle = 0; cpu_state.pc = ipc; } else firstrepcycle = 1; @@ -545,6 +649,7 @@ int rep386(int fv) c--; cycles-=(is486)?3:4; ins++; + reads++; writes++; total_cycles += is486 ? 3 : 4; if (cycles < cycles_end) break; } @@ -563,6 +668,7 @@ int rep386(int fv) c--; cycles-=(is486)?3:4; ins++; + reads++; writes++; total_cycles += is486 ? 3 : 4; if (cycles < cycles_end) break; } @@ -581,6 +687,7 @@ int rep386(int fv) c--; cycles-=(is486)?3:4; ins++; + reads++; writes++; total_cycles += is486 ? 3 : 4; if (cycles < cycles_end) break; } @@ -600,6 +707,7 @@ int rep386(int fv) c--; cycles-=(is486)?3:4; ins++; + reads_l++; writes_l++; total_cycles += is486 ? 3 : 4; if (cycles < cycles_end) break; } @@ -619,6 +727,7 @@ int rep386(int fv) c--; cycles-=(is486)?3:4; ins++; + reads++; writes++; total_cycles += is486 ? 3 : 4; if (cycles < cycles_end) break; } @@ -639,6 +748,7 @@ int rep386(int fv) c--; cycles-=(is486)?3:4; ins++; + reads_l++; writes_l++; total_cycles += is486 ? 3 : 4; if (cycles < cycles_end) break; } @@ -658,6 +768,7 @@ int rep386(int fv) else { DI++; SI++; } c--; cycles-=(is486)?7:9; + reads += 2; total_cycles += is486 ? 7 : 9; setsub8(temp,temp2); tempz = (ZF_SET()) ? 1 : 0; } @@ -676,6 +787,7 @@ int rep386(int fv) else { EDI++; ESI++; } c--; cycles-=(is486)?7:9; + reads += 2; total_cycles += is486 ? 7 : 9; setsub8(temp,temp2); tempz = (ZF_SET()) ? 1 : 0; } @@ -697,6 +809,7 @@ int rep386(int fv) else { DI+=2; SI+=2; } c--; cycles-=(is486)?7:9; + reads += 2; total_cycles += is486 ? 7 : 9; setsub16(tempw,tempw2); tempz = (ZF_SET()) ? 1 : 0; } @@ -715,6 +828,7 @@ int rep386(int fv) else { DI+=4; SI+=4; } c--; cycles-=(is486)?7:9; + reads_l += 2; total_cycles += is486 ? 7 : 9; setsub32(templ,templ2); tempz = (ZF_SET()) ? 1 : 0; } @@ -733,6 +847,7 @@ int rep386(int fv) else { EDI+=2; ESI+=2; } c--; cycles-=(is486)?7:9; + reads += 2; total_cycles += is486 ? 7 : 9; setsub16(tempw,tempw2); tempz = (ZF_SET()) ? 1 : 0; } @@ -751,6 +866,7 @@ int rep386(int fv) else { EDI+=4; ESI+=4; } c--; cycles-=(is486)?7:9; + reads_l += 2; total_cycles += is486 ? 7 : 9; setsub32(templ,templ2); tempz = (ZF_SET()) ? 1 : 0; } @@ -768,6 +884,7 @@ int rep386(int fv) else DI++; c--; cycles-=(is486)?4:5; + writes++; total_cycles += is486 ? 4 : 5; ins++; if (cycles < cycles_end) break; @@ -786,6 +903,7 @@ int rep386(int fv) else EDI++; c--; cycles-=(is486)?4:5; + writes++; total_cycles += is486 ? 4 : 5; ins++; if (cycles < cycles_end) break; @@ -804,6 +922,7 @@ int rep386(int fv) else DI+=2; c--; cycles-=(is486)?4:5; + writes++; total_cycles += is486 ? 4 : 5; ins++; if (cycles < cycles_end) break; @@ -822,6 +941,7 @@ int rep386(int fv) else EDI+=2; c--; cycles-=(is486)?4:5; + writes++; total_cycles += is486 ? 4 : 5; ins++; if (cycles < cycles_end) break; @@ -840,6 +960,7 @@ int rep386(int fv) else DI+=4; c--; cycles-=(is486)?4:5; + writes_l++; total_cycles += is486 ? 4 : 5; ins++; if (cycles < cycles_end) break; @@ -858,6 +979,7 @@ int rep386(int fv) else EDI+=4; c--; cycles-=(is486)?4:5; + writes_l++; total_cycles += is486 ? 4 : 5; ins++; if (cycles < cycles_end) break; @@ -877,6 +999,7 @@ int rep386(int fv) else SI++; c--; cycles-=5; + reads++; total_cycles += 5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -892,6 +1015,7 @@ int rep386(int fv) else ESI++; c--; cycles-=5; + reads++; total_cycles += 5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -907,6 +1031,7 @@ int rep386(int fv) else SI+=2; c--; cycles-=5; + reads++; total_cycles += 5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -922,6 +1047,7 @@ int rep386(int fv) else SI+=4; c--; cycles-=5; + reads_l++; total_cycles += 5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -937,6 +1063,7 @@ int rep386(int fv) else ESI+=2; c--; cycles-=5; + reads++; total_cycles += 5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -952,6 +1079,7 @@ int rep386(int fv) else ESI+=4; c--; cycles-=5; + reads_l++; total_cycles += 5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; } else firstrepcycle=1; @@ -971,6 +1099,7 @@ int rep386(int fv) else DI++; c--; cycles-=(is486)?5:8; + reads++; total_cycles += is486 ? 5 : 8; ins++; if (cycles < cycles_end) break; @@ -995,6 +1124,7 @@ int rep386(int fv) else EDI++; c--; cycles-=(is486)?5:8; + reads++; total_cycles += is486 ? 5 : 8; ins++; if (cycles < cycles_end) break; @@ -1017,6 +1147,7 @@ int rep386(int fv) else DI+=2; c--; cycles-=(is486)?5:8; + reads++; total_cycles += is486 ? 5 : 8; ins++; if (cycles < cycles_end) break; @@ -1039,6 +1170,7 @@ int rep386(int fv) else DI+=4; c--; cycles-=(is486)?5:8; + reads_l++; total_cycles += is486 ? 5 : 8; ins++; if (cycles < cycles_end) break; @@ -1061,6 +1193,7 @@ int rep386(int fv) else EDI+=2; c--; cycles-=(is486)?5:8; + reads++; total_cycles += is486 ? 5 : 8; ins++; if (cycles < cycles_end) break; @@ -1083,6 +1216,7 @@ int rep386(int fv) else EDI+=4; c--; cycles-=(is486)?5:8; + reads_l++; total_cycles += is486 ? 5 : 8; ins++; if (cycles < cycles_end) break; @@ -1101,6 +1235,7 @@ int rep386(int fv) if (rep32&0x200) ECX=c; else CX=c; CPU_BLOCK_END(); + PREFETCH_RUN(total_cycles, 1, -1, reads, reads_l, writes, writes_l, 0); return cpu_state.abrt; //pclog("rep cpu_block_end=%d %p\n", cpu_block_end, (void *)&cpu_block_end); // if (output) pclog("%03X %03X\n",rep32,use32); @@ -1310,7 +1445,7 @@ void exec386_dynarec(int cycs) if (page->code_present_mask & mask) { /*Walk page tree to see if we find the correct block*/ - codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); + codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); if (new_block) { valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && @@ -1559,6 +1694,7 @@ inrecomp=0; { cpu_state.abrt = 0; softresetx86(); + cpu_set_edx(); pclog("Triple fault - reset\n"); } } @@ -1597,10 +1733,18 @@ inrecomp=0; flags_rebuild(); if (msw&1) { + /* if (temp == 0x0E) + { + pclog("Servicing FDC interupt (p)!\n"); + } */ pmodeint(temp,0); } else { + /* if (temp == 0x0E) + { + pclog("Servicing FDC interupt (r)!\n"); + } */ writememw(ss,(SP-2)&0xFFFF,flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -1613,6 +1757,10 @@ inrecomp=0; loadcs(readmemw(0,addr+2)); } } + /* else + { + pclog("Servicing pending interrupt 0xFF (!)!\n"); + } */ } } timer_end_period(cycles << TIMER_SHIFT); diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index bb3d467c2..bf2fe7ad4 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -28,6 +28,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = cpu_state.eaaddr; } static inline void fetch_ea_16_long(uint32_t rmdat) @@ -43,12 +44,16 @@ static inline void fetch_ea_16_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = cpu_state.eaaddr; } #define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat); #define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat); +#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32) +#define PREFETCH_PREFIX() +#define PREFETCH_FLUSH() #define OP_TABLE(name) dynarec_ops_ ## name #define CLOCK_CYCLES(c) diff --git a/src/386_ops.h b/src/386_ops.h index 26722133d..15ce9349a 100644 --- a/src/386_ops.h +++ b/src/386_ops.h @@ -175,6 +175,8 @@ static int op0F_w_a16(uint32_t fetchdat) cpu_state.pc++; // pclog("A16W: 0F %02X\n", opcode); + PREFETCH_PREFIX(); + return x86_opcodes_0f[opcode](fetchdat >> 8); } static int op0F_l_a16(uint32_t fetchdat) @@ -184,6 +186,8 @@ static int op0F_l_a16(uint32_t fetchdat) cpu_state.pc++; // pclog("A16L: 0F %02X\n", opcode); + PREFETCH_PREFIX(); + return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8); } static int op0F_w_a32(uint32_t fetchdat) @@ -193,6 +197,8 @@ static int op0F_w_a32(uint32_t fetchdat) cpu_state.pc++; // pclog("A32W: 0F %02X\n", opcode); + PREFETCH_PREFIX(); + return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8); } static int op0F_l_a32(uint32_t fetchdat) @@ -202,6 +208,8 @@ static int op0F_l_a32(uint32_t fetchdat) cpu_state.pc++; // pclog("A32L: 0F %02X\n", opcode); + PREFETCH_PREFIX(); + return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); } diff --git a/src/808x.c b/src/808x.c index 7e0bceec6..36a4e1467 100644 --- a/src/808x.c +++ b/src/808x.c @@ -101,7 +101,6 @@ int oldcpl; int tempc; uint8_t opcode; -int times=0; uint16_t pc2,pc3; int noint=0; @@ -640,6 +639,8 @@ void resetx86() cr0 = 1 << 30; else cr0 = 0; + cpu_cache_int_enabled = 0; + cpu_update_waitstates(); cr4 = 0; eflags=0; cgate32=0; @@ -667,6 +668,7 @@ void resetx86() x86seg_reset(); codegen_reset(); x86_was_reset = 1; + port_92_clear_reset(); } void softresetx86() @@ -689,6 +691,7 @@ void softresetx86() idt.base = 0; x86seg_reset(); x86_was_reset = 1; + port_92_clear_reset(); } static void setznp8(uint8_t val) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 14eb041f2..8b0bba5e3 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -8,8 +8,8 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o aha154x cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \ i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ - keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_amstrad.o mouse_ps2.o \ - mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ + keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \ + mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ scat.o scattergather.o scsi.o scsi_cdrom.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ @@ -19,7 +19,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o aha154x vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ - vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ + vid_vga.o vid_wy700.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \ win-status.o win-video.o x86seg.o x87.o xtide.o pc.res DBOBJ = dbopl.o nukedopl.o vid_cga_comp.o diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index f119c400c..763838af4 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -8,8 +8,8 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o aha154x cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \ i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ - keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_amstrad.o mouse_ps2.o \ - mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ + keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \ + mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ scat.o scattergather.o scsi.o scsi_cdrom.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ @@ -19,7 +19,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o aha154x vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ - vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ + vid_vga.o vid_wy700.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \ win-status.o win-video.o x86seg.o x87.o xtide.o pc.res DBOBJ = dbopl.o nukedopl.o vid_cga_comp.o diff --git a/src/aha154x.c b/src/aha154x.c index 0efc1fd43..c4b921920 100644 --- a/src/aha154x.c +++ b/src/aha154x.c @@ -1,7 +1,13 @@ /* Copyright holders: SA1988 see COPYING for more details */ -/*Adaptec 154x SCSI emulation*/ +/*Adaptec 154x SCSI emulation and clones (including Buslogic ISA adapters)*/ + +/* +ToDo: +Improve support for DOS, Windows 3.x and Windows 9x as well as NT. +*/ + #include #include #include @@ -81,17 +87,75 @@ typedef struct #define CMD_RETSETUP 0x0D // return setup data #define CMD_ECHO 0x1F // ECHO command data +/** Structure for the INQUIRE_SETUP_INFORMATION reply. */ +typedef struct ReplyInquireSetupInformationSynchronousValue +{ + uint8_t uOffset : 4; + uint8_t uTransferPeriod : 3; + uint8_t fSynchronous : 1; +}ReplyInquireSetupInformationSynchronousValue; + +typedef struct ReplyInquireSetupInformation +{ + uint8_t fSynchronousInitiationEnabled : 1; + uint8_t fParityCheckingEnabled : 1; + uint8_t uReserved1 : 6; + uint8_t uBusTransferRate; + uint8_t uPreemptTimeOnBus; + uint8_t uTimeOffBus; + uint8_t cMailbox; + addr24 MailboxAddress; + ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8]; + uint8_t uDisconnectPermittedId0To7; + uint8_t uSignature; + uint8_t uCharacterD; + uint8_t uHostBusType; + uint8_t uWideTransferPermittedId0To7; + uint8_t uWideTransfersActiveId0To7; + ReplyInquireSetupInformationSynchronousValue SynchronousValuesId8To15[8]; + uint8_t uDisconnectPermittedId8To15; + uint8_t uReserved2; + uint8_t uWideTransferPermittedId8To15; + uint8_t uWideTransfersActiveId8To15; +} ReplyInquireSetupInformation; + +/** Structure for the INQUIRE_EXTENDED_SETUP_INFORMATION. */ +#pragma pack(1) +typedef struct ReplyInquireExtendedSetupInformation +{ + uint8_t uBusType; + uint8_t uBiosAddress; + uint16_t u16ScatterGatherLimit; + uint8_t cMailbox; + uint32_t uMailboxAddressBase; + uint8_t uReserved1 : 2; + uint8_t fFastEISA : 1; + uint8_t uReserved2 : 3; + uint8_t fLevelSensitiveInterrupt : 1; + uint8_t uReserved3 : 1; + uint8_t aFirmwareRevision[3]; + uint8_t fHostWideSCSI : 1; + uint8_t fHostDifferentialSCSI : 1; + uint8_t fHostSupportsSCAM : 1; + uint8_t fHostUltraSCSI : 1; + uint8_t fHostSmartTermination : 1; + uint8_t uReserved4 : 3; +} ReplyInquireExtendedSetupInformation; +#pragma pack() + typedef struct MailboxInit_t { uint8_t Count; addr24 Address; } MailboxInit_t; +#pragma pack(1) typedef struct MailboxInitExtended_t { uint8_t Count; uint32_t Address; } MailboxInitExtended_t; +#pragma pack() /////////////////////////////////////////////////////////////////////////////// // @@ -132,8 +196,22 @@ typedef struct Mailbox_t typedef struct Mailbox32_t { - uint8_t CmdStatus; uint32_t CCBPointer; + union + { + struct + { + uint8_t Reserved[3]; + uint8_t ActionCode; + } out; + struct + { + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Reserved; + uint8_t CompletionCode; + } in; + } u; } Mailbox32_t; @@ -205,7 +283,7 @@ typedef struct Mailbox32_t // // Byte 15 Target Status // -// See SCSI.H files for these statuses. +// See scsi.h files for these statuses. // // @@ -216,6 +294,29 @@ typedef struct Mailbox32_t // Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block // +typedef struct CCB32 +{ + uint8_t Opcode; + uint8_t Reserved1:3; + uint8_t ControlByte:2; + uint8_t TagQueued:1; + uint8_t QueueTag:2; + uint8_t CdbLength; + uint8_t RequestSenseLength; + uint32_t DataLength; + uint32_t DataPointer; + uint8_t Reserved2[2]; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Id; + uint8_t Lun:5; + uint8_t LegacyTagEnable:1; + uint8_t LegacyQueueTag:2; + uint8_t Cdb[12]; + uint8_t Reserved3[6]; + uint32_t SensePointer; +} CCB32; + typedef struct CCB { uint8_t Opcode; @@ -234,6 +335,28 @@ typedef struct CCB uint8_t Cdb[12]; } CCB; +typedef struct CCBC +{ + uint8_t Opcode; + uint8_t Pad1:3; + uint8_t ControlByte:2; + uint8_t Pad2:3; + uint8_t CdbLength; + uint8_t RequestSenseLength; + uint8_t Pad3[10]; + uint8_t HostStatus; + uint8_t TargetStatus; + uint8_t Pad4[2]; + uint8_t Cdb[12]; +} CCBC; + +typedef union CCBU +{ + CCB32 new; + CCB old; + CCBC common; +} CCBU; + /////////////////////////////////////////////////////////////////////////////// // // Scatter/Gather Segment List Definitions @@ -244,7 +367,13 @@ typedef struct CCB // Adapter limits // -#define MAX_SG_DESCRIPTORS 17 +#define MAX_SG_DESCRIPTORS 32 + +typedef struct SGE32 +{ + uint32_t Segment; + uint32_t SegmentPointer; +} SGE32; typedef struct SGE { @@ -254,17 +383,20 @@ typedef struct SGE typedef struct AdaptecRequests_t { - CCB CmdBlock; + CCBU CmdBlock; uint8_t *RequestSenseBuffer; uint32_t CCBPointer; + int Is24bit; } AdaptecRequests_t; typedef struct Adaptec_t { + rom_t BiosRom; AdaptecRequests_t AdaptecRequests; uint8_t Status; uint8_t Interrupt; uint8_t Geometry; + uint8_t Control; uint8_t Command; uint8_t CmdBuf[5]; uint8_t CmdParam; @@ -279,15 +411,11 @@ typedef struct Adaptec_t uint32_t MailboxInPosCur; int Irq; int DmaChannel; - int DmaPort1, DmaData1; - int DmaPort2, DmaData2; - int BusOn; - int BusOff; - int DmaSpeed; - int ScsiBios; + int IrqEnabled; + int Mbx24bit; } Adaptec_t; -Adaptec_t AdaptecLUN; +Adaptec_t AdaptecLUN[7]; int scsi_base = 0x330; int scsi_dma = 6; @@ -312,13 +440,7 @@ void AdaptecLog(const char *format, ...) fflush(stdout); } } - -/* static void AdaptecSetDMAChannel(int DmaPort1, int DmaData1, int DmaPort2, int DmaData2) -{ - dma_channel_write(DmaPort1, DmaData1); - dma_channel_write(DmaPort2, DmaData2); -} */ - + static void AdaptecClearInterrupt(Adaptec_t *Adaptec) { AdaptecLog("Adaptec: Clearing Interrupt 0x%02X\n", Adaptec->Interrupt); @@ -333,12 +455,23 @@ static void AdaptecReset(Adaptec_t *Adaptec) Adaptec->Command = 0xFF; Adaptec->CmdParam = 0; Adaptec->CmdParamLeft = 0; + Adaptec->IrqEnabled = 1; Adaptec->MailboxOutPosCur = 0; Adaptec->MailboxInPosCur = 0; AdaptecClearInterrupt(Adaptec); } +static void AdaptecResetControl(Adaptec_t *Adaptec, uint8_t Reset) +{ + AdaptecReset(Adaptec); + if (Reset) + { + Adaptec->Status |= STAT_STST; + Adaptec->Status &= ~STAT_IDLE; + } +} + static void AdaptecCommandComplete(Adaptec_t *Adaptec) { Adaptec->Status |= STAT_IDLE; @@ -354,76 +487,45 @@ static void AdaptecCommandComplete(Adaptec_t *Adaptec) Adaptec->Command = 0xFF; Adaptec->CmdParam = 0; } - -static void AdaptecInitReset(Adaptec_t *Adaptec, int Reset) -{ - AdaptecReset(Adaptec); - if (Reset) - { - Adaptec->Status |= STAT_STST; - Adaptec->Status &= ~STAT_IDLE; - } -} -static void AdaptecMailboxLogInformation(Mailbox_t *Mailbox) -{ - AdaptecLog("Adaptec: Mailbox Dump Log\n"); - AdaptecLog("CCB Pointer=%#x\n", ADDR_TO_U32(Mailbox->CCBPointer)); - AdaptecLog("Command or Status Code=%02X\n", Mailbox->CmdStatus); -} - -static void AdaptecCCBLogInformation(CCB *CmdBlock) -{ - pclog("Adaptec: CCB Dump Log\n"); - pclog("Opcode=%#x\n", CmdBlock->Opcode); - pclog("Data Direction=%u\n", CmdBlock->ControlByte); - pclog("Cdb Length=%d\n", CmdBlock->CdbLength); - pclog("Sense Length=%u\n", CmdBlock->RequestSenseLength); - pclog("Data Length=%u\n", ADDR_TO_U32(CmdBlock->DataLength)); - pclog("Data Pointer=%u\n", ADDR_TO_U32(CmdBlock->DataPointer)); - pclog("Host Adapter Status=0x%02X\n", CmdBlock->HostStatus); - pclog("Target Device Status=0x%02X\n", CmdBlock->TargetStatus); - pclog("Cdb[0]=%#x\n", CmdBlock->Cdb[0]); - pclog("Cdb[1]=%#x\n", CmdBlock->Cdb[1]); -} - -static void AdaptecMailboxIn(Adaptec_t *Adaptec, uint32_t CCBPointer, CCB *CmdBlock, uint8_t HostStatus, uint8_t TargetStatus, uint8_t MailboxCompletionCode) +static void AdaptecMailboxIn(Adaptec_t *Adaptec, uint32_t CCBPointer, CCBU *CmdBlock, + uint8_t HostStatus, uint8_t TargetStatus, uint8_t MailboxCompletionCode) { Mailbox32_t Mailbox32; Mailbox_t MailboxIn; Mailbox32.CCBPointer = CCBPointer; - Mailbox32.CmdStatus = MailboxCompletionCode; - - uint32_t Incoming = Adaptec->MailboxInAddr + (Adaptec->MailboxInPosCur * sizeof(Mailbox_t)); + Mailbox32.u.in.HostStatus = HostStatus; + Mailbox32.u.in.TargetStatus = TargetStatus; + Mailbox32.u.in.CompletionCode = MailboxCompletionCode; + + uint32_t Incoming = Adaptec->MailboxInAddr + (Adaptec->MailboxInPosCur * (Adaptec->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); if (MailboxCompletionCode != MBI_NOT_FOUND) { - CmdBlock->HostStatus = HostStatus; - CmdBlock->TargetStatus = TargetStatus; - - uint32_t CCBSize = offsetof(CCB, Cdb); - const void *Data = (const void *)&CmdBlock; - uint32_t l = PageLengthReadWrite(CCBPointer, CCBSize); - //AdaptecBufferWrite(&Adaptec->AdaptecRequests, Incoming, &MailboxIn, sizeof(Mailbox_t)); - memcpy(&ram[CCBPointer], Data, l); - CCBPointer += l; - Data -= l; - CCBSize += l; + CmdBlock->common.HostStatus = HostStatus; + CmdBlock->common.TargetStatus = TargetStatus; + + //Rewrite the CCB up to the CDB. + DMAPageWrite(CCBPointer, CmdBlock, offsetof(CCBC, Cdb)); } - MailboxIn.CmdStatus = Mailbox32.CmdStatus; - U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer); - AdaptecLog("Adaptec: Mailbox: status code=0x%02X, CCB at 0x%08X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); - - uint32_t MailboxSize = sizeof(Mailbox_t); - const void *Data = (const void *)&MailboxIn; - uint32_t l = PageLengthReadWrite(Incoming, MailboxSize); - //AdaptecBufferWrite(&Adaptec->AdaptecRequests, Incoming, &MailboxIn, sizeof(Mailbox_t)); - memcpy(&ram[Incoming], Data, l); - Incoming += l; - Data -= l; - MailboxSize += l; + pclog("Host Status 0x%02X, TargetStatus 0x%02X\n", HostStatus, TargetStatus); + + if (Adaptec->Mbx24bit) + { + MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode; + U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer); + pclog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%08X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); + + DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t)); + } + else + { + pclog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%08X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer); + + DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t)); + } Adaptec->MailboxInPosCur++; if (Adaptec->MailboxInPosCur > Adaptec->MailboxCount) @@ -433,55 +535,74 @@ static void AdaptecMailboxIn(Adaptec_t *Adaptec, uint32_t CCBPointer, CCB *CmdBl picint(1 << Adaptec->Irq); } -static void AdaptecReadSGEntries(uint32_t SGList, uint32_t Entries, SGE *SG) +static void AdaptecReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) { - uint32_t SGSize = Entries * sizeof(SGE); - void *Data = (void *)SG; - uint32_t l = PageLengthReadWrite(SGList, SGSize); - //AdaptecBufferRead(&Adaptec->AdaptecRequests, SGList, SG, Entries * sizeof(SGE)); - memcpy(Data, &ram[SGList], l); - SGList += l; - Data -= l; - SGSize += l; + if (Is24bit) + { + uint32_t i; + SGE SGE24[MAX_SG_DESCRIPTORS]; + + DMAPageRead(SGList, &SGE24, Entries * sizeof(SGE)); + + for (i=0;iDataPointer); - DataLength = ADDR_TO_U32(CmdBlock->DataLength); - - if (DataLength) + if (Is24bit) { - if (CmdBlock->Opcode == SCATTER_GATHER_COMMAND || - CmdBlock->Opcode == SCATTER_GATHER_COMMAND_RES) + DataPointer = ADDR_TO_U32(CmdBlock->old.DataPointer); + DataLength = ADDR_TO_U32(CmdBlock->old.DataLength); + } + else + { + DataPointer = CmdBlock->new.DataPointer; + DataLength = CmdBlock->new.DataLength; + } + + if (DataLength && (CmdBlock->common.Opcode != 3)) + { + if (CmdBlock->common.Opcode == SCATTER_GATHER_COMMAND || + CmdBlock->common.Opcode == SCATTER_GATHER_COMMAND_RES) { uint32_t ScatterGatherRead; uint32_t ScatterEntry; - SGE ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; - uint32_t ScatterGatherLeft = DataLength / sizeof(SGE); + SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; + uint32_t ScatterGatherLeft = DataLength / (Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t ScatterGatherAddrCurrent = DataPointer; - + do { ScatterGatherRead = (ScatterGatherLeft < ELEMENTS(ScatterGatherBuffer)) ? ScatterGatherLeft : ELEMENTS(ScatterGatherBuffer); - + ScatterGatherLeft -= ScatterGatherRead; - AdaptecReadSGEntries(ScatterGatherAddrCurrent, ScatterGatherRead, ScatterGatherBuffer); - + AdaptecReadSGEntries(Is24bit, ScatterGatherAddrCurrent, ScatterGatherRead, ScatterGatherBuffer); + for (ScatterEntry = 0; ScatterEntry < ScatterGatherRead; ScatterEntry++) - BufferSize += ADDR_TO_U32(ScatterGatherBuffer[ScatterEntry].Segment); - - ScatterGatherAddrCurrent += ScatterGatherRead * sizeof(SGE); + BufferSize += ScatterGatherBuffer[ScatterEntry].Segment; + + ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); } while (ScatterGatherLeft > 0); - + + AdaptecLog("Adaptec: Query Data Buffer\n"); AdaptecLog("Adaptec: Data Buffer Size=%u\n", BufferSize); } - else if (CmdBlock->Opcode == SCSI_INITIATOR_COMMAND || - CmdBlock->Opcode == SCSI_INITIATOR_COMMAND_RES) + else if (CmdBlock->common.Opcode == SCSI_INITIATOR_COMMAND || + CmdBlock->common.Opcode == SCSI_INITIATOR_COMMAND_RES) BufferSize = DataLength; } @@ -501,15 +622,8 @@ static void AdaptecCopyBufferFromGuestWorker(Adaptec_t *Adaptec, uint32_t Addres uint32_t Segment = Copy; uint8_t *SegmentPointer = SegmentBufferGetNextSegment(SegmentBuffer, Segment); - uint32_t SegmentSize = Segment; - void *Data = (void *)SegmentPointer; - uint32_t l = PageLengthReadWrite(Address, SegmentSize); - //AdaptecBufferRead(&Adaptec->AdaptecRequests, Address, SegmentPointer, Segment); - memcpy(Data, &ram[Address], l); - Address += l; - Data -= l; - SegmentSize += l; - + DMAPageRead(Address, SegmentPointer, Segment); + Address += Segment; Copy -= Segment; } @@ -528,14 +642,7 @@ static void AdaptecCopyBufferToGuestWorker(Adaptec_t *Adaptec, uint32_t Address, uint32_t Segment = Copy; uint8_t *SegmentPointer = SegmentBufferGetNextSegment(SegmentBuffer, Segment); - uint32_t SegmentSize = Segment; - const void *Data = (const void *)SegmentPointer; - uint32_t l = PageLengthReadWrite(Address, SegmentSize); - //AdaptecBufferWrite(&Adaptec->AdaptecRequests, Address, SegmentPointer, Segment); - memcpy(&ram[Address], Data, l); - Address += l; - Data -= l; - SegmentSize += l; + DMAPageWrite(Address, SegmentPointer, Segment); Address += Segment; Copy -= Segment; @@ -549,26 +656,35 @@ static int AdaptecScatterGatherBufferWalker(Adaptec_t *Adaptec, AdaptecRequests_ uint32_t Copied = 0; Copy += Skip; - - DataPointer = ADDR_TO_U32(AdaptecRequests->CmdBlock.DataPointer); - DataLength = ADDR_TO_U32(AdaptecRequests->CmdBlock.DataLength); - AdaptecLog("Adaptec: S/G Buffer Walker\n"); - AdaptecLog("Data Length=%u\n", DataLength); - AdaptecLog("Data Buffer Copy=%u\n", Copy); - - if ((DataLength > 0) && (AdaptecRequests->CmdBlock.ControlByte == CCB_DATA_XFER_IN || - AdaptecRequests->CmdBlock.ControlByte == CCB_DATA_XFER_OUT)) + if (AdaptecRequests->Is24bit) { - if (AdaptecRequests->CmdBlock.Opcode == SCATTER_GATHER_COMMAND || - AdaptecRequests->CmdBlock.Opcode == SCATTER_GATHER_COMMAND_RES) + DataPointer = ADDR_TO_U32(AdaptecRequests->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(AdaptecRequests->CmdBlock.old.DataLength); + } + else + { + DataPointer = AdaptecRequests->CmdBlock.new.DataPointer; + DataLength = AdaptecRequests->CmdBlock.new.DataLength; + } + + /*Mostly a hack for NT 1991 as the CCB describes a 2K buffer, but Test Unit Ready is executed + and it returns no data, the buffer must be left alone*/ + if (AdaptecRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) + DataLength = 0; + + if ((DataLength > 0) && (AdaptecRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN || + AdaptecRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT)) + { + if (AdaptecRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || + AdaptecRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { uint32_t ScatterGatherRead; uint32_t ScatterEntry; - SGE ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; - uint32_t ScatterGatherLeft = DataLength / sizeof(SGE); + SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; + uint32_t ScatterGatherLeft = DataLength / (AdaptecRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t ScatterGatherAddrCurrent = DataPointer; - + do { ScatterGatherRead = (ScatterGatherLeft < ELEMENTS(ScatterGatherBuffer)) @@ -576,43 +692,45 @@ static int AdaptecScatterGatherBufferWalker(Adaptec_t *Adaptec, AdaptecRequests_ ScatterGatherLeft -= ScatterGatherRead; - AdaptecReadSGEntries(ScatterGatherAddrCurrent, ScatterGatherRead, ScatterGatherBuffer); + AdaptecReadSGEntries(AdaptecRequests->Is24bit, ScatterGatherAddrCurrent, ScatterGatherRead, ScatterGatherBuffer); for (ScatterEntry = 0; ScatterEntry < ScatterGatherRead; ScatterEntry++) { uint32_t Address; uint32_t CopyThis; - + AdaptecLog("Adaptec: Scatter Entry=%u\n", ScatterEntry); - - Address = ADDR_TO_U32(ScatterGatherBuffer[ScatterEntry].SegmentPointer); - CopyThis = MIN(Copy, ADDR_TO_U32(ScatterGatherBuffer[ScatterEntry].Segment)); - - AdaptecLog("Adaptec: S/G Address=0x%04X, Copy=%u", Address, CopyThis); - + + Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; + CopyThis = MIN(Copy, ScatterGatherBuffer[ScatterEntry].Segment); + + AdaptecLog("Adaptec: S/G Address=0x%04X, Copy=%u\n", Address, CopyThis); + IoCopyWorker(Adaptec, Address, SegmentBuffer, CopyThis, &Skip); Copied += CopyThis; Copy -= CopyThis; } - + ScatterGatherAddrCurrent += ScatterGatherRead * sizeof(SGE); } while (ScatterGatherLeft > 0 && Copy > 0); } - else if (AdaptecRequests->CmdBlock.Opcode == SCSI_INITIATOR_COMMAND || - AdaptecRequests->CmdBlock.Opcode == SCSI_INITIATOR_COMMAND_RES) + else if (AdaptecRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || + AdaptecRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { uint32_t Address = DataPointer; - + AdaptecLog("Adaptec: Non-scattered buffer\n"); - pclog("Data Pointer=%#x\n", DataPointer); - pclog("Data Length=%u\n", DataLength); + AdaptecLog("Data Pointer=%#x\n", DataPointer); + AdaptecLog("Data Length=%u\n", DataLength); AdaptecLog("Pointer Address=%#x\n", Address); - + IoCopyWorker(Adaptec, Address, SegmentBuffer, MIN(DataLength, Copy), &Skip); Copied += MIN(DataLength, Copy); } } + pclog("Opcode %02X\n", AdaptecRequests->CmdBlock.common.Opcode); + return Copied - MIN(Skip, Copied); } @@ -630,7 +748,7 @@ static int AdaptecCopySegmentBufferFromGuest(Adaptec_t *Adaptec, AdaptecRequests uint8_t AdaptecRead(uint16_t Port, void *p) { - Adaptec_t *Adaptec = &AdaptecLUN; + Adaptec_t *Adaptec = &AdaptecLUN[scsi_cdrom_id]; uint8_t Temp; switch (Port & 3) @@ -660,11 +778,6 @@ uint8_t AdaptecRead(uint16_t Port, void *p) case 2: Temp = Adaptec->Interrupt; - if (Adaptec->ScsiBios) - { - Adaptec->Interrupt = INTR_MBIF | INTR_ANY; - picint(1 << Adaptec->Irq); - } break; case 3: @@ -678,18 +791,16 @@ uint8_t AdaptecRead(uint16_t Port, void *p) void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) { - Adaptec_t *Adaptec = &AdaptecLUN; - AdaptecLog("Adaptec: Write Port 0x%02X, Value %02X\n", Port, Val); + Adaptec_t *Adaptec = &AdaptecLUN[scsi_cdrom_id]; + pclog("Adaptec: Write Port 0x%02X, Value %02X\n", Port, Val); switch (Port & 3) { case 0: if ((Val & CTRL_HRST) || (Val & CTRL_SRST)) - { - int HardReset = !!(Val & CTRL_HRST); - - AdaptecLog("Adaptec: %s reset\n", HardReset ? "hard" : "soft"); - AdaptecInitReset(Adaptec, HardReset); + { + uint8_t Reset = !!(Val & CTRL_HRST); + AdaptecResetControl(Adaptec, Reset); break; } @@ -700,10 +811,7 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) case 1: if ((Val == 0x02) && (Adaptec->Command == 0xFF)) { - if (Adaptec->MailboxCount) - { - ScsiCallback[scsi_cdrom_id] = 1; - } + ScsiCallback[scsi_cdrom_id] = 1; break; } @@ -713,16 +821,16 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) Adaptec->CmdParam = 0; Adaptec->Status &= ~(STAT_INVCMD | STAT_IDLE); - AdaptecLog("Adaptec: Operation Code 0x%02X\n", Val); + pclog("Adaptec: Operation Code 0x%02X\n", Val); switch (Adaptec->Command) { - case 0x03: case 0x00: + case 0x03: case 0x04: - case 0x84: - case 0x85: case 0x0A: case 0x0B: + case 0x84: + case 0x85: Adaptec->CmdParamLeft = 0; break; @@ -731,6 +839,10 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) case 0x09: case 0x0D: case 0x1F: + case 0x21: + case 0x8B: + case 0x8D: + case 0x25: Adaptec->CmdParamLeft = 1; break; @@ -741,6 +853,10 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) case 0x01: Adaptec->CmdParamLeft = sizeof(MailboxInit_t); break; + + case 0x81: + Adaptec->CmdParamLeft = sizeof(MailboxInitExtended_t); + break; case 0x28: case 0x29: @@ -757,6 +873,7 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) if (!Adaptec->CmdParamLeft) { + pclog("Running Operation Code 0x%02X\n", Adaptec->Command); switch (Adaptec->Command) { case 0x00: @@ -765,8 +882,10 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) case 0x01: { - MailboxInit_t *MailboxInit = (MailboxInit_t *)Adaptec->CmdBuf; + Adaptec->Mbx24bit = 1; + MailboxInit_t *MailboxInit = (MailboxInit_t *)Adaptec->CmdBuf; + Adaptec->MailboxCount = MailboxInit->Count; Adaptec->MailboxOutAddr = ADDR_TO_U32(MailboxInit->Address); Adaptec->MailboxInAddr = Adaptec->MailboxOutAddr + (Adaptec->MailboxCount * sizeof(Mailbox_t)); @@ -774,31 +893,51 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) AdaptecLog("Adaptec Initialize Mailbox Command\n"); AdaptecLog("Mailbox Out Address=0x%08X\n", Adaptec->MailboxOutAddr); AdaptecLog("Mailbox In Address=0x%08X\n", Adaptec->MailboxInAddr); - AdaptecLog("Initialized Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, ADDR_TO_U32(MailboxInit->Address)); + pclog("Initialized Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, ADDR_TO_U32(MailboxInit->Address)); Adaptec->Status &= ~STAT_INIT; Adaptec->DataReplyLeft = 0; } break; + case 0x81: + { + Adaptec->Mbx24bit = 0; + + MailboxInitExtended_t *MailboxInit = (MailboxInitExtended_t *)Adaptec->CmdBuf; + + Adaptec->MailboxCount = MailboxInit->Count; + Adaptec->MailboxOutAddr = MailboxInit->Address; + Adaptec->MailboxInAddr = MailboxInit->Address + (Adaptec->MailboxCount * sizeof(Mailbox32_t)); + + AdaptecLog("Adaptec Extended Initialize Mailbox Command\n"); + AdaptecLog("Mailbox Out Address=0x%08X\n", Adaptec->MailboxOutAddr); + AdaptecLog("Mailbox In Address=0x%08X\n", Adaptec->MailboxInAddr); + pclog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, MailboxInit->Address); + + Adaptec->Status &= ~STAT_INIT; + Adaptec->DataReplyLeft = 0; + } + break; + case 0x03: break; case 0x04: - Adaptec->DataBuf[0] = 'A'; - Adaptec->DataBuf[1] = '0'; - Adaptec->DataBuf[2] = '3'; - Adaptec->DataBuf[3] = '1'; + Adaptec->DataBuf[0] = 0x41; + Adaptec->DataBuf[1] = 0x41; + Adaptec->DataBuf[2] = '4'; + Adaptec->DataBuf[3] = '7'; Adaptec->DataReplyLeft = 4; break; case 0x84: Adaptec->DataBuf[0] = '0'; Adaptec->DataReplyLeft = 1; - break; - + break; + case 0x85: - Adaptec->DataBuf[0] = 'A'; + Adaptec->DataBuf[0] = 'M'; Adaptec->DataReplyLeft = 1; break; @@ -807,18 +946,18 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x07: - Adaptec->BusOn = Adaptec->CmdBuf[0]; Adaptec->DataReplyLeft = 0; + pclog("Bus-on time: %d\n", Adaptec->CmdBuf[0]); break; case 0x08: - Adaptec->BusOff = Adaptec->CmdBuf[0]; - Adaptec->DataReplyLeft = 0; + Adaptec->DataReplyLeft = 0; + pclog("Bus-off time: %d\n", Adaptec->CmdBuf[0]); break; case 0x09: - Adaptec->DmaSpeed = Adaptec->CmdBuf[0]; - Adaptec->DataReplyLeft = 0; + Adaptec->DataReplyLeft = 0; + pclog("DMA transfer rate: %02X\n", Adaptec->CmdBuf[0]); break; case 0x0A: @@ -831,26 +970,61 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) case 0x0B: Adaptec->DataBuf[0] = (1 << Adaptec->DmaChannel); - - /* if (Adaptec->DmaChannel >= 0) - AdaptecSetDMAChannel(Adaptec->DmaPort1, Adaptec->DmaData1, - Adaptec->DmaPort2, Adaptec->DmaData2); */ - Adaptec->DataBuf[1] = (1 << (Adaptec->Irq - 9)); Adaptec->DataBuf[2] = 7; Adaptec->DataReplyLeft = 3; break; case 0x0D: - Adaptec->DataReplyLeft = Adaptec->CmdBuf[0]; - Adaptec->DataBuf[1] = Adaptec->DmaSpeed; - Adaptec->DataBuf[2] = Adaptec->BusOn; - Adaptec->DataBuf[3] = Adaptec->BusOff; - Adaptec->DataBuf[4] = Adaptec->MailboxCount; - Adaptec->DataBuf[5] = Adaptec->MailboxOutAddr&0xFF; - Adaptec->DataBuf[6] = (Adaptec->MailboxOutAddr>>8); - Adaptec->DataBuf[7] = (Adaptec->MailboxOutAddr>>16); - Adaptec->DataBuf[8+scsi_cdrom_id] = 1; + { + Adaptec->DataReplyLeft = Adaptec->CmdBuf[0]; + + ReplyInquireSetupInformation *Reply = (ReplyInquireSetupInformation *)Adaptec->DataBuf; + + Reply->fSynchronousInitiationEnabled = 1; + Reply->fParityCheckingEnabled = 1; + Reply->cMailbox = Adaptec->MailboxCount; + U32_TO_ADDR(Reply->MailboxAddress, Adaptec->MailboxOutAddr); + Reply->uSignature = 'B'; + /* The 'D' signature prevents Adaptec's OS/2 drivers from getting too + * friendly with BusLogic hardware and upsetting the HBA state. + */ + Reply->uCharacterD = 'D'; /* BusLogic model. */ + Reply->uHostBusType = 'A'; /* ISA bus. */ + } + break; + + case 0x8B: + { + int i; + + /* The reply length is set by the guest and is found in the first byte of the command buffer. */ + Adaptec->DataReplyLeft = Adaptec->CmdBuf[0]; + memset(Adaptec->DataBuf, 0, Adaptec->DataReplyLeft); + const char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ + int cCharsToTransfer = Adaptec->DataReplyLeft <= sizeof(aModelName) + ? Adaptec->DataReplyLeft + : sizeof(aModelName); + + for (i = 0; i < cCharsToTransfer; i++) + Adaptec->DataBuf[i] = aModelName[i]; + + } + break; + + case 0x8D: + { + Adaptec->DataReplyLeft = Adaptec->CmdBuf[0]; + ReplyInquireExtendedSetupInformation *Reply = (ReplyInquireExtendedSetupInformation *)Adaptec->DataBuf; + + Reply->uBusType = 'A'; /* ISA style */ + Reply->u16ScatterGatherLimit = 16; + Reply->cMailbox = Adaptec->MailboxCount; + Reply->uMailboxAddressBase = Adaptec->MailboxOutAddr; + Reply->fLevelSensitiveInterrupt = 1; + memcpy(Reply->aFirmwareRevision, "70M", sizeof(Reply->aFirmwareRevision)); + + } break; case 0x1F: @@ -858,11 +1032,25 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) Adaptec->DataReplyLeft = 1; break; + case 0x21: + if (Adaptec->CmdParam == 1) + Adaptec->CmdParamLeft = Adaptec->CmdBuf[0]; + + Adaptec->DataReplyLeft = 0; + break; + + case 0x25: + if (Adaptec->CmdBuf[0] == 0) + Adaptec->IrqEnabled = 0; + else + Adaptec->IrqEnabled = 1; + break; + case 0x28: case 0x29: Adaptec->DataReplyLeft = 0; Adaptec->Status |= STAT_INVCMD; - break; + break; } } @@ -873,9 +1061,11 @@ void AdaptecWrite(uint16_t Port, uint8_t Val, void *p) break; case 2: + Adaptec->Irq = Val; break; case 3: + Adaptec->Geometry = Val; break; } } @@ -892,64 +1082,40 @@ static uint8_t AdaptecConvertSenseLength(uint8_t RequestSenseLength) static void AdaptecSenseBufferAllocate(AdaptecRequests_t *AdaptecRequests) { - uint8_t SenseLength = AdaptecConvertSenseLength(AdaptecRequests->CmdBlock.RequestSenseLength); + uint8_t SenseLength = AdaptecConvertSenseLength(AdaptecRequests->CmdBlock.common.RequestSenseLength); - AdaptecRequests->RequestSenseBuffer = malloc(SenseLength); + if (SenseLength) + AdaptecRequests->RequestSenseBuffer = malloc(SenseLength); } static void AdaptecSenseBufferFree(AdaptecRequests_t *AdaptecRequests, int Copy) { - uint8_t SenseLength = AdaptecConvertSenseLength(AdaptecRequests->CmdBlock.RequestSenseLength); - + uint8_t SenseLength = AdaptecConvertSenseLength(AdaptecRequests->CmdBlock.common.RequestSenseLength); + if (Copy && SenseLength) { uint32_t SenseBufferAddress; - - SenseBufferAddress = AdaptecRequests->CCBPointer; - SenseBufferAddress += AdaptecRequests->CmdBlock.CdbLength + offsetof(CCB, Cdb); - uint32_t SenseSize = SenseLength; - const void *Data = (const void *)AdaptecRequests->RequestSenseBuffer; - uint32_t l = PageLengthReadWrite(SenseBufferAddress, SenseSize); - //AdaptecBufferWrite(AdaptecRequests, SenseBufferAddress, AdaptecRequests->RequestSenseBuffer, SenseLength); - memcpy(&ram[SenseBufferAddress], Data, l); - SenseBufferAddress += l; - Data -= l; - SenseSize += l; + /*The Sense address, in 32-bit mode, is located in the Sense Pointer of the CCB, but in + 24-bit mode, it is located at the end of the Command Descriptor Block. */ + + if (AdaptecRequests->Is24bit) + { + SenseBufferAddress = AdaptecRequests->CCBPointer; + SenseBufferAddress += AdaptecRequests->CmdBlock.common.CdbLength + offsetof(CCB, Cdb); + } + else + SenseBufferAddress = AdaptecRequests->CmdBlock.new.SensePointer; + + DMAPageWrite(SenseBufferAddress, AdaptecRequests->RequestSenseBuffer, SenseLength); } + //Free the sense buffer when needed. free(AdaptecRequests->RequestSenseBuffer); } -static void AdaptecRequestComplete(SCSI *Scsi, Adaptec_t *Adaptec, - AdaptecRequests_t *AdaptecRequests) -{ - if (AdaptecRequests->RequestSenseBuffer) - AdaptecSenseBufferFree(AdaptecRequests, (ScsiStatus != SCSI_STATUS_OK)); - - if (AdaptecRequests->CmdBlock.Opcode == SCSI_INITIATOR_COMMAND_RES || - AdaptecRequests->CmdBlock.Opcode == SCATTER_GATHER_COMMAND_RES) - { - uint32_t Residual = 0; - SCSIQueryResidual(Scsi, &Residual); - U32_TO_ADDR(AdaptecRequests->CmdBlock.DataLength, Residual); - } - - uint8_t Status = ScsiStatus; - uint32_t CCBPointer = AdaptecRequests->CCBPointer; - CCB CmdBlock; - memcpy(&CmdBlock, &AdaptecRequests->CmdBlock, sizeof(CCB)); - - if (Status == SCSI_STATUS_OK) - AdaptecMailboxIn(Adaptec, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, - MBI_SUCCESS); - else if (Status == SCSI_STATUS_CHECK_CONDITION) - AdaptecMailboxIn(Adaptec, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, - MBI_ERROR); -} - uint32_t AdaptecIoRequestCopyFromBuffer(uint32_t OffDst, SGBUF *SegmentBuffer, uint32_t Copy) { - Adaptec_t *Adaptec = &AdaptecLUN; + Adaptec_t *Adaptec = &AdaptecLUN[scsi_cdrom_id]; uint32_t Copied = 0; Copied = AdaptecCopySegmentBufferToGuest(Adaptec, &Adaptec->AdaptecRequests, SegmentBuffer, OffDst, Copy); @@ -959,72 +1125,98 @@ uint32_t AdaptecIoRequestCopyFromBuffer(uint32_t OffDst, SGBUF *SegmentBuffer, u uint32_t AdaptecIoRequestCopyToBuffer(uint32_t OffSrc, SGBUF *SegmentBuffer, uint32_t Copy) { - Adaptec_t *Adaptec = &AdaptecLUN; + Adaptec_t *Adaptec = &AdaptecLUN[scsi_cdrom_id]; uint32_t Copied = 0; Copied = AdaptecCopySegmentBufferFromGuest(Adaptec, &Adaptec->AdaptecRequests, SegmentBuffer, OffSrc, Copy); - return Copied; + return Copied; +} + +static void AdaptecSCSIRequestComplete(Adaptec_t *Adaptec, AdaptecRequests_t *AdaptecRequests) +{ + if (AdaptecRequests->RequestSenseBuffer) + AdaptecSenseBufferFree(AdaptecRequests, (ScsiStatus != SCSI_STATUS_OK)); + + uint8_t Status = ScsiStatus; + uint32_t CCBPointer = AdaptecRequests->CCBPointer; + CCBU CmdBlock; + memcpy(&CmdBlock, &AdaptecRequests->CmdBlock, sizeof(CCBU)); + + if (Status == SCSI_STATUS_OK) + { + //A Good status must return good results. + AdaptecMailboxIn(Adaptec, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, + MBI_SUCCESS); + } + else if (ScsiStatus == SCSI_STATUS_CHECK_CONDITION) + { + AdaptecMailboxIn(Adaptec, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, + MBI_ERROR); + } } static void AdaptecSCSIRequestSetup(Adaptec_t *Adaptec, uint32_t CCBPointer) { AdaptecRequests_t *AdaptecRequests = &Adaptec->AdaptecRequests; - CCB CmdBlock; + CCBU CmdBlock; - uint32_t CCBUSize = sizeof(CCB); - void *Data = (void *)&CmdBlock; - uint32_t l = PageLengthReadWrite(CCBPointer, CCBUSize); - //AdaptecBufferRead(&Adaptec->AdaptecRequests, CCBPointer, &CmdBlock, sizeof(CCBU)); - memcpy(Data, &ram[CCBPointer], l); - CCBPointer += l; - Data -= l; - CCBUSize += l; + //Fetch data from the Command Control Block. + DMAPageRead(CCBPointer, &CmdBlock, sizeof(CCB32)); - pclog("Scanning SCSI Target ID %d\n", CmdBlock.Id); + uint8_t Id = Adaptec->Mbx24bit ? CmdBlock.old.Id : CmdBlock.new.Id; + uint8_t Lun = Adaptec->Mbx24bit ? CmdBlock.old.Lun : CmdBlock.new.Lun; - if (CmdBlock.Id == scsi_cdrom_id && CmdBlock.Lun == 0) - { - pclog("SCSI Target ID %d detected and working\n", CmdBlock.Id); - - SCSI *Scsi = &ScsiDrives[CmdBlock.Id]; - - AdaptecRequests->CCBPointer = CCBPointer - 30; - - memcpy(&AdaptecRequests->CmdBlock, &CmdBlock, sizeof(CmdBlock)); - - AdaptecSenseBufferAllocate(AdaptecRequests); - - uint32_t BufferSize = 0; - AdaptecQueryDataBufferSize(Adaptec, &CmdBlock, &BufferSize); - - uint8_t SenseLength = AdaptecConvertSenseLength(CmdBlock.RequestSenseLength); - - pclog("Control Byte Transfer Direction %02X\n", CmdBlock.ControlByte); - - if (CmdBlock.ControlByte == CCB_DATA_XFER_OUT) + pclog("Scanning SCSI Target ID %d\n", Id); + + if (Id < ELEMENTS(ScsiDrives)) + { + if (Id == scsi_cdrom_id && Lun == 0) { - pclog("Adaptec Write Transfer\n"); - SCSIWriteTransfer(Scsi, CmdBlock.Id); - } - else if (CmdBlock.ControlByte == CCB_DATA_XFER_IN) - { - pclog("Adaptec Read Transfer\n"); - SCSIReadTransfer(Scsi, CmdBlock.Id); + int retcode; + + pclog("SCSI Target ID %d detected and working\n", Id); + + SCSI *Scsi = &ScsiDrives[Id]; + + AdaptecRequests->CCBPointer = CCBPointer; + AdaptecRequests->Is24bit = Adaptec->Mbx24bit; + + memcpy(&AdaptecRequests->CmdBlock, &CmdBlock, sizeof(CmdBlock)); + + uint8_t SenseLength = AdaptecConvertSenseLength(CmdBlock.common.RequestSenseLength); + + AdaptecSenseBufferAllocate(AdaptecRequests); + + uint32_t BufferSize = 0; + AdaptecQueryDataBufferSize(Adaptec, &AdaptecRequests->CmdBlock, AdaptecRequests->Is24bit, &BufferSize); + + if (CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) + { + SCSIReadTransfer(Scsi, Id); + } + else if (CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) + { + SCSIWriteTransfer(Scsi, Id); + } + + SCSISendCommand(Scsi, Id, AdaptecRequests->CmdBlock.common.Cdb, AdaptecRequests->CmdBlock.common.CdbLength, BufferSize, AdaptecRequests->RequestSenseBuffer, SenseLength); + + AdaptecSCSIRequestComplete(Adaptec, AdaptecRequests); + + pclog("Status %02X, Sense Key %02X, Asc %02X, Ascq %02X\n", ScsiStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); + pclog("Transfer Control %02X\n", CmdBlock.common.ControlByte); } else { - AdaptecMailboxIn(Adaptec, AdaptecRequests->CCBPointer, &CmdBlock, CCB_INVALID_DIRECTION, SCSI_STATUS_OK, - MBI_ERROR); + AdaptecMailboxIn(Adaptec, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, + MBI_ERROR); } - - SCSISendCommand(Scsi, CmdBlock.Id, CmdBlock.Cdb, CmdBlock.CdbLength, BufferSize, AdaptecRequests->RequestSenseBuffer, SenseLength); - - AdaptecRequestComplete(Scsi, Adaptec, AdaptecRequests); } else { - CmdBlock.Id++; + AdaptecMailboxIn(Adaptec, CCBPointer, &CmdBlock, CCB_INVALID_CCB, SCSI_STATUS_OK, + MBI_ERROR); } } @@ -1032,19 +1224,22 @@ static uint32_t AdaptecMailboxOut(Adaptec_t *Adaptec, Mailbox32_t *Mailbox32) { Mailbox_t MailboxOut; uint32_t Outgoing; + + if (Adaptec->Mbx24bit) + { + Outgoing = Adaptec->MailboxOutAddr + (Adaptec->MailboxOutPosCur * sizeof(Mailbox_t)); + + DMAPageRead(Outgoing, &MailboxOut, sizeof(Mailbox_t)); - Outgoing = Adaptec->MailboxOutAddr + (Adaptec->MailboxOutPosCur * sizeof(Mailbox_t)); - uint32_t MailboxSize = sizeof(Mailbox_t); - void *Data = (void *)&MailboxOut; - uint32_t l = PageLengthReadWrite(Outgoing, MailboxSize); - //AdaptecBufferRead(&Adaptec->AdaptecRequests, Outgoing, &MailboxOut, sizeof(Mailbox_t)); - memcpy(Data, &ram[Outgoing], l); - Outgoing += l; - Data -= l; - MailboxSize += l; - - Mailbox32->CCBPointer = ADDR_TO_U32(MailboxOut.CCBPointer); - Mailbox32->CmdStatus = MailboxOut.CmdStatus; + Mailbox32->CCBPointer = ADDR_TO_U32(MailboxOut.CCBPointer); + Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; + } + else + { + Outgoing = Adaptec->MailboxOutAddr + (Adaptec->MailboxOutPosCur * sizeof(Mailbox32_t)); + + DMAPageRead(Outgoing, Mailbox32, sizeof(Mailbox32_t)); + } return Outgoing; } @@ -1054,62 +1249,54 @@ static void AdaptecStartMailbox(Adaptec_t *Adaptec) Mailbox32_t Mailbox32; Mailbox_t MailboxOut; uint32_t Outgoing; + + uint8_t MailboxOutCur = Adaptec->MailboxOutPosCur; - uint8_t MailboxPosCur = Adaptec->MailboxOutPosCur; - - do + do { Outgoing = AdaptecMailboxOut(Adaptec, &Mailbox32); Adaptec->MailboxOutPosCur = (Adaptec->MailboxOutPosCur + 1) % Adaptec->MailboxCount; - - } while ((MailboxPosCur != Adaptec->MailboxOutPosCur) && (Mailbox32.CmdStatus == MBO_FREE)); - - AdaptecLog("Adaptec: Got loaded mailbox at slot %u, CCB phys 0x%08X\n", Adaptec->MailboxOutPosCur, Mailbox32.CCBPointer); - - uint8_t CmdStatus = MBO_FREE; - unsigned CodeOffset = offsetof(Mailbox_t, CmdStatus); + } while (Mailbox32.u.out.ActionCode == MBO_FREE && MailboxOutCur != Adaptec->MailboxOutPosCur); - uint32_t MailboxOffset = Outgoing + CodeOffset; - uint32_t CmdStatusSize = sizeof(CmdStatus); - const void *Data = (const void *)&CmdStatus; - uint32_t l = PageLengthReadWrite(MailboxOffset, CmdStatusSize); - //AdaptecBufferRead(&Adaptec->AdaptecRequests, Outgoing, &MailboxOut, sizeof(Mailbox_t)); - memcpy(&ram[MailboxOffset], Data, l); - MailboxOffset += l; - Data -= l; - CmdStatusSize += l; + Adaptec->MailboxOutPosCur = MailboxOutCur; + + uint8_t CmdStatus = MBO_FREE; + uint32_t CodeOffset = Adaptec->Mbx24bit ? offsetof(Mailbox_t, CmdStatus) : offsetof(Mailbox32_t, u.out.ActionCode); - Mailbox32.CmdStatus = MBO_START; - AdaptecSCSIRequestSetup(Adaptec, Mailbox32.CCBPointer); + DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus)); + + if (Mailbox32.u.out.ActionCode == MBO_START) + { + Adaptec->MailboxOutPosCur = 1; //Make sure that at least one outgoing mailbox is loaded. + pclog("Start Mailbox Command\n"); + AdaptecSCSIRequestSetup(Adaptec, Mailbox32.CCBPointer); + } } void AdaptecCallback(void *p) { - Adaptec_t *Adaptec = &AdaptecLUN; + Adaptec_t *Adaptec = &AdaptecLUN[scsi_cdrom_id]; ScsiCallback[scsi_cdrom_id] = 0; - if (Adaptec->MailboxCount) - { - AdaptecStartMailbox(Adaptec); - } + AdaptecStartMailbox(Adaptec); } -void AdaptecInit(uint8_t Id) +void AdaptecInit() { - AdaptecLUN.Irq = scsi_irq; - AdaptecLUN.DmaChannel = scsi_dma; + Adaptec_t *Adaptec = &AdaptecLUN[scsi_cdrom_id]; - AdaptecLUN.DmaPort1 = 0xD6; - AdaptecLUN.DmaData1 = 0xD4; - AdaptecLUN.DmaPort2 = 0xC2; - AdaptecLUN.DmaData2 = 0x02; + Adaptec->Irq = scsi_irq; + Adaptec->DmaChannel = scsi_dma; pfnIoRequestCopyFromBuffer = AdaptecIoRequestCopyFromBuffer; - pfnIoRequestCopyToBuffer = AdaptecIoRequestCopyToBuffer; + pfnIoRequestCopyToBuffer = AdaptecIoRequestCopyToBuffer; io_sethandler(scsi_base, 0x0004, AdaptecRead, NULL, NULL, AdaptecWrite, NULL, NULL, NULL); - timer_add(AdaptecCallback, &ScsiCallback[Id], &ScsiCallback[Id], NULL); + timer_add(AdaptecCallback, &ScsiCallback[scsi_cdrom_id], &ScsiCallback[scsi_cdrom_id], NULL); + pclog("Adaptec on port 0x%04X\n", scsi_base); - AdaptecReset(&AdaptecLUN); + AdaptecReset(Adaptec); + Adaptec->Status |= STAT_STST; + Adaptec->Status &= ~STAT_IDLE; } diff --git a/src/aha154x.h b/src/aha154x.h index 4037ef2bf..801bd6441 100644 --- a/src/aha154x.h +++ b/src/aha154x.h @@ -1 +1 @@ -extern void AdaptecInit(uint8_t Id); \ No newline at end of file +extern void AdaptecInit(); \ No newline at end of file diff --git a/src/amstrad.c b/src/amstrad.c index 7756f80cc..4c728ff0f 100644 --- a/src/amstrad.c +++ b/src/amstrad.c @@ -1,6 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include "ibm.h" #include "io.h" #include "keyboard.h" @@ -38,10 +35,78 @@ void amstrad_write(uint16_t port, uint8_t val, void *priv) } } +static uint8_t mousex, mousey; +static void amstrad_mouse_write(uint16_t addr, uint8_t val, void *p) +{ +// pclog("Write mouse %04X %02X %04X:%04X\n", addr, val, CS, pc); + if (addr == 0x78) + mousex = 0; + else + mousey = 0; +} + +static uint8_t amstrad_mouse_read(uint16_t addr, void *p) +{ +// printf("Read mouse %04X %04X:%04X %02X\n", addr, CS, pc, (addr == 0x78) ? mousex : mousey); + if (addr == 0x78) + return mousex; + return mousey; +} + +typedef struct mouse_amstrad_t +{ + int oldb; +} mouse_amstrad_t; + +static void mouse_amstrad_poll(int x, int y, int z, int b, void *p) +{ + mouse_amstrad_t *mouse = (mouse_amstrad_t *)p; + + mousex += x; + mousey -= y; + + if ((b & 1) && !(mouse->oldb & 1)) + keyboard_send(0x7e); + if ((b & 2) && !(mouse->oldb & 2)) + keyboard_send(0x7d); + if (!(b & 1) && (mouse->oldb & 1)) + keyboard_send(0xfe); + if (!(b & 2) && (mouse->oldb & 2)) + keyboard_send(0xfd); + + mouse->oldb = b; +} + +static void *mouse_amstrad_init() +{ + mouse_amstrad_t *mouse = (mouse_amstrad_t *)malloc(sizeof(mouse_amstrad_t)); + memset(mouse, 0, sizeof(mouse_amstrad_t)); + + return mouse; +} + +static void mouse_amstrad_close(void *p) +{ + mouse_amstrad_t *mouse = (mouse_amstrad_t *)p; + + free(mouse); +} + +mouse_t mouse_amstrad = +{ + "Amstrad mouse", + mouse_amstrad_init, + mouse_amstrad_close, + mouse_amstrad_poll, + MOUSE_TYPE_AMSTRAD +}; + void amstrad_init() { lpt2_remove_ams(); + io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL); + io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL); io_sethandler(0x0379, 0x0002, amstrad_read, NULL, NULL, NULL, NULL, NULL, NULL); io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL); } diff --git a/src/amstrad.h b/src/amstrad.h index f02907d68..1d4130f49 100644 --- a/src/amstrad.h +++ b/src/amstrad.h @@ -1,5 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ void amstrad_init(); +extern mouse_t mouse_amstrad; diff --git a/src/cdrom-ioctl-linux.c b/src/cdrom-ioctl-linux.c index 5427d35d3..5b993b612 100644 --- a/src/cdrom-ioctl-linux.c +++ b/src/cdrom-ioctl-linux.c @@ -420,16 +420,6 @@ static void ioctl_load(void) cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); } -static void ioctl_readsector(uint8_t *b, int sector) -{ - int cdrom = open("/dev/cdrom", O_RDONLY|O_NONBLOCK); - if (cdrom <= 0) - return; - lseek(cdrom, sector*2048, SEEK_SET); - read(cdrom, b, 2048); - close(cdrom); -} - union { struct cdrom_msf *msf; @@ -441,6 +431,11 @@ static int lba_to_msf(int lba) return (((lba / 75) / 60) << 16) + (((lba / 75) % 60) << 8) + (lba % 75); } +static int ioctl_sector_data_type(int sector, int ismsf) +{ + return 2; /* Always Mode 1 */ +} + static void ioctl_readsector_raw(uint8_t *b, int sector) { int err; @@ -711,7 +706,10 @@ static ATAPI ioctl_atapi= ioctl_readtoc_session, ioctl_readtoc_raw, ioctl_getcurrentsubchannel, - ioctl_readsector, + NULL, + NULL, + NULL, + ioctl_sector_data_type, ioctl_readsector_raw, ioctl_playaudio, ioctl_seek, diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 2c303f96c..173b02861 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -424,23 +424,6 @@ static void ioctl_load(void) cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); } -static void ioctl_readsector(uint8_t *b, int sector) -{ - LARGE_INTEGER pos; - long size; - if (!cdrom_drive) return; - - if (ioctl_cd_state == CD_PLAYING) - return; - - ioctl_cd_state = CD_STOPPED; - pos.QuadPart=sector*2048; - ioctl_open(0); - SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN); - ReadFile(hIOCTL,b,2048,&size,NULL); - ioctl_close(); -} - static int is_track_audio(uint32_t pos) { int c; @@ -490,137 +473,209 @@ static int ioctl_is_track_audio(uint32_t pos, int ismsf) return is_track_audio(pos); } -/* Direct SCSI read in MSF mode. */ -int SCSIReadMSF(uint8_t *b, int sector) +static int SCSICommand(const UCHAR *cdb, UCHAR *buf, uint32_t len) { HANDLE fh; DWORD ioctl_bytes; DWORD out_size; + int ioctl_rv = 0; + UCHAR tbuf[2856]; + struct sptd_with_sense + { + SCSI_PASS_THROUGH_DIRECT s; + UCHAR sense[128]; + } sptd; + + memset(&sptd, 0, sizeof(sptd)); + sptd.s.Length = sizeof(sptd.s); + // sptd.s.CdbLength = sizeof(cdb); + sptd.s.CdbLength = 12; + sptd.s.DataIn = SCSI_IOCTL_DATA_IN; + sptd.s.TimeOutValue = 30; + sptd.s.DataBuffer = tbuf; + sptd.s.DataTransferLength = len; + sptd.s.SenseInfoLength = sizeof(sptd.sense); + sptd.s.SenseInfoOffset = offsetof(struct sptd_with_sense, sense); + + // memcpy(sptd.s.Cdb, cdb, sizeof(cdb)); + memcpy(sptd.s.Cdb, cdb, 12); + ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); + memcpy(buf, sptd.s.DataBuffer, len); + + return ioctl_rv; +} + +static void ioctl_read_capacity(uint8_t *b) +{ + const UCHAR cdb[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + UCHAR buf[16]; + + ioctl_open(0); + + SCSICommand(cdb, buf, 16); + + memcpy(b, buf, 8); + + ioctl_close(); +} + +static void ioctl_read_header(uint8_t *in_cdb, uint8_t *b) +{ + const UCHAR cdb[12]; + UCHAR buf[16]; + + ioctl_open(0); + + memcpy(cdb, in_cdb, 12); + SCSICommand(cdb, buf, 16); + + memcpy(b, buf, 8); + + ioctl_close(); +} + +static void ioctl_read_disc_information(uint8_t *b) +{ + const UCHAR cdb[] = { 0x51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + UCHAR buf[68]; + + ioctl_open(0); + + SCSICommand(cdb, buf, 68); + + memcpy(b, buf, 34); + + ioctl_close(); +} + +static int SCSIReadCommon(const UCHAR *cdb_0, const UCHAR *cdb_1, const UCHAR *cdb_2, const UCHAR *cdb_4, uint8_t *b, UCHAR *buf) +{ int ioctl_rv; + + ioctl_open(0); + + /* Fill the buffer with zeroes. */ + memset(b, 0, 2856); + + ioctl_rv = SCSICommand(cdb_0, buf, 2856); + memcpy(b, buf, 2648); + + /* Next, try to read RAW subchannel data. */ + ioctl_rv += SCSICommand(cdb_1, buf, 2856); + memcpy(b + 2648, buf + 2648, 96); + + /* Next, try to read Q subchannel data. */ + ioctl_rv += SCSICommand(cdb_2, buf, 2856); + memcpy(b + 2648 + 96, buf + 2648, 16); + + /* Next, try to read R - W subchannel data. */ + ioctl_rv += SCSICommand(cdb_4, buf, 2856); + memcpy(b + 2648 + 96 + 16, buf + 2648, 96); + + ioctl_close(); + + // pclog("rv: %i\n", ioctl_rv); + + return ioctl_rv; +} + +/* Direct SCSI read in MSF mode. */ +static int SCSIReadMSF(uint8_t *b, int sector) +{ const UCHAR cdb_0[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 0, 0 }; const UCHAR cdb_1[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 1, 0 }; const UCHAR cdb_2[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 2, 0 }; const UCHAR cdb_4[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 4, 0 }; UCHAR buf[2856]; - struct sptd_with_sense - { - SCSI_PASS_THROUGH_DIRECT s; - UCHAR sense[128]; - } sptd; - ioctl_open(0); - - memset(&sptd, 0, sizeof(sptd)); - sptd.s.Length = sizeof(sptd.s); - sptd.s.CdbLength = sizeof(cdb_0); /* All 4 of our CDB's are identically sized, therefore we can take this shortcut. */ - sptd.s.DataIn = SCSI_IOCTL_DATA_IN; - sptd.s.TimeOutValue = 30; - sptd.s.DataBuffer = buf; - sptd.s.DataTransferLength = 2856; - sptd.s.SenseInfoLength = sizeof(sptd.sense); - sptd.s.SenseInfoOffset = offsetof(struct sptd_with_sense, sense); - - /* Fill the buffer with zeroes. */ - memset(b, 0, 2856); - - /* First, read without subchannel data so we at least have *SOMETHING*. */ - memcpy(sptd.s.Cdb, cdb_0, sizeof(cdb_0)); - ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) without subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b, sptd.s.DataBuffer, 2648); - - /* Next, try to read RAW subchannel data. */ - memcpy(sptd.s.Cdb, cdb_1, sizeof(cdb_1)); - ioctl_rv += DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) with RAW subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b + 2648, sptd.s.DataBuffer + 2648, 96); - - /* Next, try to read Q subchannel data. */ - memcpy(sptd.s.Cdb, cdb_2, sizeof(cdb_2)); - ioctl_rv += DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) with Q subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b + 2648 + 96, sptd.s.DataBuffer + 2648, 16); - - /* Next, try to read R - W subchannel data. */ - memcpy(sptd.s.Cdb, cdb_4, sizeof(cdb_4)); - ioctl_rv += DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) with R - W subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b + 2648 + 96 + 16, sptd.s.DataBuffer + 2648, 96); - - ioctl_close(); - - return ioctl_rv; + return SCSIReadCommon(cdb_0, cdb_1, cdb_2, cdb_4, b, buf); } /* Direct SCSI read in LBA mode. */ -void SCSIRead(uint8_t *b, int sector) +static void SCSIRead(uint8_t *b, int sector) { - HANDLE fh; - DWORD ioctl_bytes; - DWORD out_size; - BOOL ioctl_rv; const UCHAR cdb_0[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 0, 0 }; const UCHAR cdb_1[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 1, 0 }; const UCHAR cdb_2[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 2, 0 }; const UCHAR cdb_4[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 4, 0 }; UCHAR buf[2856]; - struct sptd_with_sense + + SCSIReadCommon(cdb_0, cdb_1, cdb_2, cdb_4, b, buf); + return; +} + +static uint32_t msf_to_lba32(int lba) +{ + int m = (lba >> 16) & 0xff; + int s = (lba >> 8) & 0xff; + int f = lba & 0xff; + return (m * 60 * 75) + (s * 75) + f; +} + +static int ioctl_get_type(UCHAR *cdb, UCHAR *buf) +{ + int i = 0; + int ioctl_rv = 0; + + for (i = 2; i <= 5; i++) { - SCSI_PASS_THROUGH_DIRECT s; - UCHAR sense[128]; - } sptd; + cdb[1] = i << 2; + ioctl_rv = SCSICommand(cdb, buf, 2352); + if (ioctl_rv) + { + return i; + } + } + return 0; +} + +static int ioctl_sector_data_type(int sector, int ismsf) +{ + int ioctl_rv = 0; + const UCHAR cdb_lba[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0x10, 0, 0 }; + const UCHAR cdb_msf[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0x10, 0, 0 }; + UCHAR buf[2352]; ioctl_open(0); - memset(&sptd, 0, sizeof(sptd)); - sptd.s.Length = sizeof(sptd.s); - sptd.s.CdbLength = sizeof(cdb_0); /* All 4 of our CDB's are identically sized, therefore we can take this shortcut. */ - sptd.s.DataIn = SCSI_IOCTL_DATA_IN; - sptd.s.TimeOutValue = 30; - sptd.s.DataBuffer = buf; - sptd.s.DataTransferLength = 2856; - sptd.s.SenseInfoLength = sizeof(sptd.sense); - sptd.s.SenseInfoOffset = offsetof(struct sptd_with_sense, sense); - - /* Fill the buffer with zeroes. */ - memset(b, 0, 2856); + if (ioctl_is_track_audio(sector, ismsf)) + { + return 1; + } - /* First, read without subchannel data so we at least have *SOMETHING*. */ - memcpy(sptd.s.Cdb, cdb_0, sizeof(cdb_0)); - ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) without subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b, sptd.s.DataBuffer, 2648); - - /* Next, try to read RAW subchannel data. */ - memcpy(sptd.s.Cdb, cdb_1, sizeof(cdb_1)); - ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) with RAW subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b + 2648, sptd.s.DataBuffer + 2648, 96); - - /* Next, try to read Q subchannel data. */ - memcpy(sptd.s.Cdb, cdb_2, sizeof(cdb_2)); - ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) with Q subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b + 2648 + 96, sptd.s.DataBuffer + 2648, 16); - - /* Next, try to read R - W subchannel data. */ - memcpy(sptd.s.Cdb, cdb_4, sizeof(cdb_4)); - ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - // pclog("Read (%i) with R - W subchannel data: %s\n", sector, ioctl_rv ? "SUCCESS" : "FAILURE"); - memcpy(b + 2648 + 96 + 16, sptd.s.DataBuffer + 2648, 96); + if (ismsf) + { + ioctl_rv = ioctl_get_type(cdb_msf, buf); + } + else + { + ioctl_rv = ioctl_get_type(cdb_lba, buf); + } + if (ioctl_rv) + { + ioctl_close(); + return ioctl_rv; + } + + if (ismsf) + { + sector = msf_to_lba32(sector); + if (sector < 150) + { + ioctl_close(); + return 0; + } + sector -= 150; + ioctl_rv = ioctl_get_type(cdb_lba, buf); + } + ioctl_close(); - - return; + return ioctl_rv; } static void ioctl_readsector_raw(uint8_t *b, int sector, int ismsf) { - RAW_READ_INFO in; - LARGE_INTEGER pos; - DWORD count = 0; - long size; - uint32_t temp; if (!cdrom_drive) return; if (ioctl_cd_state == CD_PLAYING) return; @@ -629,16 +684,13 @@ static void ioctl_readsector_raw(uint8_t *b, int sector, int ismsf) { if (!SCSIReadMSF(b, sector)) { - int m = (sector >> 16) & 0xff; - int s = (sector >> 8) & 0xff; - int f = sector & 0xff; - sector = (m * 60 * 75) + (s * 75) + f; + sector = msf_to_lba32(sector); if (sector < 150) { memset(b, 0, 2856); return; } - sector += 150; + sector -= 150; SCSIRead(b, sector); } } @@ -805,7 +857,15 @@ static int ioctl_readtoc_raw(unsigned char *b, int maxlen) static uint32_t ioctl_size() { - return cdrom_capacity; + uint8_t capacity_buffer[8]; + uint32_t capacity = 0; + ioctl_read_capacity(capacity_buffer); + capacity = ((uint32_t) capacity_buffer[0]) << 24; + capacity |= ((uint32_t) capacity_buffer[1]) << 16; + capacity |= ((uint32_t) capacity_buffer[2]) << 8; + capacity |= (uint32_t) capacity_buffer[3]; + return capacity + 1; + // return cdrom_capacity; } static int ioctl_status() @@ -891,13 +951,16 @@ static void ioctl_exit(void) static CDROM ioctl_cdrom= { ioctl_ready, - ioctl_medium_changed, + ioctl_medium_changed, ioctl_readtoc, ioctl_readtoc_session, - ioctl_readtoc_raw, + ioctl_readtoc_raw, ioctl_getcurrentsubchannel, - ioctl_readsector, - ioctl_readsector_raw, + ioctl_read_capacity, + ioctl_read_header, + ioctl_read_disc_information, + ioctl_sector_data_type, + ioctl_readsector_raw, ioctl_playaudio, ioctl_seek, ioctl_load, @@ -905,8 +968,8 @@ static CDROM ioctl_cdrom= ioctl_pause, ioctl_resume, ioctl_size, - ioctl_status, - ioctl_is_track_audio, + ioctl_status, + ioctl_is_track_audio, ioctl_stop, ioctl_exit }; diff --git a/src/cdrom-iso.c b/src/cdrom-iso.c index 3695b0801..0e76a86ed 100644 --- a/src/cdrom-iso.c +++ b/src/cdrom-iso.c @@ -126,40 +126,18 @@ static void iso_load(void) // pclog("iso_load stub\n"); } -static void iso_readsector(uint8_t *b, int sector) -{ - if (!cdrom_drive) return; - iso_image = fopen(iso_path, "rb"); - fseek(iso_image,sector*2048,SEEK_SET); - fread(b,2048,1,iso_image); - fclose(iso_image); -} - static void lba_to_msf(uint8_t *buf, int lba) { -#if 0 - double dlba = (double) lba + 150; - buf[2] = (uint8_t) (((uint32_t) dlba) % 75); - dlba /= 75; - buf[1] = (uint8_t) (((uint32_t) dlba) % 60); - dlba /= 60; - buf[0] = (uint8_t) dlba; -#endif lba += 150; buf[0] = (lba / 75) / 60; buf[1] = (lba / 75) % 60; buf[2] = lba % 75; } -#if 0 -static void lba_to_msf(uint8_t *buf, int lba) +static int iso_sector_data_type(int sector, int ismsf) { - lba += 150; - buf[0] = (lba / 75) / 60; - buf[1] = (lba / 75) % 60; - buf[2] = lba % 75; + return 2; /* Always Mode 1 */ } -#endif static void iso_readsector_raw(uint8_t *b, int sector, int ismsf) { @@ -406,7 +384,10 @@ static CDROM iso_cdrom = iso_readtoc_session, iso_readtoc_raw, iso_getcurrentsubchannel, - iso_readsector, + NULL, + NULL, + NULL, + iso_sector_data_type, iso_readsector_raw, iso_playaudio, iso_seek, diff --git a/src/cdrom-null.c b/src/cdrom-null.c index d865c0c0d..2d77469a8 100644 --- a/src/cdrom-null.c +++ b/src/cdrom-null.c @@ -62,8 +62,9 @@ static void null_load(void) { } -static void null_readsector(uint8_t *b, int sector) +static int null_sector_data_type(int sector, int ismsf) { + return 0; } static void null_readsector_raw(uint8_t *b, int sector, int ismsf) @@ -126,7 +127,10 @@ static CDROM null_cdrom = null_readtoc_session, null_readtoc_raw, null_getcurrentsubchannel, - null_readsector, + NULL, + NULL, + NULL, + null_sector_data_type, null_readsector_raw, null_playaudio, null_seek, diff --git a/src/cdrom.h b/src/cdrom.h index 716a6e647..cbe9ec5e8 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -10,7 +10,10 @@ typedef struct CDROM int (*readtoc_session)(uint8_t *b, int msf, int maxlen); int (*readtoc_raw)(uint8_t *b, int maxlen); uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf); - void (*readsector)(uint8_t *b, int sector); + void (*read_capacity)(uint8_t *b); + void (*read_header)(uint8_t *in_cdb, uint8_t *b); + void (*read_disc_information)(uint8_t *b); + int (*sector_data_type)(int sector, int ismsf); void (*readsector_raw)(uint8_t *b, int sector, int ismsf); void (*playaudio)(uint32_t pos, uint32_t len, int ismsf); void (*seek)(uint32_t pos); diff --git a/src/codegen_ops.c b/src/codegen_ops.c index a12dc0150..a1f846a52 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -29,8 +29,8 @@ RecompOpFn recomp_opcodes[512] = { /*16-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, NULL, +/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16, /*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL, @@ -39,20 +39,20 @@ RecompOpFn recomp_opcodes[512] = /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL, /*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE, -/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, ropLEA_w, NULL, NULL, +/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_w, ropMOV_seg_w, NULL, /*90*/ ropNOP, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, -/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES, ropLDS, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, NULL, NULL, ropCLD, ropSTD, ropFE, ropFF_16, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16, /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, -/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, NULL, +/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32, /*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL, /*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL, @@ -61,15 +61,15 @@ RecompOpFn recomp_opcodes[512] = /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL, /*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE, -/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, ropLEA_l, NULL, NULL, +/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_w_seg, ropLEA_l, ropMOV_seg_w, NULL, /*90*/ ropNOP, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL, /*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, -/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL, +/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES, ropLDS, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, NULL, NULL, ropCLD, ropSTD, ropFE, ropFF_32 +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32 }; RecompOpFn recomp_opcodes_0f[512] = @@ -88,8 +88,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL, +/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -110,8 +110,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w, +/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, @@ -188,7 +188,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ @@ -210,7 +210,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -422,7 +422,7 @@ RecompOpFn recomp_opcodes_de[512] = /*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, @@ -444,7 +444,7 @@ RecompOpFn recomp_opcodes_de[512] = /*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, }; diff --git a/src/codegen_ops_fpu.h b/src/codegen_ops_fpu.h index 02b3f4795..4fafa33ce 100644 --- a/src/codegen_ops_fpu.h +++ b/src/codegen_ops_fpu.h @@ -477,6 +477,14 @@ static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin return op_pc; } +static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_COMPARE_REG(0, 1); + FP_POP2(); + + return op_pc; +} static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { @@ -600,3 +608,31 @@ static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint return op_pc + 1; } + + +static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_FCHS(); + + return op_pc; +} + +#define opFLDimm(name, v) \ + static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + static double fp_imm = v; \ + \ + FP_ENTER(); \ + FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \ + \ + return op_pc; \ + } + +opFLDimm(1, 1.0) +opFLDimm(L2T, 3.3219280948873623) +opFLDimm(L2E, 1.4426950408889634); +opFLDimm(PI, 3.141592653589793); +opFLDimm(EG2, 0.3010299956639812); +opFLDimm(LN2, 0.693147180559945); +opFLDimm(Z, 0.0) diff --git a/src/codegen_ops_misc.h b/src/codegen_ops_misc.h index 3754d7fac..9d9ee7507 100644 --- a/src/codegen_ops_misc.h +++ b/src/codegen_ops_misc.h @@ -14,6 +14,17 @@ static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32 return op_pc; } +static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + CLEAR_BITS((uintptr_t)&flags, I_FLAG); + return op_pc; +} +static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + SET_BITS((uintptr_t)&flags, I_FLAG); + return op_pc; +} + static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { x86seg *target_seg; @@ -71,7 +82,7 @@ static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint x86seg *target_seg; int host_reg; - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30) + if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) return 0; if ((fetchdat & 0x30) == 0x00) @@ -163,7 +174,7 @@ static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint x86seg *target_seg; int host_reg; - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30) + if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) return 0; if ((fetchdat & 0x30) == 0x00) diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index 2ad330473..bfee56a29 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -504,3 +504,153 @@ static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, return op_pc + 1; } + +static uint32_t ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + + switch (fetchdat & 0x38) + { + case 0x00: /*ES*/ + host_reg = LOAD_VAR_WL(&ES); + break; + case 0x08: /*CS*/ + host_reg = LOAD_VAR_WL(&CS); + break; + case 0x18: /*DS*/ + host_reg = LOAD_VAR_WL(&DS); + break; + case 0x10: /*SS*/ + host_reg = LOAD_VAR_WL(&SS); + break; + case 0x20: /*FS*/ + host_reg = LOAD_VAR_WL(&FS); + break; + case 0x28: /*GS*/ + host_reg = LOAD_VAR_WL(&GS); + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) + { + if (op_32 & 0x100) + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); + else + STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 1); + + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 1; +} +static uint32_t ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + + switch (fetchdat & 0x38) + { + case 0x00: /*ES*/ + case 0x18: /*DS*/ + case 0x20: /*FS*/ + case 0x28: /*GS*/ + break; + case 0x10: /*SS*/ + default: + return 0; + } + + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_W(fetchdat & 7); + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_W(target_seg); + + host_reg = 0; + } + + switch (fetchdat & 0x38) + { + case 0x00: /*ES*/ + LOAD_SEG(host_reg, &_es); + break; + case 0x18: /*DS*/ + LOAD_SEG(host_reg, &_ds); + break; + case 0x20: /*FS*/ + LOAD_SEG(host_reg, &_fs); + break; + case 0x28: /*GS*/ + LOAD_SEG(host_reg, &_gs); + break; + } + + return op_pc + 1; +} + +#define ropLseg(seg, rseg) \ +static uint32_t ropL ## seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ +{ \ + int dest_reg = (fetchdat >> 3) & 7; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + SAVE_EA(); \ + \ + if (op_32 & 0x100) \ + { \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, 0); \ + LOAD_EA(); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ + } \ + else \ + { \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, 0); \ + LOAD_EA(); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ + } \ + LOAD_SEG(0, &rseg); \ + if (op_32 & 0x100) \ + { \ + \ + int host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); \ + STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \ + } \ + else \ + { \ + int host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); \ + STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \ + } \ + \ + if (&rseg == &_ss) \ + CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \ + return op_pc + 1; \ +} + +ropLseg(DS, _ds) +ropLseg(ES, _es) +ropLseg(FS, _fs) +ropLseg(GS, _gs) +ropLseg(SS, _ss) diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 06cf0e1a0..082d8a4e3 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -247,4 +247,37 @@ static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32 ROP_PUSH_SEG(CS) ROP_PUSH_SEG(DS) ROP_PUSH_SEG(ES) +ROP_PUSH_SEG(FS) +ROP_PUSH_SEG(GS) ROP_PUSH_SEG(SS) + +#define ROP_POP_SEG(seg, rseg) \ +static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ +{ \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(2); \ + \ + return op_pc; \ +} \ +static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ +{ \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(4); \ + \ + return op_pc; \ +} + +ROP_POP_SEG(DS, _ds) +ROP_POP_SEG(ES, _es) +ROP_POP_SEG(FS, _fs) +ROP_POP_SEG(GS, _gs) diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index 319b6f13e..452241e81 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -1105,6 +1105,13 @@ static void MEM_LOAD_ADDR_EA_W(x86seg *seg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } +static void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +{ + addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0xc0); + addbyte(offset); + MEM_LOAD_ADDR_EA_W(seg); +} static void MEM_LOAD_ADDR_EA_L(x86seg *seg) { if (IS_32_ADDR(&seg->base)) @@ -3346,6 +3353,10 @@ static int LOAD_VAR_W(uintptr_t addr) return host_reg; } +static int LOAD_VAR_WL(uintptr_t addr) +{ + return LOAD_VAR_W(addr); +} static int LOAD_VAR_L(uintptr_t addr) { int host_reg = REG_EBX; @@ -3390,9 +3401,9 @@ static int LOAD_HOST_REG(int host_reg) if (host_reg & 8) addbyte(0x44); addbyte(0x89); - addbyte(0xc0 | REG_ECX | ((host_reg & 7) << 3)); + addbyte(0xc0 | REG_EBX | ((host_reg & 7) << 3)); - return REG_ECX | (host_reg & 0x10); + return REG_EBX | (host_reg & 0x10); } static int ZERO_EXTEND_W_B(int reg) @@ -3897,6 +3908,26 @@ static void FP_POP() addbyte(0x45); addbyte(cpu_state_offset(TOP)); } +static void FP_POP2() +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x44); + addbyte(0x05); + addbyte(cpu_state_offset(tag)); + addbyte(3); + addbyte(0x83); /*ADD AL, 2*/ + addbyte(0xc0); + addbyte(2); + addbyte(0x83); /*AND AL, 7*/ + addbyte(0xe0); + addbyte(7); + addbyte(0x89); /*MOV [TOP], EAX*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); +} static void FP_LOAD_S() { @@ -4074,6 +4105,65 @@ static void FP_LOAD_IQ() addbyte(cpu_state_offset(tag)); } +static void FP_LOAD_IMM_Q(uint64_t v) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST) + 4); + addlong(v >> 32); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0xc6); /*MOV [tag+EBX], (v ? 0 : 1)*/ + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag)); + addbyte(v ? 0 : 1); +} + +static void FP_FCHS() +{ + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0xf2); /*SUBSD XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc0); + addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ + addbyte(0x0f); + addbyte(0x11); + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); +} + static int FP_LOAD_REG(int reg) { addbyte(0x8b); /*MOV EBX, TOP*/ @@ -5923,3 +6013,17 @@ static void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) call_long(writememll); /*done:*/ } + +static void LOAD_SEG(int host_reg, void *seg) +{ + load_param_2_64(&codeblock[block_current], (uint64_t)seg); + load_param_1_reg_32(host_reg); + CALL_FUNC(loadseg); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte(cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 1ae11dd6e..ac6111669 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -145,6 +145,18 @@ static int LOAD_VAR_W(uintptr_t addr) return host_reg; } +static int LOAD_VAR_WL(uintptr_t addr) +{ + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0x0f); /*MOVZX host_reg, [addr]*/ + addbyte(0xb7); + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t)addr); + + return host_reg; +} static int LOAD_VAR_L(uintptr_t addr) { int host_reg = find_host_reg(); @@ -693,6 +705,19 @@ static void MEM_LOAD_ADDR_EA_W(x86seg *seg) host_reg_mapping[0] = 8; } +static void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +{ + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0xc0); + addbyte(offset); + addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ + addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} static int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) { addbyte(0x8b); /*MOVL EDX, seg->base*/ @@ -2169,6 +2194,59 @@ static void FP_LOAD_IQ() } } +static void FP_LOAD_IMM_Q(uint64_t v) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xc7); /*MOV ST[reg][EBP], v*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(v ? 0 : 1); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(v ? 0 : 1); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + } +} + static int FP_LOAD_REG(int reg) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) @@ -2425,6 +2503,42 @@ static void FP_POP() addbyte(cpu_state_offset(TOP)); } } +static void FP_POP2() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(3); + addbyte(0xc6); /*MOVB tag[1][EBP], 3*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP+1)&7])); + addbyte(3); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP+2) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP + 2) & 7); + } + else + { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x44); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(3); + addbyte(0x04); /*ADD AL, 2*/ + addbyte(2); + addbyte(0x24); /*AND AL, 7*/ + addbyte(7); + addbyte(0x88); /*MOV TOP, AL*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + } +} #define FPU_ADD 0x00 #define FPU_DIV 0x30 @@ -3162,6 +3276,47 @@ static void FP_COMPARE_REG(int dst, int src) } } +static void FP_FCHS() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + } + else + { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + } +} + static void UPDATE_NPXC(int reg) { addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ @@ -3664,3 +3819,23 @@ static void MEM_CHECK_WRITE_L(x86seg *seg) addlong(mem_check_write_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); LOAD_EA(); } + +static void LOAD_SEG(int host_reg, void *seg) +{ + addbyte(0xc7); /*MOV [ESP+4], seg*/ + addbyte(0x44); + addbyte(0x24); + addbyte(4); + addlong((uint32_t)seg); + addbyte(0x89); /*MOV [ESP], host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(0x24); + CALL_FUNC(loadseg); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte(cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 46f2d79e7..65eddfabd 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -550,17 +550,21 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT() addbyte(0x83); /*ADD ESP, 8*/ addbyte(0xc4); addbyte(8); +#ifndef RELEASE_BUILD addbyte(0x80); /*CMP abrt, 0*/ addbyte(0x7d); addbyte(cpu_state_offset(abrt)); addbyte(0); +#endif addbyte(0x0f); /*MOVZX ECX, AL*/ addbyte(0xb6); addbyte(0xc8); +#ifndef RELEASE_BUILD addbyte(0x75); /*JNE mem_abrt_rout*/ addbyte(1); +#endif addbyte(0xc3); /*RET*/ - +#ifndef RELEASE_BUILD addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/ addbyte(0x04); addbyte(0x24); @@ -568,7 +572,7 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT() addbyte(0xe8); /*CALL fatal*/ addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); /*Should not return!*/ - +#endif return addr; } @@ -615,17 +619,21 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT() addbyte(0x83); /*ADD ESP, 8*/ addbyte(0xc4); addbyte(8); +#ifndef RELEASE_BUILD addbyte(0x80); /*CMP abrt, 0*/ addbyte(0x7d); addbyte(cpu_state_offset(abrt)); addbyte(0); +#endif addbyte(0x0f); /*MOVZX ECX, AX*/ addbyte(0xb7); addbyte(0xc8); +#ifndef RELEASE_BUILD addbyte(0x75); /*JNE mem_abrt_rout*/ addbyte(1); +#endif addbyte(0xc3); /*RET*/ - +#ifndef RELEASE_BUILD addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/ addbyte(0x04); addbyte(0x24); @@ -633,7 +641,7 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT() addbyte(0xe8); /*CALL fatal*/ addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); /*Should not return!*/ - +#endif return addr; } @@ -681,14 +689,16 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT() addbyte(8); addbyte(0x89); /*MOV ECX, EAX*/ addbyte(0xc1); +#ifndef RELEASE_BUILD addbyte(0x80); /*CMP abrt, 0*/ addbyte(0x7d); addbyte(cpu_state_offset(abrt)); addbyte(0); addbyte(0x75); /*JNE mem_abrt_rout*/ addbyte(1); +#endif addbyte(0xc3); /*RET*/ - +#ifndef RELEASE_BUILD addbyte(0x83); /*SUBL 4,%esp*/ addbyte(0xEC); addbyte(4); @@ -699,7 +709,7 @@ static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT() addbyte(0xe8); /*CALL fatal*/ addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); /*Should not return!*/ - +#endif return addr; } @@ -740,14 +750,16 @@ static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT() addbyte(0x83); /*ADD ESP, 12*/ addbyte(0xc4); addbyte(12); +#ifndef RELEASE_BUILD addbyte(0x80); /*CMP abrt, 0*/ addbyte(0x7d); addbyte(cpu_state_offset(abrt)); addbyte(0); addbyte(0x75); /*JNE mem_abrt_rout*/ addbyte(1); +#endif addbyte(0xc3); /*RET*/ - +#ifndef RELEASE_BUILD addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/ addbyte(0x04); addbyte(0x24); @@ -755,7 +767,7 @@ static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT() addbyte(0xe8); /*CALL fatal*/ addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); /*Should not return!*/ - +#endif return addr; } @@ -804,14 +816,16 @@ static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT() addbyte(0x83); /*ADD ESP, 12*/ addbyte(0xc4); addbyte(12); +#ifndef RELEASE_BUILD addbyte(0x80); /*CMP abrt, 0*/ addbyte(0x7d); addbyte(cpu_state_offset(abrt)); addbyte(0); addbyte(0x75); /*JNE mem_abrt_rout*/ addbyte(1); +#endif addbyte(0xc3); /*RET*/ - +#ifndef RELEASE_BUILD addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ addbyte(0x04); addbyte(0x24); @@ -819,7 +833,7 @@ static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT() addbyte(0xe8); /*CALL fatal*/ addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); /*Should not return!*/ - +#endif return addr; } @@ -867,14 +881,16 @@ static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT() addbyte(0x83); /*ADD ESP, 12*/ addbyte(0xc4); addbyte(12); +#ifndef RELEASE_BUILD addbyte(0x80); /*CMP abrt, 0*/ addbyte(0x7d); addbyte(cpu_state_offset(abrt)); addbyte(0); addbyte(0x75); /*JNE mem_abrt_rout*/ addbyte(1); +#endif addbyte(0xc3); /*RET*/ - +#ifndef RELEASE_BUILD addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ addbyte(0x04); addbyte(0x24); @@ -882,7 +898,7 @@ static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT() addbyte(0xe8); /*CALL fatal*/ addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); /*Should not return!*/ - +#endif return addr; } diff --git a/src/cpu.c b/src/cpu.c index a1d6facde..f40ec1682 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -77,8 +77,13 @@ int cpu_use_dynarec; uint64_t cpu_CR4_mask; +int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l; +int cpu_prefetch_cycles, cpu_prefetch_width; +int cpu_waitstates; +int cpu_cache_int_enabled, cpu_cache_ext_enabled; + int is286, is386; -int israpidcad; +int israpidcad, is_pentium; uint64_t tsc = 0; @@ -159,218 +164,251 @@ static struct CPU cpus_8088[] = { /*8088 standard*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0}, - {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0}, - {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0}, - {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0}, - {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0}, - {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0}, - {"", -1, 0, 0, 0, 0} + {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"", -1, 0, 0, 0, 0, 0,0,0,0} }; CPU cpus_pcjr[] = { /*8088 PCjr*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0}, - {"", -1, 0, 0, 0, 0} + {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"", -1, 0, 0, 0, 0, 0,0,0,0} }; CPU cpus_8086[] = { /*8086 standard*/ - {"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0}, - {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0}, - {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0}, - {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0}, - {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0}, - {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0}, - {"", -1, 0, 0, 0, 0} + {"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"", -1, 0, 0, 0, 0, 0,0,0,0} }; CPU cpus_pc1512[] = { /*8086 Amstrad*/ - {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0}, - {"", -1, 0, 0, 0, 0} + {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0}, + {"", -1, 0, 0, 0, 0, 0,0,0,0} }; CPU cpus_286[] = { /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0}, - {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0}, - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0}, - {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0}, - {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0}, - {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0}, - {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0}, + {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2}, + {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2}, + {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2}, + {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3}, + {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3}, + {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4}, + {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4}, {"", -1, 0, 0, 0, 0} }; CPU cpus_ibmat[] = { /*286*/ - {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0}, - {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0}, + {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3}, + {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3}, {"", -1, 0, 0, 0, 0} }; CPU cpus_ps1_m2011[] = { /*286*/ - {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0}, + {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2}, {"", -1, 0, 0, 0, 0} }; CPU cpus_i386[] = { /*i386*/ - {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0}, - {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0}, - {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0}, - {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0}, - {"i386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0}, - {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0}, - {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0}, - {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0}, - {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0}, - {"i386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0}, - {"RapidCAD/25", CPU_RAPIDCAD, 2, 25000000, 1, 0, 0x430, 0, 0, 0}, - {"RapidCAD/33", CPU_RAPIDCAD, 3, 33333333, 1, 0, 0x430, 0, 0, 0}, - {"RapidCAD/40", CPU_RAPIDCAD, 4, 40000000, 1, 0, 0x430, 0, 0, 0}, + {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3}, + {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3}, + {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3}, + {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3}, + {"i386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3}, + {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3}, + {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3}, + {"i386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3}, + {"RapidCAD/25", CPU_RAPIDCAD, 2, 25000000, 1, 0, 0x430, 0, 0, 0, 4,4,3,3}, + {"RapidCAD/33", CPU_RAPIDCAD, 3, 33333333, 1, 0, 0x430, 0, 0, 0, 6,6,3,3}, + {"RapidCAD/40", CPU_RAPIDCAD, 4, 40000000, 1, 0, 0x430, 0, 0, 0, 7,7,3,3}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_i386DX[] = +{ + /*i386*/ + {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3}, + {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3}, + {"i386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3}, + {"RapidCAD/25", CPU_RAPIDCAD, 2, 25000000, 1, 0, 0x430, 0, 0, 0, 4,4,3,3}, + {"RapidCAD/33", CPU_RAPIDCAD, 3, 33333333, 1, 0, 0x430, 0, 0, 0, 6,6,3,3}, + {"RapidCAD/40", CPU_RAPIDCAD, 4, 40000000, 1, 0, 0x430, 0, 0, 0, 7,7,3,3}, {"", -1, 0, 0, 0} }; CPU cpus_acer[] = { /*i386*/ - {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0}, + {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4}, {"", -1, 0, 0, 0} }; CPU cpus_Am386[] = { /*Am386*/ - {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0}, - {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0}, - {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0}, - {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0}, - {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0}, - {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0}, - {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0}, - {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0}, + {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3}, + {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3}, + {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3}, + {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3}, + {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3}, + {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3}, + {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_Am386DX[] = + +{ + /*Am386*/ + {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3}, + {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3}, + {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3}, {"", -1, 0, 0, 0} }; CPU cpus_486SDLC[] = { /*Cx486SLC/DLC*/ - {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0, 0, 0x0000, 0}, - {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0, 0, 0x0000, 0}, - {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0, 0, 0x0000, 0}, - {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0, 0, 0x0006, 0}, - {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0, 0, 0x0006, 0}, - {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0, 0, 0x0006, 0}, - {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0, 0, 0x0001, 0}, - {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0, 0, 0x0001, 0}, - {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0, 0, 0x0001, 0}, - {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0, 0, 0x0007, 0}, - {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0, 0, 0x0007, 0}, - {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0, 0, 0x0007, 0}, - {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0, 0, 0x0007, 0}, + {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3}, + {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3}, + {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3}, + {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6}, + {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6}, + {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6}, + {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3}, + {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3}, + {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3}, + {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6}, + {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6}, + {"", -1, 0, 0, 0} +}; + +CPU cpus_486DLC[] = +{ + /*Cx486DLC*/ + {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3}, + {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3}, + {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3}, + {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6}, + {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6}, + {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6}, {"", -1, 0, 0, 0} }; CPU cpus_i486[] = { /*i486*/ - {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"iDX4/75", CPU_i486DX, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC}, /*CPUID available on DX4, >= 75 MHz*/ - {"iDX4/100", CPU_i486DX,10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ - {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3}, + {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3}, + {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3}, + {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3}, + {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6}, + {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3}, + {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3}, + {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4}, + {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6}, + {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6}, + {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6}, + {"iDX4/75", CPU_i486DX, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, /*CPUID available on DX4, >= 75 MHz*/ + {"iDX4/100", CPU_i486DX,10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ + {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7}, + {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8}, {"", -1, 0, 0, 0} }; CPU cpus_Am486[] = { /*Am486/5x86*/ - {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ - {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ - {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC}, - {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC}, - {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC}, - {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC}, + {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3}, + {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3}, + {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/ + {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/ + {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3}, + {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3}, + {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6}, + {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6}, + {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6}, + {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, + {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9}, + {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9}, + {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9}, + {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12}, + {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12}, {"", -1, 0, 0, 0} }; CPU cpus_Cx486[] = { /*Cx486/5x86*/ - {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC}, - {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC}, - {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC}, - {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC}, - {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC}, - {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC}, - {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC}, + {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3}, + {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3}, + {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3}, + {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3}, + {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3}, + {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6}, + {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6}, + {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16}, + {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, + {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9}, + {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9}, + {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9}, + {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12}, {"", -1, 0, 0, 0} }; CPU cpus_6x86[] = { /*Cyrix 6x86*/ - {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6}, + {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, /*Cyrix 6x86L*/ - {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, /*Cyrix 6x86MX*/ - {"6x86MX-PR90/75",CPU_Cx6x86MX, 18, 75000000, 2, 25000000, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR90", CPU_Cx6x86MX, 18, 90000000, 2, 30000000, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR133", CPU_Cx6x86MX, 18, 100000000, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR150", CPU_Cx6x86MX, 18, 120000000, 3, 30000000, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7}, + {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7}, + {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9}, + {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12}, + {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, {"", -1, 0, 0, 0} }; @@ -379,191 +417,164 @@ CPU cpus_Cx486[] = CPU cpus_WinChip[] = { /*IDT WinChip*/ - {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, - {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC}, + {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4}, + {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4}, + {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4}, + {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6}, + {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6}, + {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7}, + {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7}, + {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, + {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, + {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, + {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12}, {"", -1, 0, 0, 0} }; CPU cpus_Pentium5V[] = { /*Intel Pentium (5V, socket 4)*/ - {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, {"", -1, 0, 0, 0} }; CPU cpus_Pentium5V50[] = { /*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/ - {"Pentium 50 (Q0399)",CPU_PENTIUM, 5, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 100",CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"Pentium 50 (Q0399)",CPU_PENTIUM, 5, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3}, + {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium OverDrive 100",CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6}, + {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, {"", -1, 0, 0, 0} }; CPU cpus_PentiumS5[] = { /*Intel Pentium (Socket 5)*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7}, + {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, {"", -1, 0, 0, 0} }; CPU cpus_Pentium[] = { /*Intel Pentium*/ - {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium OverDrive MMX 75",CPU_PENTIUMMMX,9,75000000,2,25000000,0x1542,0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6}, + {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10}, + {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10}, + {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12}, + {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13}, + {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7}, + {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7}, + {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, {"", -1, 0, 0, 0} }; CPU cpus_K5[] = { /*AMD K5 (Socket 5)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 9, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 9, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 90 (P90)", CPU_K5, 12, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 12, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 100 (P100)", CPU_K5, 13, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (SSA/5) 100 (PR100)",CPU_K5, 13, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 14, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 16, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 17, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 116.5 (PR166)",CPU_5K86, 19, 166666666,3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 21, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"K5 (5k86) 75 (P75)", CPU_K5, 9, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 9, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"K5 (5k86) 90 (P90)", CPU_K5, 12, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 12, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (5k86) 100 (P100)", CPU_K5, 13, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (SSA/5) 100 (PR100)",CPU_K5, 13, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 14, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 16, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 17, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"K5 (5k86) 116.5 (PR166)",CPU_5K86, 19, 166666666,3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 21, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, {"", -1, 0, 0, 0} }; CPU cpus_K56[] = { /*AMD K5 and K6 (Socket 7)*/ - {"K5 (5k86) 75 (P75)", CPU_K5, 9, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (SSA/5) 75 (PR75)", CPU_K5, 9, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 90 (P90)", CPU_K5, 12, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (SSA/5) 90 (PR90)", CPU_K5, 12, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 100 (P100)", CPU_K5, 13, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (SSA/5) 100 (PR100)",CPU_K5, 13, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 90 (PR120)", CPU_5K86, 14, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 100 (PR133)", CPU_5K86, 16, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 105 (PR150)", CPU_5K86, 17, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 116.5 (PR166)",CPU_5K86, 19, 166666666,3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K5 (5k86) 133 (PR200)", CPU_5K86, 21, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 6) 166", CPU_K6, 19, 166666666, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 6) 200", CPU_K6, 21, 200000000, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 6) 233", CPU_K6, 24, 233333333, 4, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 7) 200", CPU_K6, 21, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 7) 233", CPU_K6, 24, 233333333, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 7) 266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"K6 (Model 7) 300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"K5 (5k86) 75 (P75)", CPU_K5, 9, 75000000, 2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"K5 (SSA/5) 75 (PR75)", CPU_K5, 9, 75000000, 2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"K5 (5k86) 90 (P90)", CPU_K5, 12, 90000000, 2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (SSA/5) 90 (PR90)", CPU_K5, 12, 90000000, 2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (5k86) 100 (P100)", CPU_K5, 13, 100000000, 2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (SSA/5) 100 (PR100)",CPU_K5, 13, 100000000, 2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4}, + {"K5 (5k86) 90 (PR120)", CPU_5K86, 14, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"K5 (5k86) 100 (PR133)", CPU_5K86, 16, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6}, + {"K5 (5k86) 105 (PR150)", CPU_5K86, 17, 150000000, 3, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"K5 (5k86) 116.5 (PR166)",CPU_5K86, 19, 166666666,3, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"K5 (5k86) 133 (PR200)", CPU_5K86, 21, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"K6 (Model 6) 166", CPU_K6, 19, 166666666, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"K6 (Model 6) 200", CPU_K6, 21, 200000000, 3, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"K6 (Model 6) 233", CPU_K6, 24, 233333333, 4, 33333333, 0x562, 0x562, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10}, + {"K6 (Model 7) 200", CPU_K6, 21, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"K6 (Model 7) 233", CPU_K6, 24, 233333333, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10}, + {"K6 (Model 7) 266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12}, + {"K6 (Model 7) 300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13}, {"", -1, 0, 0, 0} }; CPU cpus_PentiumPro[] = { /*Intel Pentium Pro and II Overdrive*/ - {"Pentium Pro 50", CPU_PENTIUMPRO, 5, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 60" , CPU_PENTIUMPRO, 6, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 66" , CPU_PENTIUMPRO, 6, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 75", CPU_PENTIUMPRO, 9, 75000000, 2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 150", CPU_PENTIUMPRO, 17, 150000000, 3, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 166", CPU_PENTIUMPRO, 19, 166666666, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 180", CPU_PENTIUMPRO, 20, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium Pro 200", CPU_PENTIUMPRO, 21, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 50", CPU_PENTIUM2D, 5, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 60", CPU_PENTIUM2D, 6, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 66", CPU_PENTIUM2D, 6, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 75", CPU_PENTIUM2D, 9, 75000000, 2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 210", CPU_PENTIUM2D, 22, 210000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 233", CPU_PENTIUM2D, 24, 233333333, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 240", CPU_PENTIUM2D, 25, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 266", CPU_PENTIUM2D, 26, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 270", CPU_PENTIUM2D, 27, 270000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 300/66",CPU_PENTIUM2D, 28, 300000000, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 300/60",CPU_PENTIUM2D, 28, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II Overdrive 333", CPU_PENTIUM2D, 29, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, + {"Pentium Pro 50", CPU_PENTIUMPRO, 5, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3}, + {"Pentium Pro 60" , CPU_PENTIUMPRO, 6, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium Pro 66" , CPU_PENTIUMPRO, 6, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium Pro 75", CPU_PENTIUMPRO, 9, 75000000, 2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium Pro 150", CPU_PENTIUMPRO, 17, 150000000, 3, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium Pro 166", CPU_PENTIUMPRO, 19, 166666666, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7}, + {"Pentium Pro 180", CPU_PENTIUMPRO, 20, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Pentium Pro 200", CPU_PENTIUMPRO, 21, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9}, + {"Pentium II Overdrive 50", CPU_PENTIUM2D, 5, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4,4,3,3}, + {"Pentium II Overdrive 60", CPU_PENTIUM2D, 6, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium II Overdrive 66", CPU_PENTIUM2D, 6, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3}, + {"Pentium II Overdrive 75", CPU_PENTIUM2D, 9, 75000000, 2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4}, + {"Pentium II Overdrive 210", CPU_PENTIUM2D, 22, 210000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7}, + {"Pentium II Overdrive 233", CPU_PENTIUM2D, 24, 233333333, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,1}, + {"Pentium II Overdrive 240", CPU_PENTIUM2D, 25, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12}, + {"Pentium II Overdrive 266", CPU_PENTIUM2D, 26, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12}, + {"Pentium II Overdrive 270", CPU_PENTIUM2D, 27, 270000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12}, + {"Pentium II Overdrive 300/66",CPU_PENTIUM2D, 28, 300000000, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12}, + {"Pentium II Overdrive 300/60",CPU_PENTIUM2D, 28, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13}, + {"Pentium II Overdrive 333", CPU_PENTIUM2D, 29, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13}, {"", -1, 0, 0, 0} }; -#if 0 -CPU cpus_Pentium2[] = -{ - /*Intel Pentium II Klamath*/ - {"Pentium II 75", CPU_PENTIUM2, 9, 75000000, 2, 25000000, 0x632, 0x632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II 75 (634)",CPU_PENTIUM2, 9, 75000000, 2, 25000000, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II 233", CPU_PENTIUM2, 24, 233333333, 4, 33333333, 0x632, 0x632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II 266", CPU_PENTIUM2, 26, 266666666, 4, 33333333, 0x633, 0x633, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II 300", CPU_PENTIUM2, 28, 300000000, 5, 33333333, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"", -1, 0, 0, 0} -}; - -CPU cpus_Pentium2D[] = -{ - /*Intel Pentium II Deschutes*/ - {"Pentium II D 75", CPU_PENTIUM2D, 9, 75000000, 2, 25000000, 0x654, 0x654, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 266", CPU_PENTIUM2D, 26, 266666666, 4, 33333333, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 300", CPU_PENTIUM2D, 28, 300000000, 5, 33333333, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 333", CPU_PENTIUM2D, 29, 333333333, 5, 33333333, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 350", CPU_PENTIUM2D, 30, 350000000, 4, 50000000, 0x653, 0x653, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 400", CPU_PENTIUM2D, 31, 400000000, 4, 50000000, 0x653, 0x653, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 450", CPU_PENTIUM2D, 32, 450000000, 5, 50000000, 0x654, 0x654, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"Pentium II D 500", CPU_PENTIUM2D, 33, 500000000, 5, 50000000, 0x654, 0x654, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC}, - {"", -1, 0, 0, 0} -}; -#endif - void cpu_set_edx() { EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; @@ -589,9 +600,10 @@ void cpu_set() is386 = (cpu_s->cpu_type >= CPU_386SX); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD); + is_pentium= (cpu_s->cpu_type >= CPU_WINCHIP); hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); - cpu_16bitbus = (cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC); + cpu_16bitbus = cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC); if (cpu_s->multi) cpu_busspeed = cpu_s->rspeed / cpu_s->multi; cpu_multi = cpu_s->multi; @@ -601,6 +613,8 @@ void cpu_set() cpu_hasCR4 = 0; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; + cpu_update_waitstates(); + isa_cycles = (int)(((int64_t)cpu_s->rspeed << ISA_CYCLES_SHIFT) / 8000000ll); if (cpu_s->pci_speed) @@ -2318,3 +2332,43 @@ void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn x86_dynarec_opcodes = dynarec_opcodes; x86_dynarec_opcodes_0f = dynarec_opcodes_0f; } + +void cpu_update_waitstates() +{ + cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu]; + + cpu_prefetch_width = cpu_16bitbus ? 2 : 4; + + if (cpu_cache_int_enabled) + { + /* Disable prefetch emulation */ + cpu_prefetch_cycles = 0; + } + else if (cpu_waitstates && (cpu_s->cpu_type >= CPU_286 && cpu_s->cpu_type <= CPU_386DX)) + { + /* Waitstates override */ + cpu_prefetch_cycles = cpu_waitstates+1; + cpu_cycles_read = cpu_waitstates+1; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); + cpu_cycles_write = cpu_waitstates+1; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); + } + else if (cpu_cache_ext_enabled) + { + /* Use cache timings */ + cpu_prefetch_cycles = cpu_s->cache_read_cycles; + cpu_cycles_read = cpu_s->cache_read_cycles; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_read_cycles; + cpu_cycles_write = cpu_s->cache_write_cycles; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_write_cycles; + } + else + { + /* Use memory timings */ + cpu_prefetch_cycles = cpu_s->mem_read_cycles; + cpu_cycles_read = cpu_s->mem_read_cycles; + cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_read_cycles; + cpu_cycles_write = cpu_s->mem_write_cycles; + cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; + } +} diff --git a/src/cpu.h b/src/cpu.h index a07549eab..b75ee35b5 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -78,14 +78,19 @@ typedef struct uint32_t cpuid_model; uint16_t cyrix_id; int cpu_flags; + int mem_read_cycles, mem_write_cycles; + int cache_read_cycles, cache_write_cycles; } CPU; extern CPU cpus_8088[]; extern CPU cpus_8086[]; extern CPU cpus_286[]; extern CPU cpus_i386[]; +extern CPU cpus_i386DX[]; extern CPU cpus_Am386[]; +extern CPU cpus_Am386DX[]; extern CPU cpus_486SDLC[]; +extern CPU cpus_486DLC[]; extern CPU cpus_i486[]; extern CPU cpus_Am486[]; extern CPU cpus_Cx486[]; @@ -129,6 +134,11 @@ extern uint64_t cpu_CR4_mask; #define CPU_REQUIRES_DYNAREC 2 // #define CPU_REQUIRES_DYNAREC 0 +extern int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l; +extern int cpu_prefetch_cycles, cpu_prefetch_width; +extern int cpu_waitstates; +extern int cpu_cache_int_enabled, cpu_cache_ext_enabled; + extern uint64_t tsc; void cyrix_write(uint16_t addr, uint8_t val, void *priv); @@ -149,4 +159,6 @@ extern int xt_cpu_multi; extern int isa_cycles; #define ISA_CYCLES(x) ((x * isa_cycles) >> ISA_CYCLES_SHIFT) +void cpu_update_waitstates(); + #endif diff --git a/src/device.c b/src/device.c index 66d74c179..44f6cb5e9 100644 --- a/src/device.c +++ b/src/device.c @@ -1,9 +1,8 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include "ibm.h" #include "config.h" +#include "cpu.h" #include "device.h" +#include "model.h" #include "sound.h" static void *device_priv[256]; @@ -19,9 +18,9 @@ void device_init() void device_add(device_t *d) { int c = 0; - void *priv; + void *priv = NULL; - while ((c < 256) && (devices[c] != NULL)) + while (devices[c] != NULL && c < 256) c++; if (c >= 256) @@ -29,9 +28,12 @@ void device_add(device_t *d) current_device = d; - priv = d->init(); - if (priv == NULL) - fatal("device_add : device init failed\n"); + if (d->init != NULL) + { + priv = d->init(); + if (priv == NULL) + fatal("device_add : device init failed\n"); + } devices[c] = d; device_priv[c] = priv; @@ -45,7 +47,8 @@ void device_close_all() { if (devices[c] != NULL) { - devices[c]->close(device_priv[c]); + if (devices[c]->close != NULL) + devices[c]->close(device_priv[c]); devices[c] = device_priv[c] = NULL; } } @@ -77,8 +80,8 @@ void device_speed_changed() } } } - - sound_speed_changed(); + + sound_speed_changed(); } void device_force_redraw() @@ -138,3 +141,43 @@ char *device_get_config_string(char *s) } return NULL; } + +int model_get_config_int(char *s) +{ + device_t *device = model_getdevice(model); + device_config_t *config; + + if (!device) + return 0; + + config = device->config; + + while (config->type != -1) + { + if (!strcmp(s, config->name)) + return config_get_int(device->name, s, config->default_int); + + config++; + } + return 0; +} + +char *model_get_config_string(char *s) +{ + device_t *device = model_getdevice(model); + device_config_t *config; + + if (!device) + return 0; + + config = device->config; + + while (config->type != -1) + { + if (!strcmp(s, config->name)) + return config_get_string(device->name, s, config->default_string); + + config++; + } + return NULL; +} diff --git a/src/device.h b/src/device.h index f4eb9aa35..970b4067f 100644 --- a/src/device.h +++ b/src/device.h @@ -1,6 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #define CONFIG_STRING 0 #define CONFIG_INT 1 #define CONFIG_BINARY 2 @@ -51,3 +48,6 @@ enum { DEVICE_NOT_WORKING = 1 /*Device does not currently work correctly and will be disabled in a release build*/ }; + +int model_get_config_int(char *s); +char *model_get_config_string(char *s); diff --git a/src/disc.c b/src/disc.c index 372a88cd7..2b2632e2a 100644 --- a/src/disc.c +++ b/src/disc.c @@ -14,20 +14,19 @@ #include "fdd.h" #include "timer.h" -int disc_poll_time[2] = { 16, 16 }; +int disc_poll_time[FDD_NUM] = { 16, 16, 16, 16 }; -int disc_track[2]; -int writeprot[2], fwriteprot[2]; +int disc_track[FDD_NUM]; +int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; -DRIVE drives[2]; -int drive_type[2]; +DRIVE drives[FDD_NUM]; +int drive_type[FDD_NUM]; int curdrive = 0; int swwp = 0; int disable_write = 0; -//char discfns[2][260] = {"", ""}; int defaultwriteprot = 0; int fdc_time; @@ -35,11 +34,11 @@ int disc_time; int fdc_ready; -int drive_empty[2] = {1, 1}; -int disc_changed[2]; +int drive_empty[FDD_NUM] = {1, 1, 1, 1}; +int disc_changed[FDD_NUM]; int motorspin; -int motoron[2]; +int motoron[FDD_NUM]; int fdc_indexcount = 52; @@ -111,8 +110,8 @@ void disc_load(int drive, char *fn) loaders[c].load(drive, fn); drive_empty[drive] = 0; strcpy(discfns[drive], fn); - fdd_set_head(drive ^ fdd_swap, 0); - fdd_forced_seek(drive ^ fdd_swap, 0); + // fdd_set_head(real_drive(drive), 0); + fdd_forced_seek(real_drive(drive), 0); disc_changed[drive] = 1; return; } @@ -120,7 +119,7 @@ void disc_load(int drive, char *fn) } pclog("Couldn't load %s %s\n",fn,p); drive_empty[drive] = 1; - fdd_set_head(drive ^ fdd_swap, 0); + fdd_set_head(real_drive(drive), 0); discfns[drive][0] = 0; } @@ -129,7 +128,7 @@ void disc_close(int drive) // pclog("disc_close %i\n", drive); if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); drive_empty[drive] = 1; - fdd_set_head(drive ^ fdd_swap, 0); + fdd_set_head(real_drive(drive), 0); discfns[drive][0] = 0; drives[drive].hole = NULL; drives[drive].poll = NULL; @@ -148,7 +147,7 @@ static int disc_period = 32; int disc_hole(int drive) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].hole) { @@ -162,7 +161,7 @@ int disc_hole(int drive) double disc_byteperiod(int drive) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].byteperiod) { @@ -179,7 +178,7 @@ double disc_real_period(int drive) double ddbp; double dusec; - ddbp = disc_byteperiod(drive ^ fdd_swap); + ddbp = disc_byteperiod(real_drive(drive)); dusec = (double) TIMER_USEC; @@ -188,7 +187,7 @@ double disc_real_period(int drive) void disc_poll(int drive) { - if (drive > 1) + if (drive >= FDD_NUM) { disc_poll_time[drive] += (int) (32.0 * TIMER_USEC); return; @@ -203,7 +202,7 @@ void disc_poll(int drive) { disc_notfound--; if (!disc_notfound) - fdc_notfound(); + fdc_noidam(); } } @@ -217,6 +216,16 @@ void disc_poll_1() disc_poll(1); } +void disc_poll_2() +{ + disc_poll(2); +} + +void disc_poll_3() +{ + disc_poll(3); +} + int disc_get_bitcell_period(int rate) { int bit_rate; @@ -276,18 +285,20 @@ void disc_reset() disc_period = 32; timer_add(disc_poll_0, &(disc_poll_time[0]), &(motoron[0]), NULL); timer_add(disc_poll_1, &(disc_poll_time[1]), &(motoron[1]), NULL); + timer_add(disc_poll_2, &(disc_poll_time[2]), &(motoron[2]), NULL); + timer_add(disc_poll_3, &(disc_poll_time[3]), &(motoron[3]), NULL); } void disc_init() { // pclog("disc_init %p\n", drives); - drives[0].poll = drives[1].poll = 0; - drives[0].seek = drives[1].seek = 0; - drives[0].readsector = drives[1].readsector = 0; + drives[0].poll = drives[1].poll = drives[2].poll = drives[3].poll = 0; + drives[0].seek = drives[1].seek = drives[2].seek = drives[3].seek = 0; + drives[0].readsector = drives[1].readsector = drives[2].readsector = drives[3].readsector = 0; disc_reset(); } -int oldtrack[2] = {0, 0}; +int oldtrack[FDD_NUM] = {0, 0, 0, 0}; void disc_seek(int drive, int track) { // pclog("disc_seek: drive=%i track=%i\n", drive, track); @@ -301,7 +312,7 @@ void disc_seek(int drive, int track) void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].readsector) drives[drive].readsector(drive, sector, track, side, density, sector_size); @@ -311,7 +322,7 @@ void disc_readsector(int drive, int sector, int track, int side, int density, in void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].writesector) drives[drive].writesector(drive, sector, track, side, density, sector_size); @@ -321,7 +332,7 @@ void disc_writesector(int drive, int sector, int track, int side, int density, i void disc_comparesector(int drive, int sector, int track, int side, int density, int sector_size) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].comparesector) drives[drive].comparesector(drive, sector, track, side, density, sector_size); @@ -331,7 +342,7 @@ void disc_comparesector(int drive, int sector, int track, int side, int density, void disc_readaddress(int drive, int track, int side, int density) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].readaddress) drives[drive].readaddress(drive, track, side, density); @@ -339,7 +350,7 @@ void disc_readaddress(int drive, int track, int side, int density) void disc_format(int drive, int track, int side, int density, uint8_t fill) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].format) drives[drive].format(drive, track, side, density, fill); @@ -349,7 +360,7 @@ void disc_format(int drive, int track, int side, int density, uint8_t fill) void disc_stop(int drive) { - drive ^= fdd_swap; + drive = real_drive(drive); if (drives[drive].stop) drives[drive].stop(drive); diff --git a/src/disc.h b/src/disc.h index aa9b077d7..54abe9e38 100644 --- a/src/disc.h +++ b/src/disc.h @@ -1,6 +1,8 @@ /* Copyright holders: Sarah Walker, Tenshi see COPYING for more details */ +#define FDD_NUM 4 + typedef struct { void (*seek)(int drive, int track); @@ -15,7 +17,7 @@ typedef struct void (*poll)(int drive); } DRIVE; -extern DRIVE drives[2]; +extern DRIVE drives[FDD_NUM]; extern int curdrive; @@ -39,13 +41,12 @@ void disc_stop(int drive); int disc_empty(int drive); void disc_set_rate(int drive, int drvden, int rate); extern int disc_time; -extern int disc_poll_time[2]; +extern int disc_poll_time[FDD_NUM]; void fdc_callback(); int fdc_data(uint8_t dat); void fdc_spindown(); void fdc_finishread(); -void fdc_notfound(); void fdc_datacrcerror(); void fdc_headercrcerror(); void fdc_writeprotect(); @@ -57,7 +58,7 @@ extern int fdc_ready; extern int fdc_indexcount;*/ extern int motorspin; -extern int motoron[2]; +extern int motoron[FDD_NUM]; extern int swwp; extern int disable_write; @@ -65,16 +66,17 @@ extern int disable_write; extern int defaultwriteprot; //extern char discfns[4][260]; -extern int writeprot[2], fwriteprot[2]; -extern int disc_track[2]; -extern int disc_changed[2]; -extern int drive_empty[2]; -extern int drive_type[2]; +extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; +extern int disc_track[FDD_NUM]; +extern int disc_changed[FDD_NUM]; +extern int drive_empty[FDD_NUM]; +extern int drive_type[FDD_NUM]; /*Used in the Read A Track command. Only valid for disc_readsector(). */ #define SECTOR_FIRST -2 #define SECTOR_NEXT -1 +#if 0 /* Bits 0-3 define byte type, bit 5 defines whether it is a per-track (0) or per-sector (1) byte, if bit 7 is set, the byte is the index hole. */ #define BYTE_GAP0 0x00 #define BYTE_GAP1 0x10 @@ -108,6 +110,7 @@ extern int drive_type[2]; #define BYTE_TYPE_AM 0x03 #define BYTE_TYPE_DATA 0x04 #define BYTE_TYPE_CRC 0x05 +#endif typedef union { uint16_t word; @@ -133,7 +136,7 @@ typedef struct uint8_t check_crc; } d86f_handler_t; -d86f_handler_t d86f_handler[2]; +d86f_handler_t d86f_handler[FDD_NUM]; void d86f_common_handlers(int drive); diff --git a/src/disc_86f.c b/src/disc_86f.c index 5c09ff38a..9969d39db 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -9,6 +9,7 @@ #include "lzf/lzf.h" #include "config.h" +#include "dma.h" #include "disc.h" #include "disc_86f.h" #include "disc_random.h" @@ -195,193 +196,12 @@ static struct __attribute__((packed)) int cur_track; uint32_t error_condition; int is_compressed; + int id_found; uint8_t original_file_name[2048]; uint8_t *filebuf; uint8_t *outbuf; -} d86f[2]; - -#ifdef OLD_COMPRESS -/* Compress from file source to file dest until EOF on source. - def() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_STREAM_ERROR if an invalid compression - level is supplied, Z_VERSION_ERROR if the version of zlib.h and the - version of the library linked do not match, or Z_ERRNO if there is - an error reading or writing the files. */ -int def(FILE *source, FILE *dest, int level) -{ - int ret, flush; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate deflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - ret = deflateInit(&strm, level); - if (ret != Z_OK) - return ret; - - /* compress until end of file */ - do { - strm.avail_in = fread(in, 1, CHUNK, source); - if (ferror(source)) { - (void)deflateEnd(&strm); - return Z_ERRNO; - } - flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; - strm.next_in = in; - - /* run deflate() on input until output buffer not full, finish - compression if all of source has been read in */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = deflate(&strm, flush); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) { - (void)deflateEnd(&strm); - return Z_ERRNO; - } - } while (strm.avail_out == 0); - assert(strm.avail_in == 0); /* all input will be used */ - - /* done when last data in file processed */ - } while (flush != Z_FINISH); - assert(ret == Z_STREAM_END); /* stream will be complete */ - - /* clean up and return */ - (void)deflateEnd(&strm); - return Z_OK; -} - -/* Decompress from file source to file dest until stream ends or EOF. - inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_DATA_ERROR if the deflate data is - invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and - the version of the library linked do not match, or Z_ERRNO if there - is an error reading or writing the files. */ -int inf(FILE *source, FILE *dest) -{ - int ret; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate inflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; - - /* decompress until deflate stream ends or end of file */ - do { - strm.avail_in = fread(in, 1, CHUNK, source); - if (ferror(source)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - if (strm.avail_in == 0) - break; - strm.next_in = in; - - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - return ret; - } - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - } while (strm.avail_out == 0); - - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END); - - /* clean up and return */ - (void)inflateEnd(&strm); - return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; -} - -/* compress or decompress */ -int d86f_zlib(FILE *dst, FILE *src, int dir) -{ - int ret; - - /* do compression if no arguments */ - if (!dir) { - ret = def(src, dst, Z_DEFAULT_COMPRESSION); - if (ret != Z_OK) - return 0; - return 1; - } - - /* do decompression if -d specified */ - else if (dir) { - ret = inf(src, dst); - if (ret != Z_OK) - return 0; - return 1; - } -} -#endif - -#ifdef OLD_CRC -void d86f_generate_table64() -{ - for(int i=0; i<256; ++i) - { - uint64_t crc = i; - - for(unsigned int j=0; j<8; ++j) - { - // is current coefficient set? - if(crc & 1) - { - // yes, then assume it gets zero'd (by implied x^64 coefficient of dividend) - crc >>= 1; - - // and add rest of the divisor - crc ^= poly; - } - else - { - // no? then move to next coefficient - crc >>= 1; - } - } - - table[i] = crc; - } -} - -void d86f_calccrc64(uint8_t b, uint64_t *crc) -{ - uint8_t index = b ^ *crc; - uint64_t lookup = table[index]; - - *crc >>= 8; - *crc ^= lookup; -} -#endif + uint32_t dma_over; +} d86f[FDD_NUM]; static void d86f_setupcrc(uint16_t poly) { @@ -841,13 +661,66 @@ int d86f_format_conditions(int drive) return d86f_valid_bit_rate(drive); } +int d86f_wrong_densel(int drive) +{ + int is_3mode = 0; + + if ((fdd_get_flags(drive) & 7) == 3) + { + is_3mode = 1; + } + + switch (d86f_hole(drive)) + { + case 0: + default: + if (fdd_get_densel(drive)) + { + return 1; + } + else + { + return 0; + } + break; + case 1: + if (fdd_get_densel(drive)) + { + return 0; + } + else + { + if (is_3mode) + { + return 0; + } + else + { + return 1; + } + } + break; + case 2: + if (fdd_get_densel(drive)) + { + return 0; + } + else + { + return 1; + } + break; + } +} + int d86f_can_format(int drive) { int temp; temp = !writeprot[drive]; temp = temp && !swwp; - temp = temp && fdd_can_read_medium(drive ^ fdd_swap); + temp = temp && fdd_can_read_medium(real_drive(drive)); temp = temp && d86f_handler[drive].format_conditions(drive); /* Allows proxied formats to add their own extra conditions to formatting. */ + temp = temp && !d86f_wrong_densel(drive); return temp; } @@ -924,7 +797,7 @@ static int d86f_get_bitcell_period(int drive) if (!mfm) rate /= 2.0; size = (size * 250.0) / rate; size = (size * 300.0) / rpm; - size = (size * fdd_getrpm(drive ^ fdd_swap)) / 300.0; + size = (size * fdd_getrpm(real_drive(drive))) / 300.0; return (int) size; } @@ -932,7 +805,7 @@ int d86f_can_read_address(int drive) { int temp = 0; temp = (fdc_get_bitcell_period() == d86f_get_bitcell_period(drive)); - temp = temp && fdd_can_read_medium(drive ^ fdd_swap); + temp = temp && fdd_can_read_medium(real_drive(drive)); temp = temp && (fdc_is_mfm() == d86f_is_mfm(drive)); temp = temp && (d86f_get_encoding(drive) <= 1); return temp; @@ -1270,6 +1143,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ else { /* Not skip mode, process the sector anyway. */ + // pclog("Wrong AM found (%04X) (%02X)\n", other_am, d86f[drive].state); fdc_set_wrong_am(); d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; d86f[drive].state++; @@ -1345,7 +1219,7 @@ void d86f_read_sector_id(int drive, int side, int match) if (d86f[drive].calc_crc.word != d86f[drive].track_crc.word) { d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; - // printf("%04X != %04X (%08X)\n", d86f[drive].track_crc.word, d86f[drive].calc_crc.word, d86f[drive].last_sector.dword); + printf("ID CRC error: %04X != %04X (%08X)\n", d86f[drive].track_crc.word, d86f[drive].calc_crc.word, d86f[drive].last_sector.dword); if ((d86f[drive].state != STATE_02_READ_ID) && (d86f[drive].state != STATE_0A_READ_ID)) { d86f[drive].error_condition = 0; @@ -1373,8 +1247,9 @@ void d86f_read_sector_id(int drive, int side, int match) else { /* CRC is valid. */ - // pclog("Sector ID found: %08X\n", last_sector.dword); + // pclog("Sector ID found: %08X; Requested: %08X\n", d86f[drive].last_sector.dword, d86f[drive].req_sector.dword); d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; + d86f[drive].id_found++; if ((d86f[drive].last_sector.dword == d86f[drive].req_sector.dword) || !match) { // pclog("ID read (%02X)\n", d86f[drive].state); @@ -1395,6 +1270,20 @@ void d86f_read_sector_id(int drive, int side, int match) } else { + if (d86f[drive].last_sector.id.c != d86f[drive].req_sector.id.c) + { + if (d86f[drive].last_sector.id.c == 0xFF) + { + // pclog("[State: %02X] [Side %i] Bad cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + d86f[drive].error_condition |= 8; + } + else + { + // pclog("[State: %02X] [Side %i] Wrong cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + d86f[drive].error_condition |= 0x10; + } + } + d86f[drive].state--; } } @@ -1414,9 +1303,17 @@ uint8_t d86f_get_data(int drive, int base) if (d86f[drive].data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) { data = fdc_getdata(d86f[drive].data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); - if (data == -1) + if ((data & DMA_OVER) || (data == -1)) { - data = 0; + d86f[drive].dma_over++; + if (data == -1) + { + data = 0; + } + else + { + data &= 0xff; + } } } else @@ -1457,6 +1354,7 @@ void d86f_read_sector_data(int drive, int side) { int data = 0; int recv_data = 0; + int read_status = 0; uint16_t temp; uint32_t sector_len = d86f[drive].last_sector.id.n; uint32_t crc_pos = 0; @@ -1483,7 +1381,12 @@ void d86f_read_sector_data(int drive, int side) { if (d86f[drive].state != STATE_16_VERIFY_DATA) { - fdc_data(data); + read_status = fdc_data(data); + if (read_status == -1) + { + d86f[drive].dma_over++; + // pclog("DMA over now: %i\n", d86f[drive].dma_over); + } } } } @@ -1498,9 +1401,28 @@ void d86f_read_sector_data(int drive, int side) if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap())) { /* We've got the data. */ + if (d86f[drive].dma_over > 1) + { + // pclog("DMA overrun while reading data!\n"); + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + d86f[drive].state = STATE_IDLE; + fdc_finishread(); + fdc_overrun(); + + d86f_get_bit(drive, side); + + d86f[drive].data_find.bits_obtained++; + return; + } + else + { + // pclog("Bytes over DMA: %i\n", d86f[drive].dma_over); + } + if ((d86f[drive].calc_crc.word != d86f[drive].track_crc.word) && (d86f[drive].state != STATE_02_READ_DATA)) { - // printf("%04X != %04X (%08X)\n", d86f[drive].track_crc.word, d86f[drive].calc_crc.word, d86f[drive].last_sector.dword); + printf("Data CRC error: %04X != %04X (%08X)\n", d86f[drive].track_crc.word, d86f[drive].calc_crc.word, d86f[drive].last_sector.dword); d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].error_condition = 0; d86f[drive].state = STATE_IDLE; @@ -1650,6 +1572,19 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap())) { + if (d86f[drive].dma_over > 1) + { + // pclog("DMA overrun while writing data!\n"); + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + d86f[drive].state = STATE_IDLE; + fdc_finishread(); + fdc_overrun(); + + d86f[drive].data_find.bits_obtained++; + return; + } + /* We've written the data. */ d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].error_condition = 0; @@ -1669,15 +1604,24 @@ void d86f_advance_bit(int drive, int side) d86f[drive].track_pos++; d86f[drive].track_pos %= d86f_handler[drive].get_raw_size(drive, side); - if (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) d86f_handler[drive].read_revolution(drive); + if (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) + { + d86f_handler[drive].read_revolution(drive); - if ((d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) && (d86f[drive].state != STATE_IDLE)) d86f[drive].index_count++; + if (d86f[drive].state != STATE_IDLE) + { + d86f[drive].index_count++; + // pclog("Index count now: %i\n", d86f[drive].index_count); + } + } } void d86f_advance_word(int drive, int side) { d86f[drive].track_pos += 16; d86f[drive].track_pos %= d86f_handler[drive].get_raw_size(drive, side); + + if ((d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) && (d86f[drive].state != STATE_IDLE)) d86f[drive].index_count++; } void d86f_spin_to_index(int drive, int side) @@ -1765,6 +1709,24 @@ uint16_t endian_swap(uint16_t word) return temp; } +void d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_fill, int do_write) +{ + if (mfm && do_write) + { + if (do_write && (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side))) + { + d86f_write_direct_common(drive, side, gap_fill, 0, 0); + } + } + + d86f[drive].state = STATE_IDLE; + d86f_handler[drive].writeback(drive); + // pclog("Format finished (%i) (%i)!\n", d86f[drive].track_pos, sc); + d86f[drive].error_condition = 0; + d86f[drive].datac = 0; + fdc_sector_finishread(); +} + void d86f_format_track(int drive, int side) { int data; @@ -1791,7 +1753,7 @@ void d86f_format_track(int drive, int side) am_len = mfm ? 4 : 1; gap_sizes[0] = mfm ? 80 : 40; gap_sizes[1] = mfm ? 50 : 26; - gap_sizes[2] = fdc_get_gap2(drive ^ fdd_swap); + gap_sizes[2] = fdc_get_gap2(real_drive(drive)); gap_sizes[3] = fdc_get_gap(); sync_len = mfm ? 12 : 6; sc = fdc_get_format_sectors(); @@ -1813,6 +1775,10 @@ void d86f_format_track(int drive, int side) if (d86f[drive].datac <= 3) { data = fdc_getdata(0); + if (data != -1) + { + data &= 0xff; + } if ((data == -1) && (d86f[drive].datac < 3)) { data = 0; @@ -1822,7 +1788,7 @@ void d86f_format_track(int drive, int side) if (d86f[drive].datac == 3) { fdc_stop_id_request(); - // pclog("Formatting sector: %08X...\n", d86f[drive].format_sector_id.dword); + // pclog("Formatting sector: %08X (%i) (%i)...\n", d86f[drive].format_sector_id.dword, d86f[drive].track_pos, sc); } } case FMT_PRETRK_SYNC: @@ -1913,20 +1879,10 @@ void d86f_format_track(int drive, int side) d86f_advance_word(drive, side); - if (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) + if ((d86f[drive].index_count) && (d86f[drive].format_state < FMT_SECTOR_ID_SYNC) || (d86f[drive].format_state > FMT_SECTOR_GAP3)) { - /* Before we return, if the encoding is MFM, we have to make sure the clock bit of the first bit in the track is correct. */ - if (mfm && do_write) - { - if (do_write) d86f_write_direct_common(drive, side, gap_fill, 0, 0); - } - - d86f[drive].state = STATE_IDLE; - d86f_handler[drive].writeback(drive); - // pclog("Format finished!\n"); - d86f[drive].error_condition = 0; - d86f[drive].datac = 0; - fdc_sector_finishread(); + // pclog("Format finished regularly\n"); + d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); return; } @@ -1945,6 +1901,12 @@ void d86f_format_track(int drive, int side) d86f[drive].calc_crc.word = 0xffff; break; case FMT_POSTTRK_CHECK: + if (d86f[drive].index_count) + { + // pclog("Format finished with delay\n"); + d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); + return; + } d86f[drive].sector_count++; if (d86f[drive].sector_count < sc) { @@ -1983,16 +1945,19 @@ void d86f_poll(int drive) { if (!d86f_can_read_address(drive)) { - /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) pclog("Bitcell period mismatch\n"); - if (!fdd_can_read_medium(drive ^ fdd_swap)) pclog("Drive can not read medium (hole = %01X)\n", d86f_hole(drive)); - if (fdc_is_mfm() != d86f_is_mfm(drive)) pclog("Encoding mismatch\n"); - if (d86f_get_encoding(drive) > 1) pclog("Image encoding (%s) not FM or MFM\n", (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ + /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) pclog("[%i, %i] Bitcell period mismatch (%i != %i)\n", drive, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive)); + if (!fdd_can_read_medium(real_drive(drive))) pclog("[%i, %i] Drive can not read medium (hole = %01X)\n", drive, side, d86f_hole(drive)); + if (fdc_is_mfm() != d86f_is_mfm(drive)) pclog("[%i, %i] Encoding mismatch\n", drive, side); + if (d86f_get_encoding(drive) > 1) pclog("[%i, %i] Image encoding (%s) not FM or MFM\n", drive, side, (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ d86f[drive].state = STATE_SECTOR_NOT_FOUND; } } - d86f_get_bit(drive, side ^ 1); + if ((d86f[drive].state != STATE_02_SPIN_TO_INDEX) && (d86f[drive].state != STATE_0D_SPIN_TO_INDEX)) + { + d86f_get_bit(drive, side ^ 1); + } switch(d86f[drive].state) { @@ -2114,11 +2079,77 @@ void d86f_poll(int drive) d86f_advance_bit(drive, side); + if (d86f_wrong_densel(drive) && (d86f[drive].state != STATE_IDLE)) + { + // pclog("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + d86f[drive].state = STATE_IDLE; + fdc_noidam(); + return; + } + if ((d86f[drive].index_count == 2) && (d86f[drive].state != STATE_IDLE)) { - // pclog("[State: %02X] [Side %i] Sector not found (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); - d86f[drive].state = STATE_IDLE; - fdc_notfound(); + switch(d86f[drive].state) + { + case STATE_0A_FIND_ID: + case STATE_SECTOR_NOT_FOUND: + // pclog("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + d86f[drive].state = STATE_IDLE; + fdc_noidam(); + break; + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + // pclog("[State: %02X] [Side %i] No data address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + d86f[drive].state = STATE_IDLE; + fdc_nodataam(); + break; + case STATE_02_SPIN_TO_INDEX: + case STATE_02_READ_DATA: + case STATE_05_WRITE_DATA: + case STATE_06_READ_DATA: + case STATE_09_WRITE_DATA: + case STATE_0C_READ_DATA: + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_FORMAT_TRACK: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + /* In these states, we should *NEVER* care about how many index pulses there have been. */ + break; + default: + d86f[drive].state = STATE_IDLE; + if (d86f[drive].id_found) + { + if (d86f[drive].error_condition & 0x18) + { + if ((d86f[drive].error_condition & 0x18) == 0x08) + { + // pclog("[State: %02X] [Side %i] Bad cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + fdc_badcylinder(); + } + if ((d86f[drive].error_condition & 0x10) == 0x10) + { + // pclog("[State: %02X] [Side %i] Wrong cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + fdc_wrongcylinder(); + } + } + else + { + // pclog("[State: %02X] [Side %i] Sector not found (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + fdc_nosector(); + } + } + else + { + // pclog("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + fdc_noidam(); + } + break; + } } } @@ -2628,7 +2659,7 @@ void d86f_writeback(int drive) { logical_track = d86f[drive].cur_track + thin_track; } - if (d86f[drive].track_offset[((d86f[drive].cur_track + thin_track) << 1) + side]) + if (d86f[drive].track_offset[logical_track]) { fseek(d86f[drive].f, d86f[drive].track_offset[logical_track], SEEK_SET); d86f_write_track(drive, side, d86f[drive].thin_track_encoded_data[thin_track][side], d86f[drive].thin_track_surface_data[thin_track][side]); @@ -2648,7 +2679,7 @@ void d86f_writeback(int drive) { logical_track = d86f[drive].cur_track; } - if (d86f[drive].track_offset[(d86f[drive].cur_track << 1) + side]) + if (d86f[drive].track_offset[logical_track]) { // pclog("Writing track...\n"); fseek(d86f[drive].f, d86f[drive].track_offset[logical_track], SEEK_SET); @@ -2751,16 +2782,28 @@ void d86f_stop(int drive) int d86f_common_command(int drive, int sector, int track, int side, int rate, int sector_size) { - // pclog("d86f_common_command: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, sector, track, side); + // pclog("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, sector, track, side); d86f[drive].req_sector.id.c = track; d86f[drive].req_sector.id.h = side; - d86f[drive].req_sector.id.r = sector; + if (sector == SECTOR_FIRST) + { + d86f[drive].req_sector.id.r = 1; + } + else if (sector == SECTOR_NEXT) + { + d86f[drive].req_sector.id.r++; + } + else + { + d86f[drive].req_sector.id.r = sector; + } d86f[drive].req_sector.id.n = sector_size; if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - fdc_notfound(); + // pclog("Wrong side!\n"); + fdc_noidam(); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return 0; @@ -2769,6 +2812,8 @@ int d86f_common_command(int drive, int sector, int track, int side, int rate, in d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].index_count = d86f[drive].error_condition = d86f[drive].satisfying_bytes = 0; + d86f[drive].id_found = 0; + d86f[drive].dma_over = 0; return 1; } @@ -2818,10 +2863,12 @@ void d86f_comparesector(int drive, int sector, int track, int side, int rate, in void d86f_readaddress(int drive, int track, int side, int rate) { + // pclog("Reading sector ID on drive %i...\n", drive); + if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - pclog("Trying to access the second side of a single-sided disk\n"); - fdc_notfound(); + // pclog("Trying to access the second side of a single-sided disk\n"); + fdc_noidam(); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -2830,6 +2877,8 @@ void d86f_readaddress(int drive, int track, int side, int rate) d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].index_count = d86f[drive].error_condition = d86f[drive].satisfying_bytes = 0; + d86f[drive].id_found = 0; + d86f[drive].dma_over = 0; d86f[drive].state = STATE_0A_FIND_ID; } @@ -2888,7 +2937,7 @@ void d86f_common_format(int drive, int track, int side, int rate, uint8_t fill, if ((side && (d86f_get_sides(drive) == 1)) || !(d86f_can_format(drive))) { - fdc_notfound(); + fdc_cannotformat(); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -2938,7 +2987,7 @@ void d86f_common_format(int drive, int track, int side, int rate, uint8_t fill, { // d86f[drive].side_flags[side] &= 0xc0; d86f[drive].side_flags[side] = 0; - d86f[drive].side_flags[side] |= (fdd_getrpm(drive ^ fdd_swap) == 360) ? 0x20 : 0; + d86f[drive].side_flags[side] |= (fdd_getrpm(real_drive(drive)) == 360) ? 0x20 : 0; d86f[drive].side_flags[side] |= fdc_get_bit_rate(); d86f[drive].side_flags[side] |= fdc_is_mfm() ? 8 : 0; @@ -2948,6 +2997,7 @@ void d86f_common_format(int drive, int track, int side, int rate, uint8_t fill, d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].index_count = d86f[drive].error_condition = d86f[drive].satisfying_bytes = d86f[drive].sector_count = 0; + d86f[drive].dma_over = 0; d86f[drive].state = STATE_0D_SPIN_TO_INDEX; } diff --git a/src/disc_86f.h b/src/disc_86f.h index 873110d6b..47a71f8f3 100644 --- a/src/disc_86f.h +++ b/src/disc_86f.h @@ -38,7 +38,9 @@ void d86f_prepare_track_layout(int drive, int side); #define pre_data length_sync + length_am #define post_gap length_crc +#if 0 extern int raw_tsize[2]; extern int gap2_size[2]; extern int gap3_size[2]; extern int gap4_size[2]; +#endif diff --git a/src/disc_fdi.c b/src/disc_fdi.c index 1f9be5950..a016d4462 100644 --- a/src/disc_fdi.c +++ b/src/disc_fdi.c @@ -24,7 +24,7 @@ static struct int trackindex[2][4]; int lasttrack; -} fdi[2]; +} fdi[FDD_NUM]; uint16_t fdi_disk_flags(int drive) { @@ -117,24 +117,28 @@ int32_t fdi_extra_bit_cells(int drive, int side) int raw_size = 0; + int is_300_rpm = 0; + density = fdi_density(); + is_300_rpm = (fdd_getrpm(real_drive(drive)) == 300); + switch (fdc_get_bit_rate()) { case 0: - raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 200000 : 166666; + raw_size = is_300_rpm ? 200000 : 166666; break; case 1: - raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 120000 : 100000; + raw_size = is_300_rpm ? 120000 : 100000; break; case 2: - raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 100000 : 83333; + raw_size = is_300_rpm ? 100000 : 83333; case 3: case 5: - raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 400000 : 333333; + raw_size = is_300_rpm ? 400000 : 333333; break; default: - raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 100000 : 83333; + raw_size = is_300_rpm ? 100000 : 83333; } return (fdi[drive].tracklen[side][density] - raw_size); diff --git a/src/disc_imd.c b/src/disc_imd.c index 1aa587b6d..f5db814f6 100644 --- a/src/disc_imd.c +++ b/src/disc_imd.c @@ -40,7 +40,7 @@ static struct uint8_t interleave_ordered_pos[256][2]; uint8_t *current_data[2]; uint8_t track_buffer[2][25000]; -} imd[2]; +} imd[FDD_NUM]; void imd_init() { diff --git a/src/disc_img.c b/src/disc_img.c index 0fe016fcd..fa8641611 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -27,7 +27,7 @@ static struct uint16_t sector_pos[2][256]; uint8_t current_sector_pos_side; uint16_t current_sector_pos; -} img[2]; +} img[FDD_NUM]; uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 }; static uint8_t xdf_spt[2] = { 6, 8 }; @@ -193,6 +193,32 @@ void img_init() void d86f_register_img(int drive); +int bps_is_valid(uint16_t bps) +{ + int i; + for (i = 0; i <= 8; i++) + { + if (bps == (128 << i)) + { + return 1; + } + } + return 0; +} + +int first_byte_is_valid(uint8_t first_byte) +{ + switch(first_byte) + { + case 0x60: + case 0xE9: + case 0xEB: + return 1; + default: + return 0; + } +} + void img_load(int drive, char *fn) { int size; @@ -208,6 +234,7 @@ void img_load(int drive, char *fn) char ext[4]; int fdi; int i; + uint8_t first_byte; ext[0] = fn[strlen(fn) - 3] | 0x60; ext[1] = fn[strlen(fn) - 2] | 0x60; @@ -256,6 +283,8 @@ void img_load(int drive, char *fn) { /* Read the BPB */ pclog("img_load(): File is a raw image...\n"); + fseek(img[drive].f, 0x00, SEEK_SET); + first_byte = fgetc(img[drive].f); fseek(img[drive].f, 0x0B, SEEK_SET); fread(&bpb_bps, 1, 2, img[drive].f); fseek(img[drive].f, 0x13, SEEK_SET); @@ -281,7 +310,7 @@ void img_load(int drive, char *fn) pclog("BPB reports %i sides and %i bytes per sector\n", bpb_sides, bpb_bps); - if (((bpb_sides < 1) || (bpb_sides > 2) || (bpb_bps < 128) || (bpb_bps > 2048)) && !fdi) + if (((bpb_sides < 1) || (bpb_sides > 2) || !bps_is_valid(bpb_bps) || !first_byte_is_valid(first_byte)) && !fdi) { /* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably not a BPB at all, so we have to guess the parameters from file size. */ diff --git a/src/disc_td0.c b/src/disc_td0.c index d622c4c16..9e21a9b11 100644 --- a/src/disc_td0.c +++ b/src/disc_td0.c @@ -107,7 +107,7 @@ typedef struct uint8_t interleave_ordered_pos[256][2]; } td0_t; -td0_t td0[2]; +td0_t td0[FDD_NUM]; void floppy_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) diff --git a/src/dma.c b/src/dma.c index d262cf50d..870d35d1f 100644 --- a/src/dma.c +++ b/src/dma.c @@ -86,7 +86,7 @@ void dma_write(uint16_t addr, uint8_t val, void *priv) dma.wp ^= 1; if (dma.wp) dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0xff00) | val; else dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0x00ff) | (val << 8); - dma.ac[(addr >> 1) & 3] = dma.ab[(addr >> 1) & 3]; + dma.ac[(addr >> 1) & 3] = dma.ab[(addr >> 1) & 3] & 0xffff; dmaon[(addr >> 1) & 3] = 1; return; @@ -94,7 +94,8 @@ void dma_write(uint16_t addr, uint8_t val, void *priv) dma.wp ^= 1; if (dma.wp) dma.cb[(addr >> 1) & 3] = (dma.cb[(addr >> 1) & 3] & 0xff00) | val; else dma.cb[(addr >> 1) & 3] = (dma.cb[(addr >> 1) & 3] & 0x00ff) | (val << 8); - dma.cc[(addr >> 1) & 3] = dma.cb[(addr >> 1) & 3]; + dma.cc[(addr >> 1) & 3] = dma.cb[(addr >> 1) & 3] & 0xffff; + // pclog("DMA count for channel %i now: %02X\n", (addr >> 1) & 3, dma.cc[(addr >> 1) & 3]); dmaon[(addr >> 1) & 3] = 1; return; @@ -169,7 +170,7 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv) dma16.wp ^= 1; if (dma16.wp) dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xff00) | val; else dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0x00ff) | (val << 8); - dma16.ac[(addr >> 1) & 3] = dma16.ab[(addr >> 1) & 3]; + dma16.ac[(addr >> 1) & 3] = dma16.ab[(addr >> 1) & 3] & 0xffff; dma16on[(addr >> 1) & 3] = 1; return; @@ -177,7 +178,7 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv) dma16.wp ^= 1; if (dma16.wp) dma16.cb[(addr >> 1) & 3] = (dma16.cb[(addr >> 1) & 3] & 0xff00) | val; else dma16.cb[(addr >> 1) & 3] = (dma16.cb[(addr >> 1) & 3] & 0x00ff) | (val << 8); - dma16.cc[(addr >> 1) & 3] = dma16.cb[(addr >> 1) & 3]; + dma16.cc[(addr >> 1) & 3] = dma16.cb[(addr >> 1) & 3] & 0xffff; dma16on[(addr >> 1) & 3] = 1; return; @@ -263,6 +264,24 @@ void dma16_init() io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); } +void dma_alias_set() +{ + io_sethandler(0x0090, 0x0010, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); +} + +void dma_alias_remove() +{ + io_removehandler(0x0090, 0x0010, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); +} + +void dma_alias_remove_piix() +{ + io_removehandler(0x0090, 0x0001, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); + io_removehandler(0x0094, 0x0003, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); + io_removehandler(0x0098, 0x0001, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); + io_removehandler(0x009C, 0x0003, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); +} + uint8_t _dma_read(uint32_t addr) { @@ -286,184 +305,309 @@ void _dma_writew(uint32_t addr, uint16_t val) mem_invalidate_range(addr, addr + 1); } +int dma_is_masked(int channel) +{ + if (channel < 4) + { + if (dma.m & (1 << channel)) + { + return 1; + } + if (AT) + { + if (dma16.m & 1) + { + return 1; + } + } + } + else + { + channel &= 3; + if (dma16.m & (1 << channel)) + { + return 1; + } + } + return 0; +} + +int dma_channel_mode(int channel) +{ + if (channel < 4) + { + return (dma.mode[channel] & 0xC) >> 2; + } + else + { + channel &= 3; + return (dma16.mode[channel] & 0xC) >> 2; + } +} + +DMA * get_dma_controller(int channel) +{ + if (channel < 4) + { + return &dma; + } + else + { + return &dma16; + } +} + int dma_channel_read(int channel) { uint16_t temp; int tc = 0; - - if (dma.command & 0x04) + + int cmode = 0; + int real_channel = channel & 3; + + int mem_over = 0; + + DMA *dma_controller; + + cmode = dma_channel_mode(channel); + + channel &= 7; + + if ((channel >= 4) && !AT) + { + // pclog ("DMA read - channel is 4 or higher on a non-AT machine\n"); return DMA_NODATA; - + } + + dma_controller = get_dma_controller(channel); + + if (dma_controller->command & 0x04) + { + // pclog ("DMA read - channel bit 2 of control bit is set\n"); + return DMA_NODATA; + } + if (!AT) refreshread(); - - if (channel < 4) - { - if (dma.m & (1 << channel)) - return DMA_NODATA; - if ((dma.mode[channel] & 0xC) != 8) - return DMA_NODATA; - temp = _dma_read(dma.ac[channel] + (dma.page[channel] << 16)); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]; - - if (dma.mode[channel] & 0x20) dma.ac[channel]--; - else dma.ac[channel]++; - dma.cc[channel]--; - if (dma.cc[channel] < 0) - { - tc = 1; - if (dma.mode[channel] & 0x10) /*Auto-init*/ - { - dma.cc[channel] = dma.cb[channel]; - dma.ac[channel] = dma.ab[channel]; - } - else - dma.m |= (1 << channel); - dma.stat |= (1 << channel); - } - - if (tc) - return temp | DMA_OVER; - return temp; - } - else - { - channel &= 3; - if ((dma16.m & (1 << channel)) || (dma16.m & 1)) - return DMA_NODATA; - if ((dma16.mode[channel] & 0xC) != 8) - return DMA_NODATA; - -#if 0 - temp = _dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)) | - (_dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1) << 8); -#endif - - temp = _dma_readw((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)); - - if (dma16.mode[channel] & 0x20) dma16.ac[channel]--; - else dma16.ac[channel]++; - dma16.cc[channel]--; - if (dma16.cc[channel] < 0) - { - tc = 1; - if (dma16.mode[channel] & 0x10) /*Auto-init*/ - { - dma16.cc[channel] = dma16.cb[channel]; - dma16.ac[channel] = dma16.ab[channel]; - } - else - { - dma16.m |= (1 << channel); - if (!channel) - { - dma16.m |= 0xf; - } - } - dma16.stat |= (1 << channel); - } - - if (tc) - return temp | DMA_OVER; - return temp; - } -} - -void dma_channel_dump() -{ - int i = 0; - FILE *f; - f = fopen("dma.dmp", "wb"); - for (i = 0; i < (21 * 512); i++) + if ((channel == 4) || dma_is_masked(channel)) { - fputc(mem_readb_phys((dma.page[2] << 16) + dma16.ac[2] + i), f); + // pclog ("DMA read - channel is 4 or masked\n"); + return DMA_NODATA; } - fclose(f); + + if (cmode) + { + if (cmode != 2) + { + // pclog ("DMA read - transfer mode (%i) is 1 or 3\n", cmode); + return DMA_NODATA; + } + else + { + if (channel < 4) + { + temp = _dma_read(dma_controller->ac[real_channel] + (dma_controller->page[real_channel] << 16)); + } + else + { + temp = _dma_readw((dma_controller->ac[real_channel] << 1) + ((dma_controller->page[real_channel] & ~1) << 16)); + } + } + } + + if (dma_controller->mode[real_channel] & 0x20) + { + if (dma_controller->ac[real_channel] == 0) + { + mem_over = 1; + } + dma_controller->ac[real_channel]--; + } + else + { + if (dma_controller->ac[real_channel] == 0xFFFF) + { + mem_over = 1; + } + dma_controller->ac[real_channel]++; + } + dma_controller->ac[real_channel] &= 0xffff; + + dma_controller->cc[real_channel]--; + if ((dma_controller->cc[real_channel] < 0) || mem_over) + { + tc = 1; + if (dma_controller->mode[real_channel] & 0x10) /*Auto-init*/ + { + // pclog("DMA read auto-init\n"); + dma_controller->cc[real_channel] = dma_controller->cb[real_channel] & 0xffff; + dma_controller->ac[real_channel] = dma_controller->ab[real_channel] & 0xffff; + } + else + { + dma_controller->cc[real_channel] &= 0xffff; + dma_controller->m |= (1 << real_channel); + } + dma_controller->stat |= (1 << real_channel); + } + + if (tc) + { + // pclog("DMA read over in transfer mode %i (value %04X)!\n", cmode, temp); + return temp | DMA_OVER; + } + + // pclog("DMA read success (value %04X)\n", temp); + return temp; } int dma_channel_write(int channel, uint16_t val) { - if (dma.command & 0x04) + int tc = 0; + + int cmode = 0; + int real_channel = channel & 3; + + int mem_over = 0; + + DMA *dma_controller; + + cmode = dma_channel_mode(channel); + + channel &= 7; + + if ((channel >= 4) && !AT) + { + // pclog ("DMA write - channel is 4 or higher on a non-AT machine\n"); return DMA_NODATA; + } + + dma_controller = get_dma_controller(channel); + + if (dma_controller->command & 0x04) + { + // pclog ("DMA write - channel bit 2 of control bit is set\n"); + return DMA_NODATA; + } if (!AT) refreshread(); - if (channel < 4) - { - if (dma.m & (1 << channel)) - return DMA_NODATA; - if ((dma.mode[channel] & 0xC) != 4) + if ((channel == 4) || dma_is_masked(channel)) + { + // pclog ("DMA write - channel is 4 or masked\n"); + return DMA_NODATA; + } + + if (cmode) + { + if (cmode != 1) + { + // pclog ("DMA write - transfer mode (%i) is 2 or 3\n", cmode); return DMA_NODATA; + } - _dma_write(dma.ac[channel] + (dma.page[channel] << 16), val); + if (channel < 4) + { + _dma_write(dma_controller->ac[real_channel] + (dma_controller->page[real_channel] << 16), val); + } + else + { + _dma_writew((dma_controller->ac[real_channel] << 1) + ((dma_controller->page[real_channel] & ~1) << 16), val); + } + } - if (dma.mode[channel]&0x20) dma.ac[channel]--; - else dma.ac[channel]++; - dma.cc[channel]--; - if (dma.cc[channel] < 0) - { - if (dma.mode[channel] & 0x10) /*Auto-init*/ - { - dma.cc[channel] = dma.cb[channel]; - dma.ac[channel] = dma.ab[channel]; - } - else - dma.m |= (1 << channel); - dma.stat |= (1 << channel); - } + if (dma_controller->mode[real_channel] & 0x20) + { + if (dma_controller->ac[real_channel] == 0) + { + mem_over = 1; + } + dma_controller->ac[real_channel]--; + } + else + { + if (dma_controller->ac[real_channel] == 0xFFFF) + { + mem_over = 1; + } + dma_controller->ac[real_channel]++; + } + dma_controller->ac[real_channel] &= 0xffff; - if (dma.m & (1 << channel)) - return DMA_OVER; - } - else - { - channel &= 3; - if ((dma16.m & (1 << channel)) || (dma16.m & 1)) - return DMA_NODATA; - if ((dma16.mode[channel] & 0xC) != 4) - return DMA_NODATA; + dma_controller->cc[real_channel]--; + if ((dma_controller->cc[real_channel] < 0) || mem_over) + { + tc = 1; + if (dma_controller->mode[real_channel] & 0x10) /*Auto-init*/ + { + // pclog("DMA write auto-init\n"); + dma_controller->cc[real_channel] = dma_controller->cb[real_channel] & 0xffff; + dma_controller->ac[real_channel] = dma_controller->ab[real_channel] & 0xffff; + } + else + { + dma_controller->cc[real_channel] &= 0xffff; + dma_controller->m |= (1 << real_channel); + } + dma_controller->stat |= (1 << real_channel); + } -#if 0 - _dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val); - _dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1, val >> 8); -#endif + // if (dma_is_masked(channel)) + if (tc) + { + // pclog("DMA write over in transfer mode %i (value %04X)\n", cmode, val); + return DMA_OVER; + } - _dma_writew((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val); - - if (dma16.mode[channel]&0x20) dma16.ac[channel]--; - else dma16.ac[channel]++; - dma16.cc[channel]--; - if (dma16.cc[channel] < 0) - { - if (dma16.mode[channel] & 0x10) /*Auto-init*/ - { - dma16.cc[channel] = dma16.cb[channel] + 1; - dma16.ac[channel] = dma16.ab[channel]; - } - dma16.m |= (1 << channel); - if (!channel) - { - dma16.m |= 0xf; - } - dma16.stat |= (1 << channel); - } - - if ((dma.m & (1 << channel)) || (dma.m & 1)) - return DMA_OVER; - } - return 0; + // pclog("DMA write success (value %04X)\n", val); + return 0; } -size_t PageLengthReadWrite(uint32_t Address, size_t TotalSize) +static size_t PageLengthReadWrite(uint32_t PhysAddress, size_t TotalSize) { - size_t l; + size_t LengthSize; uint32_t Page; - Page = Address & 4095; - l = (Page + 4096) - Address; - if (l > TotalSize) - l = TotalSize; + Page = PhysAddress & 4095; + LengthSize = (Page + 4096) - PhysAddress; + if (LengthSize > TotalSize) + LengthSize = TotalSize; - return l; + return LengthSize; } + +//DMA Bus Master Page Read/Write +void DMAPageRead(uint32_t PhysAddress, void *DataRead, size_t TotalSize) +{ + uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize); + memcpy(DataRead, &ram[PhysAddress], PageLen); + DataRead -= PageLen; + PageLen -= TotalSize; +} + +void DMAPageWrite(uint32_t PhysAddress, const void *DataWrite, size_t TotalSize) +{ + uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize); + memcpy(&ram[PhysAddress], DataWrite, PageLen); + DataWrite -= PageLen; + PageLen -= TotalSize; +} + +int dma_mode(int channel) +{ + if (channel < 4) + { + return dma.mode[channel]; + } + else + { + return dma16.mode[channel & 3]; + } +} + +/* void dma_c2_mode() +{ + printf("DMA Channel 2 mode: %02X\n", dma.mode[2]); +} */ diff --git a/src/dma.h b/src/dma.h index 3200144e5..14a6ab0ea 100644 --- a/src/dma.h +++ b/src/dma.h @@ -7,6 +7,7 @@ void dma_reset(); #define DMA_NODATA -1 #define DMA_OVER 0x10000 +#define DMA_VERIFY 0x20000 void readdma0(); int readdma1(); @@ -18,4 +19,5 @@ void writedma2(uint8_t temp); int dma_channel_read(int channel); int dma_channel_write(int channel, uint16_t val); -size_t PageLengthReadWrite(uint32_t Address, size_t TotalSize); \ No newline at end of file +void DMAPageRead(uint32_t PhysAddress, void *DataRead, size_t TotalSize); +void DMAPageWrite(uint32_t PhysAddress, const void *DataWrite, size_t TotalSize); \ No newline at end of file diff --git a/src/dosbox/vid_cga_comp.c b/src/dosbox/vid_cga_comp.c index 3a1099617..7752f5ba6 100644 --- a/src/dosbox/vid_cga_comp.c +++ b/src/dosbox/vid_cga_comp.c @@ -1,7 +1,5 @@ -/* Authors: Andrew Jenner - Extra contributors: Tenshi - Distributed as is with the Unlicense (PD), see "UNLICENSE" -*/ +/* Code borrowed from DOSBox and adapted by OBattler. + Original author: reenigne. */ #include #include @@ -69,38 +67,30 @@ static Bit8u byte_clamp_other(int v) { return v < 0 ? 0 : (v > 255 ? 255 : v); } FILE *df; -void update_cga16_color(cga_t *cga) { +void update_cga16_color(uint8_t cgamode) { int x; Bit32u x2; - double i0, i3, mode_saturation, c, i, v, r, g, b, q, a, s, iq_adjust_i, iq_adjust_q; - - static const double ri = 0.9563; - static const double rq = 0.6210; - static const double gi = -0.2721; - static const double gq = -0.6474; - static const double bi = -1.1069; - static const double bq = 1.7046; if (!new_cga) { min_v = chroma_multiplexer[0] + intensity[0]; max_v = chroma_multiplexer[255] + intensity[3]; } else { - i0 = intensity[0]; - i3 = intensity[3]; + double i0 = intensity[0]; + double i3 = intensity[3]; min_v = NEW_CGA(chroma_multiplexer[0], i0, i0, i0, i0); max_v = NEW_CGA(chroma_multiplexer[255], i3, i3, i3, i3); } mode_contrast = 256/(max_v - min_v); mode_brightness = -min_v*mode_contrast; - if ((cga->cgamode & 3) == 1) + if ((cgamode & 3) == 1) mode_hue = 14; else mode_hue = 4; mode_contrast *= contrast * (new_cga ? 1.2 : 1)/100; // new CGA: 120% mode_brightness += (new_cga ? brightness-10 : brightness)*5; // new CGA: -10 - mode_saturation = (new_cga ? 4.35 : 2.9)*saturation/100; // new CGA: 150% + double mode_saturation = (new_cga ? 4.35 : 2.9)*saturation/100; // new CGA: 150% for (x = 0; x < 1024; ++x) { int phase = x & 3; @@ -108,33 +98,42 @@ void update_cga16_color(cga_t *cga) { int left = (x >> 6) & 15; int rc = right; int lc = left; - if ((cga->cgamode & 4) != 0) { + if ((cgamode & 4) != 0) { rc = (right & 8) | ((right & 7) != 0 ? 7 : 0); lc = (left & 8) | ((left & 7) != 0 ? 7 : 0); } - c = chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase]; - i = intensity[(left >> 3) | ((right >> 2) & 2)]; + double c = + chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase]; + double i = intensity[(left >> 3) | ((right >> 2) & 2)]; + double v; if (!new_cga) v = c + i; else { - r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)]; - g = intensity[((left >> 1) & 1) | (right & 2)]; - b = intensity[(left & 1) | ((right << 1) & 2)]; + double r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)]; + double g = intensity[((left >> 1) & 1) | (right & 2)]; + double b = intensity[(left & 1) | ((right << 1) & 2)]; v = NEW_CGA(c, i, r, g, b); } CGA_Composite_Table[x] = (int) (v*mode_contrast + mode_brightness); } - i = CGA_Composite_Table[6*68] - CGA_Composite_Table[6*68 + 2]; - q = CGA_Composite_Table[6*68 + 1] - CGA_Composite_Table[6*68 + 3]; + double i = CGA_Composite_Table[6*68] - CGA_Composite_Table[6*68 + 2]; + double q = CGA_Composite_Table[6*68 + 1] - CGA_Composite_Table[6*68 + 3]; - a = tau*(33 + 90 + hue_offset + mode_hue)/360.0; - c = cos(a); - s = sin(a); - r = 256*mode_saturation/sqrt(i*i+q*q); + double a = tau*(33 + 90 + hue_offset + mode_hue)/360.0; + double c = cos(a); + double s = sin(a); + double r = 256*mode_saturation/sqrt(i*i+q*q); - iq_adjust_i = -(i*c + q*s)*r; - iq_adjust_q = (q*c - i*s)*r; + double iq_adjust_i = -(i*c + q*s)*r; + double iq_adjust_q = (q*c - i*s)*r; + + static const double ri = 0.9563; + static const double rq = 0.6210; + static const double gi = -0.2721; + static const double gq = -0.6474; + static const double bi = -1.1069; + static const double bq = 1.7046; video_ri = (int) (ri*iq_adjust_i + rq*iq_adjust_q); video_rq = (int) (-ri*iq_adjust_q + rq*iq_adjust_i); @@ -157,7 +156,7 @@ static int temp[SCALER_MAXWIDTH + 10]={0}; static int atemp[SCALER_MAXWIDTH + 2]={0}; static int btemp[SCALER_MAXWIDTH + 2]={0}; -Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit8u *TempLine) +Bit8u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit8u *TempLine) { int x; Bit32u x2; @@ -187,8 +186,6 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double int* o = temp; Bit8u* rgbi = TempLine; int* b = &CGA_Composite_Table[border*68]; - int *i, *ap, *bp; - Bit32u* srgb; for (x = 0; x < 4; ++x) OUT(b[(x+3)&3]); OUT(CGA_Composite_Table[(border<<6) | ((*rgbi)<<2) | 3]); @@ -200,10 +197,10 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double for (x = 0; x < 5; ++x) OUT(b[x&3]); - if ((cga->cgamode & 4) != 0) { + if ((cgamode & 4) != 0) { // Decode - i = temp + 5; - srgb = (Bit32u *)TempLine; + int* i = temp + 5; + Bit32u* srgb = (Bit32u *)TempLine; for (x2 = 0; x2 < blocks*4; ++x2) { int c = (i[0]+i[0])<<3; int d = (i[-1]+i[1])<<3; @@ -215,9 +212,9 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double } else { // Store chroma - i = temp + 4; - ap = atemp + 1; - bp = btemp + 1; + int* i = temp + 4; + int* ap = atemp + 1; + int* bp = btemp + 1; for (x = -1; x < w + 1; ++x) { ap[x] = i[-4]-((i[-2]-i[0]+i[2])<<1)+i[4]; bp[x] = (i[-3]-i[-1]+i[1]-i[3])<<1; @@ -228,7 +225,7 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double i = temp + 5; i[-1] = (i[-1]<<3) - ap[-1]; i[0] = (i[0]<<3) - ap[0]; - srgb = (Bit32u *)TempLine; + Bit32u* srgb = (Bit32u *)TempLine; for (x2 = 0; x2 < blocks; ++x2) { int y,a,b,c,d,rr,gg,bb; COMPOSITE_CONVERT(a, b); @@ -243,79 +240,79 @@ Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool double return TempLine; } -void IncreaseHue(cga_t *cga) +void IncreaseHue(uint8_t cgamode) { hue_offset += 5.0; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void DecreaseHue(cga_t *cga) +void DecreaseHue(uint8_t cgamode) { hue_offset -= 5.0; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void IncreaseSaturation(cga_t *cga) +void IncreaseSaturation(uint8_t cgamode) { saturation += 5; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void DecreaseSaturation(cga_t *cga) +void DecreaseSaturation(uint8_t cgamode) { saturation -= 5; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void IncreaseContrast(cga_t *cga) +void IncreaseContrast(uint8_t cgamode) { contrast += 5; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void DecreaseContrast(cga_t *cga) +void DecreaseContrast(uint8_t cgamode) { contrast -= 5; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void IncreaseBrightness(cga_t *cga) +void IncreaseBrightness(uint8_t cgamode) { brightness += 5; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void DecreaseBrightness(cga_t *cga) +void DecreaseBrightness(uint8_t cgamode) { brightness -= 5; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void IncreaseSharpness(cga_t *cga) +void IncreaseSharpness(uint8_t cgamode) { sharpness += 10; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void DecreaseSharpness(cga_t *cga) +void DecreaseSharpness(uint8_t cgamode) { sharpness -= 10; - update_cga16_color(cga); + update_cga16_color(cgamode); } -void cga_comp_init(cga_t *cga) +void cga_comp_init(int revision) { - new_cga = cga->revision; + new_cga = revision; /* Making sure this gets reset after reset. */ brightness = 0; @@ -324,5 +321,5 @@ void cga_comp_init(cga_t *cga) sharpness = 0; hue_offset = 0; - update_cga16_color(cga); + update_cga16_color(0); } diff --git a/src/dosbox/vid_cga_comp.h b/src/dosbox/vid_cga_comp.h index 5685672d3..4640efd8f 100644 --- a/src/dosbox/vid_cga_comp.h +++ b/src/dosbox/vid_cga_comp.h @@ -1,12 +1,8 @@ -/* Authors: Andrew Jenner - Extra contributors: Tenshi - Distributed as is with the Unlicense (PD), see "UNLICENSE" -*/ #define Bit8u uint8_t #define Bit32u uint32_t #define Bitu unsigned int #define bool uint8_t -void update_cga16_color(cga_t *cga); -void cga_comp_init(cga_t *cga); -Bit8u * Composite_Process(cga_t *cga, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit8u *TempLine); +void update_cga16_color(uint8_t cgamode); +void cga_comp_init(int revision); +Bit8u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit8u *TempLine); diff --git a/src/fdc.c b/src/fdc.c index 751dcd380..5c9cebec3 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -13,9 +13,9 @@ #include "pic.h" #include "timer.h" -extern int motoron[2]; +extern int motoron[FDD_NUM]; -int ui_writeprot[2] = {0, 0}; +int ui_writeprot[FDD_NUM] = {0, 0, 0, 0}; int command_has_drivesel[256] = { [0x02] = 1, /* READ TRACK */ [0x04] = 1, /* SENSE DRIVE STATUS */ @@ -72,11 +72,11 @@ typedef struct FDC int is_nsc; /* 1 = FDC is on a National Semiconductor Super I/O chip, 0 = other FDC. This is needed, because the National Semiconductor Super I/O chips add some FDC commands. */ int enh_mode; - int rwc[2]; + int rwc[4]; int boot_drive; int densel_polarity; int densel_force; - int drvrate[2]; + int drvrate[4]; int dma; int fifo, tfifo; @@ -97,6 +97,9 @@ typedef struct FDC int satisfying_sectors; sector_id_t read_track_sector; + int fintr; + + int rw_drive; } FDC; static FDC fdc; @@ -107,8 +110,8 @@ int timetolive; int lastbyte=0; uint8_t disc_3f7; -int discmodified[2]; -int discrate[2]; +int discmodified[4]; +int discrate[4]; int discint; void fdc_reset() @@ -268,49 +271,42 @@ void fdc_reset_fifo_buf() fdc.fifobufpos = 0; } +void fdc_fifo_buf_advance() +{ + if (fdc.fifobufpos == fdc.tfifo) + { + fdc.fifobufpos = 0; + } + else + { + fdc.fifobufpos++; + } + // pclog("FIFO buffer position = %02X\n", fdc.fifobufpos); +} + void fdc_fifo_buf_write(int val) { - if (fdc.fifobufpos < fdc.tfifo) - { - fdc.fifobuf[fdc.fifobufpos] = val; - fdc.fifobufpos++; - fdc.fifobufpos %= fdc.tfifo; - // pclog("FIFO buffer position = %02X\n", fdc.fifobufpos); - if (fdc.fifobufpos == fdc.tfifo) fdc.fifobufpos = 0; - } + fdc.fifobuf[fdc.fifobufpos] = val; + fdc_fifo_buf_advance(); } int fdc_fifo_buf_read() { int temp = 0; - if (fdc.fifobufpos < fdc.tfifo) - { - temp = fdc.fifobuf[fdc.fifobufpos]; - fdc.fifobufpos++; - fdc.fifobufpos %= fdc.tfifo; - // pclog("FIFO buffer position = %02X\n", fdc.fifobufpos); - if (fdc.fifobufpos == fdc.tfifo) fdc.fifobufpos = 0; - } + temp = fdc.fifobuf[fdc.fifobufpos]; + fdc_fifo_buf_advance(); return temp; } -/* For DMA mode, just goes ahead in FIFO buffer but doesn't actually read or write anything. */ -void fdc_fifo_buf_dummy() -{ - if (fdc.fifobufpos < fdc.tfifo) - { - fdc.fifobufpos++; - fdc.fifobufpos %= fdc.tfifo; - // pclog("FIFO buffer position = %02X\n", fdc.fifobufpos); - if (fdc.fifobufpos == fdc.tfifo) fdc.fifobufpos = 0; - } -} - static void fdc_int() { if (!fdc.pcjr) { - picint(1 << 6); + if (fdc.dor & 8) + { + // pclog("FDC interrupt!\n"); + picint(1 << 6); + } } } @@ -345,6 +341,14 @@ int bit_rate = 250; static void fdc_rate(int drive); +void fdc_update_rates() +{ + fdc_rate(0); + fdc_rate(1); + fdc_rate(2); + fdc_rate(3); +} + void fdc_update_is_nsc(int is_nsc) { int old_is_nsc = fdc.is_nsc; @@ -353,8 +357,7 @@ void fdc_update_is_nsc(int is_nsc) { fdc.densel_force = fdc.densel_force ^ 3; } - fdc_rate(0); - fdc_rate(1); + fdc_update_rates(); } void fdc_update_max_track(int max_track) @@ -365,8 +368,7 @@ void fdc_update_max_track(int max_track) void fdc_update_enh_mode(int enh_mode) { fdc.enh_mode = enh_mode; - fdc_rate(0); - fdc_rate(1); + fdc_update_rates(); } int fdc_get_rwc(int drive) @@ -393,8 +395,7 @@ void fdc_update_boot_drive(int boot_drive) void fdc_update_densel_polarity(int densel_polarity) { fdc.densel_polarity = densel_polarity; - fdc_rate(0); - fdc_rate(1); + fdc_update_rates(); } uint8_t fdc_get_densel_polarity() @@ -405,8 +406,7 @@ uint8_t fdc_get_densel_polarity() void fdc_update_densel_force(int densel_force) { fdc.densel_force = densel_force; - fdc_rate(0); - fdc_rate(1); + fdc_update_rates(); } void fdc_update_drvrate(int drive, int drvrate) @@ -545,10 +545,22 @@ void fdc_seek(int drive, int params) fdc.stat |= (1 << fdc.drive); } +int real_drive(int drive) +{ + if (drive < 2) + { + return drive ^ fdd_swap; + } + else + { + return drive; + } +} + void fdc_write(uint16_t addr, uint8_t val, void *priv) { // pclog("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready); - int drive; + int drive, i, drive_num; int seek_time, seek_time_base; switch (addr&7) @@ -578,7 +590,11 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) { val &= 0xfe; } - motoron[0] = val & 0x01; + motoron[0 ^ fdd_swap] = val & 0x01; + /* if (!motoron[0 ^ fdd_swap]) + { + disc_changed[0 ^ fdd_swap] = 0; + } */ // fdc.drive = 0; /* if (motoron) output = 3; @@ -587,6 +603,17 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) } else { + if (!(val & 8) && (fdc.dor & 8)) + { + fdc.tc = 1; + fdc_int(); + } + if (!(val&4)) + { + disc_stop(real_drive(val & 3)); + fdc.stat=0x00; + fdc.pnum=fdc.ptot=0; + } if (val&4) { fdc.stat=0x80; @@ -603,27 +630,34 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) } timer_process(); timer_update_outstanding(); - val &= 0x3f; /* Drives 2 and 3 are not emulated, so their motors are always forced off. */ + // val &= 0x3f; /* Drives 2 and 3 are not emulated, so their motors are always forced off. */ /* We can now simplify this since each motor now spins separately. */ - if (!fdd_get_flags(0 ^ fdd_swap)) + for (i = 0; i < FDD_NUM; i++) { - val &= 0x2f; + drive_num = real_drive(i); + if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) + { + val &= ~(0x10 << drive_num); + } + else + { + motoron[i] = (val & (0x10 << drive_num)); + } } - if (!fdd_get_flags(1 ^ fdd_swap)) + drive_num = real_drive(val & 3); + /* if (!motoron[drive_num]) { - val &= 0x1f; - } - motoron[0] = (val & 0x10); - motoron[1] = (val & 0x20); + disc_changed[drive_num] = 0; + } */ } fdc.dor=val; - // printf("DOR now %02X\n",val); + // printf("DOR now %02X (%04X:%04X)\n",val, CS, cpu_state.pc); return; case 3: /* TDR */ if (fdc.enh_mode) { - drive = (fdc.dor & 1) ^ fdd_swap; + drive = real_drive(fdc.dor & 3); fdc_update_rwc(drive, (val & 0x30) >> 4); } return; @@ -637,8 +671,10 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.perp &= 0xfc; fdc_reset(); } + // pclog("DSR now: %02X\n", val); return; case 5: /*Command register*/ + // pclog("CMD now: %02X\n", val); if ((fdc.stat & 0xf0) == 0xb0) { if (fdc.pcjr || !fdc.fifo) @@ -658,10 +694,20 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) // rpclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot); if (fdc.pnum==fdc.ptot) { + // if ((fdc.stat & 0x10) || !fdc.stat) + if ((fdc.stat & 0xf0) != 0x80) + { + /* If bit 4 of the MSR is set, or the MSR is 0x00, the FDC is NOT in the command phase, therefore do NOT accept commands. */ + return; + } + + fdc.stat &= 0xf; + fdc.tc = 0; fdc.data_ready = 0; fdc.command=val; + fdc.stat |= 0x10; // pclog("Starting FDC command %02X\n",fdc.command); switch (fdc.command&0x1F) { @@ -669,7 +715,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) if (!fdc.is_nsc) goto bad_command; fdc.pnum=0; fdc.ptot=4; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; fdc.format_state = 0; break; @@ -680,19 +726,19 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.wrong_am=0; fdc.pnum=0; fdc.ptot=8; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; fdc.mfm=(fdc.command&0x40)?1:0; break; case 3: /*Specify*/ fdc.pnum=0; fdc.ptot=2; - fdc.stat=0x90; + fdc.stat |= 0x90; break; case 4: /*Sense drive status*/ fdc.pnum=0; fdc.ptot=1; - fdc.stat=0x90; + fdc.stat |= 0x90; break; case 5: /*Write data*/ case 9: /*Write deleted data*/ @@ -703,7 +749,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) // printf("Write data!\n"); fdc.pnum=0; fdc.ptot=8; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; fdc.mfm=(fdc.command&0x40)?1:0; // readflash=1; @@ -722,16 +768,17 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.deleted |= (fdc.command & 0x20); fdc.pnum=0; fdc.ptot=8; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; fdc.mfm=(fdc.command&0x40)?1:0; break; case 7: /*Recalibrate*/ fdc.pnum=0; fdc.ptot=1; - fdc.stat=0x90; + fdc.stat |= 0x90; break; case 8: /*Sense interrupt status*/ + if (!fdc.fintr) goto bad_command; // printf("Sense interrupt status %i\n",curdrive); fdc.lastdrive = fdc.drive; // fdc.stat = 0x10 | (fdc.stat & 0xf); @@ -743,14 +790,14 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) case 10: /*Read sector ID*/ fdc.pnum=0; fdc.ptot=1; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; fdc.mfm=(fdc.command&0x40)?1:0; break; case 0x0d: /*Format track*/ fdc.pnum=0; fdc.ptot=5; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; fdc.format_state = 0; fdc.mfm=(fdc.command&0x40)?1:0; @@ -758,7 +805,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) case 15: /*Seek*/ fdc.pnum=0; fdc.ptot=2; - fdc.stat=0x90; + fdc.stat |= 0x90; break; case 0x0e: /*Dump registers*/ fdc.lastdrive = fdc.drive; @@ -776,13 +823,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) if (!AT || fdc.pcjr || fdc.ps1) goto bad_command; fdc.pnum=0; fdc.ptot=1; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; break; case 0x13: /*Configure*/ fdc.pnum=0; fdc.ptot=3; - fdc.stat=0x90; + fdc.stat |= 0x90; fdc.pos=0; break; case 0x14: /*Unlock*/ @@ -809,7 +856,7 @@ bad_command: // fatal("Bad FDC command %02X\n",val); // dumpregs(); // exit(-1); - fdc.stat=0x10; + fdc.stat |= 0x10; discint=0xfc; timer_process(); disctime = 200 * (1 << TIMER_SHIFT); @@ -819,19 +866,27 @@ bad_command: } else { + fdc.stat = 0x10 | (fdc.stat & 0xf); fdc.params[fdc.pnum++]=val; + if (fdc.pnum == 1) + { + if (command_has_drivesel[fdc.command & 0x1F]) + { + fdc.drive = fdc.dor & 3; + fdc.rw_drive = fdc.params[0] & 3; + if (((fdc.command & 0x1F) == 7) || ((fdc.command & 0x1F) == 15)) + { + fdc.stat |= (1 << real_drive(fdc.drive)); + } + } + } if (fdc.pnum==fdc.ptot) { // pclog("Got all params %02X\n", fdc.command); - fdc.stat=0x30; discint=fdc.command&0x1F; timer_process(); disctime = 1024 * (1 << TIMER_SHIFT); timer_update_outstanding(); - if (command_has_drivesel[discint & 0x1F]) - { - fdc.drive = fdc.params[0] & 3; - } fdc_reset_stat = 0; switch (discint & 0x1F) { @@ -859,17 +914,18 @@ bad_command: fdc.rw_track = fdc.params[1]; // pclog("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.track[fdc.drive], fdc.head, fdc.sector, fdc.eot[fdc.drive]); disc_readsector(fdc.drive, SECTOR_FIRST, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); + fdc.stat |= 0x40; disctime = 0; readflash = 1; fdc.inread = 1; break; case 3: /*Specify*/ - fdc.stat=0x80; - fdc.specify[0] = fdc.params[0]; - fdc.specify[1] = fdc.params[1]; - fdc.dma = (fdc.specify[1] & 1) ^ 1; - disctime = 0; + fdc.stat=0x80; + fdc.specify[0] = fdc.params[0]; + fdc.specify[1] = fdc.params[1]; + fdc.dma = (fdc.specify[1] & 1) ^ 1; + disctime = 0; break; case 0x12: @@ -993,19 +1049,49 @@ bad_command: } } fdc.rw_track = fdc.params[1]; + // pclog("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc.drive, fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4], fdc.params[5], fdc.params[6], fdc.params[7]); + if (((dma_mode(2) & 0x0C) == 0x00) && !fdc.pcjr && fdc.dma) + { + /* DMA is in verify mode, treat this like a VERIFY command. */ + // pclog("Verify-mode read!\n"); + fdc.tc = 1; + fdc.deleted |= 2; + } + // dma_c2_mode(); disc_readsector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); + fdc.stat |= 0x40; disctime = 0; readflash = 1; fdc.inread = 1; break; case 7: /*Recalibrate*/ - seek_time_base = fdd_doublestep_40(fdc.drive ^ fdd_swap) ? 10 : 5; - fdc.stat = 1 << fdc.drive; + seek_time_base = fdd_doublestep_40(real_drive(fdc.drive)) ? 10 : 5; + fdc.stat = (1 << real_drive(fdc.drive)) | 0x80; disctime = 0; - if (((fdc.drive ^ fdd_swap) == 1) && !fdc.drv2en) - fdc_notfound(); - else + + drive_num = real_drive(fdc.drive); + + /* Three conditions under which the command should fail. */ + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num] || fdd_track0(real_drive(drive_num))) + { + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) + { + fdc.st0 = 0x70 | (fdc.params[0] & 3); + } + else + { + fdc.st0 = 0x20 | (fdc.params[0] & 3); + } + disctime = 0; + discint=-3; + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); + break; + } + + if ((real_drive(fdc.drive) != 1) || fdc.drv2en) { fdc_seek(fdc.drive, -fdc.max_track); } @@ -1024,20 +1110,33 @@ bad_command: fdc.format_state = 1; fdc.pos = 0; fdc.stat = 0x30; + // pclog("FDC FORMAT: %02X %02X %02X %02X %02X\n", fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4]); break; case 0xf: /*Seek*/ - fdc.stat = 1 << fdc.drive; + fdc.stat = (1 << fdc.drive) | 0x80; fdc.head = (fdc.params[0] & 4) ? 1 : 0; fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); disctime = 0; - seek_time_base = fdd_doublestep_40(fdc.drive ^ fdd_swap) ? 10 : 5; + + drive_num = real_drive(fdc.drive); + seek_time_base = fdd_doublestep_40(drive_num) ? 10 : 5; + + /* Three conditions under which the command should fail. */ + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) + { + /* Yes, failed SEEK's still report success, unlike failed RECALIBRATE's. */ + fdc.st0 = 0x20 | (fdc.params[0] & 7); + disctime = 0; + discint=-3; + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); + break; + } + if (fdc.command & 0x80) { - if (!fdc.params[1]) - { - break; - } if (fdc.params[1]) { if (fdc.command & 0x40) @@ -1055,16 +1154,32 @@ bad_command: else { disctime = seek_time_base * TIMER_USEC; + + fdc.st0 = 0x20 | (fdc.params[0] & 7); + disctime = 0; + discint=-3; + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); + break; } } else { - seek_time = ((int) (fdc.params[1] - fdc.track[fdc.drive])) * seek_time_base * TIMER_USEC; - if (!seek_time) + // pclog("Seeking to track %i...\n", fdc.params[1]); + seek_time = ((int) (fdc.params[1] - fdc.track[real_drive(fdc.drive)])) * seek_time_base * TIMER_USEC; + + if ((fdc.params[1] - fdc.track[real_drive(fdc.drive)]) == 0) { - disctime = seek_time_base * TIMER_USEC; + fdc.st0 = 0x20 | (fdc.params[0] & 7); + disctime = 0; + discint=-3; + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); break; } + fdc_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); if (seek_time < 0) seek_time = -seek_time; disctime = seek_time; @@ -1076,18 +1191,26 @@ bad_command: disctime = 0; fdc.head = (fdc.params[0] & 4) ? 1 : 0; fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); - if (((fdc.drive ^ fdd_swap) != 1) || fdc.drv2en) + if ((real_drive(fdc.drive) != 1) || fdc.drv2en) + { disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate); + fdc.stat |= 0x50; + } else - fdc_notfound(); + fdc_noidam(); break; } } + else + { + fdc.stat = 0x90 | (fdc.stat & 0xf); + } } return; case 7: if (!AT) return; fdc.rate=val&3; + // pclog("Rate now: %i\n", val & 3); disc_3f7=val; return; @@ -1105,8 +1228,22 @@ uint8_t fdc_read(uint16_t addr, void *priv) // /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %02x %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,fdc.stat,ins); switch (addr&7) { - case 1: /*???*/ - drive = (fdc.dor & 1) ^ fdd_swap; + case 0: /* STA */ + if (is486) + { + return 0; + } + else + { + return 0xff; + } + break; + case 1: /* STB */ + if (is486) + { + return 0; + } + drive = real_drive(fdc.dor & 3); if (!fdc.enable_3f1) return 0xff; // temp=0x50; @@ -1116,8 +1253,12 @@ uint8_t fdc_read(uint16_t addr, void *priv) else temp &= ~0x20; break; + case 2: + temp = fdc.dor; + // pclog("Read DOR: %02X\n", fdc.dor); + break; case 3: - drive = (fdc.dor & 1) ^ fdd_swap; + drive = real_drive(fdc.dor & 3); if (fdc.ps1) { /*PS/1 Model 2121 seems return drive type in port 0x3f3, @@ -1139,7 +1280,12 @@ uint8_t fdc_read(uint16_t addr, void *priv) } break; case 4: /*Status*/ + if (!(fdc.dor & 4) & !fdc.pcjr) + { + return 0; + } temp=fdc.stat; + // pclog("Read MSR: %02X\n", fdc.stat); break; case 5: /*Data*/ fdc.stat&=~0x80; @@ -1157,6 +1303,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) { paramstogo--; temp=fdc.res[10 - paramstogo]; + // pclog("Read result: %02X\n", temp); // pclog("Read param %i %02X\n",10-paramstogo,temp); if (!paramstogo) { @@ -1186,14 +1333,19 @@ uint8_t fdc_read(uint16_t addr, void *priv) fdc.stat &= 0xf0; break; case 7: /*Disk change*/ - drive = (fdc.dor & 1) ^ fdd_swap; + drive = real_drive(fdc.dor & 3); if (fdc.dor & (0x10 << drive)) temp = (disc_changed[drive] || drive_empty[drive])?0x80:0; else temp = 0; if (fdc.dskchg_activelow) /*PC2086/3086 seem to reverse this bit*/ temp ^= 0x80; -// printf("- DC %i %02X %02X %i %i - ",fdc.dor & 1, fdc.dor, 0x10 << (fdc.dor & 1), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]); + if (AT) + { + temp |= 0x7F; + } + // pclog("Read CCR: %02X\n", temp); +// printf("- DC %i %02X %02X %i %i - ",fdc.dor & 3, fdc.dor, 0x10 << (fdc.dor & 3), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]); // discchanged[fdc.dor&1]=0; break; default: @@ -1210,7 +1362,7 @@ void fdc_poll_common_finish(int compare, int st5) { fdc_int(); fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; + fdc.res[4]=(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.rw_drive; fdc.res[5]=st5; fdc.res[6]=0; if (fdc.wrong_am) @@ -1244,6 +1396,16 @@ void fdc_poll_common_finish(int compare, int st5) { fdc.res[5] |= 0x04; } + if (fdc.satisfying_sectors & 8) + { + fdc.res[5] |= 0x04; + fdc.res[6] |= 0x02; + } + if (fdc.satisfying_sectors & 0x10) + { + fdc.res[5] |= 0x04; + fdc.res[6] |= 0x10; + } } fdc.res[7]=fdc.rw_track; fdc.res[8]=fdc.head; @@ -1271,6 +1433,9 @@ void fdc_callback() { int temp; int compare = 0; + int drive_num = 0; + int old_sector = 0; + int bad_end = 0; disctime = 0; // pclog("fdc_callback %i %i\n", discint, disctime); // if (fdc.inread) @@ -1281,13 +1446,18 @@ void fdc_callback() // if (output) printf("EOC - interrupt!\n"); //rpclog("EOC\n"); fdc_int(); + fdc.stat = (fdc.stat & 0xf) | 0x80; + fdc.fintr = 1; + return; case -2: /*End of command*/ fdc.stat = (fdc.stat & 0xf) | 0x80; + fdc.fintr = 0; return; case -1: /*Reset*/ //rpclog("Reset\n"); fdc_int(); fdc_reset_stat = 4; + fdc.fintr = 1; return; case 1: /*Mode*/ fdc.stat=0x80; @@ -1305,14 +1475,18 @@ void fdc_callback() return; } else + { disc_readsector(fdc.drive, SECTOR_NEXT, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); + fdc.stat |= 0x40; + } fdc.inread = 1; return; + case 4: /*Sense drive status*/ fdc.res[10] = (fdc.params[0] & 7) | 0x28; - if (((fdc.drive ^ fdd_swap) != 1) || fdc.drv2en) + if ((real_drive(fdc.drive) != 1) || fdc.drv2en) { - if (fdd_track0(fdc.drive ^ fdd_swap)) + if (fdd_track0(real_drive(fdc.drive))) fdc.res[10] |= 0x10; } if (writeprot[fdc.drive]) @@ -1340,26 +1514,30 @@ void fdc_callback() { compare = 0; } + bad_end = 1; if ((discint == 6) || (discint == 0xC)) { if (fdc.wrong_am && !(fdc.deleted & 0x20)) { /* Mismatching data address mark and no skip, set TC. */ fdc.tc = 1; + bad_end = 0; } } + old_sector = fdc.sector; if (fdc.tc) { + fdc.sector++; fdc_poll_readwrite_finish(compare); return; } - readflash = 1; if ((discint == 0x16) && (fdc.params[0] & 0x80)) { /* VERIFY command, EC set */ fdc.sc--; if (!fdc.sc) { + fdc.sector++; fdc_poll_readwrite_finish(0); return; } @@ -1368,8 +1546,9 @@ void fdc_callback() else if ((discint == 0x16) && !(fdc.params[0] & 0x80)) { /* VERIFY command, EC clear */ - if ((fdc.sector == fdc.params[5]) && (fdc.head == (fdc.command & 0x80) ? 1 : 0)) + if ((fdc.sector == old_sector) && (fdc.head == (fdc.command & 0x80) ? 1 : 0)) { + fdc.sector++; fdc_poll_readwrite_finish(0); return; } @@ -1385,7 +1564,7 @@ void fdc_callback() return; } /* Reached end of track, MT bit is set, head is 1 */ - if ((fdc.head & 1)) + if (fdd_get_head(real_drive(fdc.drive)) == 1) { fdc.rw_track++; fdc.sector = 1; @@ -1394,7 +1573,7 @@ void fdc_callback() fdc_no_dma_end(compare); return; } - if ((fdc.command & 0x80) && (fdd_get_head(fdc.drive ^ fdd_swap) == 0)) + if ((fdc.command & 0x80) && (fdd_get_head(real_drive(fdc.drive)) == 0)) { fdc.sector = 1; fdc.head |= 1; @@ -1405,6 +1584,7 @@ void fdc_callback() { fdc.sector++; } + readflash = 1; switch (discint) { case 5: @@ -1415,6 +1595,7 @@ void fdc_callback() case 0xC: case 0x16: disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); + fdc.stat |= 0x40; break; case 0x11: case 0x19: @@ -1426,15 +1607,13 @@ void fdc_callback() return; case 7: /*Recalibrate*/ - fdc.track[fdc.drive]=0; -// if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0; - if ((fdc.params[0] & 3) <= 1) - fdc.st0 = 0x20 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0); - else - fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0); - if (!fdd_track0(fdc.drive ^ fdd_swap)) + // if (!driveempty[fdc.dor & 3]) discchanged[fdc.dor & 3] = 0; + fdc.track[real_drive(fdc.dor & 3)] = 0; + drive_num = real_drive(fdc.rw_drive); + fdc.st0 = 0x20 | (fdc.params[0] & 3) | (fdd_get_head(drive_num)?4:0); + if (!fdd_track0(drive_num)) { - fdc.st0 |= 0x30; + fdc.st0 |= 0x50; } discint=-3; timer_process(); @@ -1450,11 +1629,12 @@ void fdc_callback() fdc.stat = (fdc.stat & 0xf) | 0xd0; if (fdc_reset_stat) { - if ((4 - fdc_reset_stat) <= 1) + drive_num = real_drive(4 - fdc_reset_stat); + if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) { - disc_stop(4 - fdc_reset_stat); - fdd_set_head((4 - fdc_reset_stat) ^ fdd_swap, 0); - fdc.res[9] = 0xc0 | (4 - fdc_reset_stat) | (fdd_get_head((4 - fdc_reset_stat) ^ fdd_swap) ? 4 : 0); + disc_stop(drive_num); + fdd_set_head(drive_num, 0); + fdc.res[9] = 0xc0 | (4 - fdc_reset_stat) | (fdd_get_head(drive_num) ? 4 : 0); } else { @@ -1463,17 +1643,37 @@ void fdc_callback() } else { - if (fdc.drive <= 1) + drive_num = real_drive(fdc.drive); + if (fdc.drive < FDD_NUM) { - disc_stop(fdc.drive); + disc_stop(drive_num); } fdc.res[9] = fdc.st0; } - fdc.res[10] = fdc.track[fdc.drive]; - if (!fdc_reset_stat) - fdc.st0 = 0x80; - else + if (fdd_get_flags(drive_num)) + { + fdc.res[10] = fdc.track[drive_num]; + } + else + { + fdc.res[10] = 0; + } + // pclog("Track returned by sense: %i\n", fdc.res[10]); + if (fdc_reset_stat) + { fdc_reset_stat--; + /* if (!fdc_reset_stat) + { + fdc.fintr = 0; + } */ + } + if (!fdc_reset_stat) + { + fdc.st0 = 0x80; + fdc.fintr = 0; + } + + // pclog("SENSE INTERRUPT STATUS: Results %02X %02X, ST0 %02X\n", fdc.res[9], fdc.res[10], fdc.st0); paramstogo = 2; discint = 0; @@ -1501,10 +1701,10 @@ void fdc_callback() discint=-2; fdc_int(); fdc.stat=0xD0; - fdc.res[4] = (fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; + fdc.res[4] = (fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.drive; fdc.res[5] = fdc.res[6] = 0; fdc.res[7] = fdc.track[fdc.drive]; - fdc.res[8] = fdd_get_head(fdc.drive ^ fdd_swap); + fdc.res[8] = fdd_get_head(real_drive(fdc.drive)); fdc.res[9] = fdc.format_dat[fdc.pos - 2] + 1; fdc.res[10] = fdc.params[4]; paramstogo=7; @@ -1514,13 +1714,11 @@ void fdc_callback() return; case 15: /*Seek*/ - fdc.track[fdc.params[0] & 3]=fdc.params[1]; -// if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0; + fdc.track[real_drive(fdc.dor & 3)] = fdc.params[1]; +// if (!driveempty[fdc.dor & 3]) discchanged[fdc.dor & 3] = 0; // printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive); - if ((fdc.params[0] & 3) <= 1) - fdc.st0 = 0x20 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0); - else - fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0); + drive_num = real_drive(fdc.rw_drive); + fdc.st0 = 0x20 | (fdc.params[0] & 3) | (fdd_get_head(drive_num)?4:0); discint=-3; timer_process(); disctime = 2048 * (1 << TIMER_SHIFT); @@ -1565,6 +1763,7 @@ void fdc_callback() fdc.pretrk = fdc.params[2]; fdc.fifo = (fdc.params[1] & 0x20) ? 0 : 1; fdc.tfifo = (fdc.params[1] & 0xF) + 1; + // pclog("CONFIGURE (%02X, %02X, %02X)\n", fdc.params[0], fdc.params[1], fdc.params[2]); // pclog("FIFO is now %02X, threshold is %02X\n", fdc.fifo, fdc.tfifo); fdc.stat = 0x80; disctime = 0; @@ -1618,13 +1817,32 @@ void fdc_error(int st5, int st6) fdc_int(); fdc.stat=0xD0; - fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; - fdc.res[5]=st5; /*Overrun*/ + fdc.res[4]=0x40|(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.rw_drive; + fdc.res[5]=st5; fdc.res[6]=st6; - fdc.res[7]=0; - fdc.res[8]=0; - fdc.res[9]=0; - fdc.res[10]=0; + switch(discint) + { + case 0x02: + case 0x05: + case 0x06: + case 0x09: + case 0x0C: + case 0x11: + case 0x16: + case 0x19: + case 0x1D: + fdc.res[7]=fdc.rw_track; + fdc.res[8]=fdc.head; + fdc.res[9]=fdc.sector; + fdc.res[10]=fdc.params[4]; + break; + default: + fdc.res[7]=0; + fdc.res[8]=0; + fdc.res[9]=0; + fdc.res[10]=0; + break; + } paramstogo=7; } @@ -1643,17 +1861,19 @@ int fdc_is_verify() int fdc_data(uint8_t data) { + int result = 0; + if (fdc.deleted & 2) { /* We're in a VERIFY command, so return with 0. */ return 0; } - if (fdc.tc) - return 0; - if (fdc.pcjr || !fdc.dma) { + if (fdc.tc) + return 0; + if (fdc.data_ready) { fdc_overrun(); @@ -1681,8 +1901,16 @@ int fdc_data(uint8_t data) } else { - if (dma_channel_write(2, data) & DMA_OVER) + result = dma_channel_write(2, data); + if (result & DMA_OVER) + { fdc.tc = 1; + // pclog("DMA overrun!\n"); + return -1; + } + + if (fdc.tc) + return -1; if (!fdc.fifo || (fdc.tfifo <= 1)) { @@ -1691,7 +1919,7 @@ int fdc_data(uint8_t data) } else { - fdc_fifo_buf_dummy(); + fdc_fifo_buf_advance(); if (fdc.fifobufpos == 0) { // We have wrapped around, means FIFO is over @@ -1707,12 +1935,13 @@ int fdc_data(uint8_t data) void fdc_finishread() { fdc.inread = 0; - disctime = 200 * TIMER_USEC; + // disctime = 200 * TIMER_USEC; // rpclog("fdc_finishread\n"); } void fdc_track_finishread(int condition) { + fdc.stat = 0x10; fdc.satisfying_sectors |= condition; fdc.inread = 0; fdc_callback(); @@ -1721,6 +1950,7 @@ void fdc_track_finishread(int condition) void fdc_sector_finishcompare(int satisfying) { + fdc.stat = 0x10; fdc.satisfying_sectors++; fdc.inread = 0; fdc_callback(); @@ -1729,17 +1959,45 @@ void fdc_sector_finishcompare(int satisfying) void fdc_sector_finishread() { + fdc.stat = 0x10; fdc.inread = 0; fdc_callback(); // rpclog("fdc_finishread\n"); } +#if 0 void fdc_notfound() { fdc_error(5, 0); // rpclog("c82c711_fdc_notfound\n"); } +#endif + +/* There is no sector ID. */ +void fdc_noidam() +{ + fdc_error(1, 0); +} + +/* Sector ID's are there, but there is no sector. */ +void fdc_nosector() +{ + fdc_error(4, 0); +} + +/* There is no sector data. */ +void fdc_nodataam() +{ + fdc_error(1, 1); +} + +/* Abnormal termination with both status 1 and 2 set to 0, used when abnormally + terminating the FDC FORMAT TRACK command. */ +void fdc_cannotformat() +{ + fdc_error(0, 0); +} void fdc_datacrcerror() { @@ -1755,6 +2013,16 @@ void fdc_headercrcerror() // rpclog("c82c711_fdc_headercrcerror\n"); } +void fdc_wrongcylinder() +{ + fdc_error(4, 0x10); +} + +void fdc_badcylinder() +{ + fdc_error(4, 0x02); +} + void fdc_writeprotect() { fdc_error(0x02, 0); @@ -1798,12 +2066,12 @@ int fdc_getdata(int last) } else { - fdc_fifo_buf_dummy(); + fdc_fifo_buf_advance(); if (!last && (fdc.fifobufpos == 0)) fdc.stat = 0x90; } - + if (data & DMA_OVER) fdc.tc = 1; } @@ -1814,10 +2082,10 @@ int fdc_getdata(int last) void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2) { -// pclog("SectorID %i %i %i %i\n", track, side, sector, size); + // pclog("SectorID %i %i %i %i\n", track, side, sector, size); fdc_int(); fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; + fdc.res[4]=(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.drive; fdc.res[5]=0; fdc.res[6]=0; fdc.res[7]=track; @@ -1839,10 +2107,13 @@ void fdc_init() fdc.dskchg_activelow = 0; fdc.enable_3f1 = 1; + fdc_update_is_nsc(0); fdc_update_enh_mode(0); fdc_update_densel_polarity(1); fdc_update_rwc(0, 0); fdc_update_rwc(1, 0); + fdc_update_rwc(2, 0); + fdc_update_rwc(3, 0); fdc_update_densel_force(0); fdc_update_drv2en(1); @@ -1904,7 +2175,7 @@ void fdc_remove() void fdc_discchange_clear(int drive) { - if (drive < 2) + if (drive < FDD_NUM) disc_changed[drive] = 0; } diff --git a/src/fdc.h b/src/fdc.h index 1e159abc7..9b1f840aa 100644 --- a/src/fdc.h +++ b/src/fdc.h @@ -31,6 +31,13 @@ void fdc_update_densel_force(int densel_force); void fdc_update_drvrate(int drive, int drvrate); void fdc_update_drv2en(int drv2en); +void fdc_noidam(); +void fdc_nosector(); +void fdc_nodataam(); +void fdc_cannotformat(); +void fdc_wrongcylinder(); +void fdc_badcylinder(); + sector_id_t fdc_get_read_track_sector(); int fdc_get_compare_condition(); int fdc_is_deleted(); @@ -55,3 +62,5 @@ void fdc_sector_finishcompare(int satisfying); void fdc_sector_finishread(); void fdc_track_finishread(int condition); int fdc_is_verify(); + +int real_drive(int drive); diff --git a/src/fdc37c665.c b/src/fdc37c665.c index 7a6dcb700..d076ae2cb 100644 --- a/src/fdc37c665.c +++ b/src/fdc37c665.c @@ -28,7 +28,7 @@ static void write_lock(uint8_t val) void fdc37c665_write(uint16_t port, uint8_t val, void *priv) { - pclog("Write SuperIO %04x %02x\n", port, val); + // pclog("Write SuperIO %04x %02x\n", port, val); if (fdc37c665_lock[0] == 0x55 && fdc37c665_lock[1] == 0x55) { if (port == 0x3f0) @@ -130,7 +130,7 @@ void fdc37c665_write(uint16_t port, uint8_t val, void *priv) uint8_t fdc37c665_read(uint16_t port, void *priv) { - pclog("Read SuperIO %04x %02x\n", port, fdc37c665_curreg); + // pclog("Read SuperIO %04x %02x\n", port, fdc37c665_curreg); if (fdc37c665_lock[0] == 0x55 && fdc37c665_lock[1] == 0x55) { if (port == 0x3f1) diff --git a/src/fdc37c932fr.c b/src/fdc37c932fr.c index 96c9e1a04..68abfea5e 100644 --- a/src/fdc37c932fr.c +++ b/src/fdc37c932fr.c @@ -14,7 +14,6 @@ #include "ide.h" #include "io.h" #include "lpt.h" -#include "mouse_serial.h" #include "serial.h" #include "fdc37c932fr.h" @@ -245,6 +244,8 @@ process_value: if (valxor & 0xC) fdc_update_densel_force((val & 0xC) >> 2); break; case 0xF2: + if (valxor & 0xC0) fdc_update_rwc(3, (valxor & 0xC0) >> 6); + if (valxor & 0x30) fdc_update_rwc(2, (valxor & 0x30) >> 4); if (valxor & 0x0C) fdc_update_rwc(1, (valxor & 0x0C) >> 2); if (valxor & 0x03) fdc_update_rwc(0, (valxor & 0x03)); break; @@ -254,6 +255,12 @@ process_value: case 0xF5: if (valxor & 0x18) fdc_update_drvrate(1, (val & 0x18) >> 3); break; + case 0xF6: + if (valxor & 0x18) fdc_update_drvrate(2, (val & 0x18) >> 3); + break; + case 0xF7: + if (valxor & 0x18) fdc_update_drvrate(3, (val & 0x18) >> 3); + break; } break; case 3: @@ -471,8 +478,12 @@ void fdc37c932fr_init() fdd_swap = 0; fdc_update_rwc(0, 0); fdc_update_rwc(1, 0); + fdc_update_rwc(2, 0); + fdc_update_rwc(3, 0); fdc_update_drvrate(0, 0); fdc_update_drvrate(1, 0); + fdc_update_drvrate(2, 0); + fdc_update_drvrate(3, 0); fdc_update_max_track(79); io_sethandler(0xe0, 0x0006, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL); io_sethandler(0xea, 0x0002, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL); diff --git a/src/fdd.c b/src/fdd.c index 5d7fb46c8..b6c49143a 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -15,7 +15,7 @@ static struct int densel; int head; -} fdd[2]; +} fdd[FDD_NUM]; /* Flags: Bit 0: 300 rpm supported; @@ -25,6 +25,9 @@ static struct Bit 4: high density supported; Bit 5: extended density supported; Bit 6: double step for 40-track media; + Bit 7: invert DENSEL polarity; + Bit 8: ignore DENSEL; + Bit 9: drive is a PS/2 drive; */ #define FLAG_RPM_300 1 #define FLAG_RPM_360 2 @@ -33,6 +36,9 @@ static struct #define FLAG_HOLE1 16 #define FLAG_HOLE2 32 #define FLAG_DOUBLE_STEP 64 +#define FLAG_INVERT_DENSEL 128 +#define FLAG_IGNORE_DENSEL 256 +#define FLAG_PS2 512 static struct { @@ -60,10 +66,18 @@ static struct .max_track = 86, .flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP }, + { /*3.5" HD PS/2*/ + .max_track = 86, + .flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2 + }, { /*3.5" HD*/ .max_track = 86, .flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP }, + { /*3.5" HD PC-98*/ + .max_track = 86, + .flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL + }, { /*3.5" HD 3-Mode*/ .max_track = 86, .flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP @@ -78,7 +92,7 @@ int fdd_swap = 0; void fdd_forced_seek(int drive, int track_diff) { - drive ^= fdd_swap; + drive = real_drive(drive); fdd[drive].track += track_diff; @@ -96,7 +110,7 @@ void fdd_forced_seek(int drive, int track_diff) void fdd_seek(int drive, int track_diff) { - drive ^= fdd_swap; + drive = real_drive(drive); if (!track_diff) { @@ -121,7 +135,7 @@ void fdd_seek(int drive, int track_diff) int fdd_track0(int drive) { - drive ^= fdd_swap; + drive = real_drive(drive); /* If drive is disabled, TRK0 never gets set. */ if (!drive_types[fdd[drive].type].max_track) return 0; @@ -131,29 +145,49 @@ int fdd_track0(int drive) void fdd_set_densel(int densel) { - fdd[0].densel = densel; - fdd[1].densel = densel; + int i = 0; + + for (i = 0; i < 4; i++) + { + if (drive_types[fdd[i].type].flags & FLAG_INVERT_DENSEL) + { + fdd[i].densel = densel ^ 1; + } + else + { + fdd[i].densel = densel; + } + } } int fdd_getrpm(int drive) { int hole = disc_hole(drive); - drive ^= fdd_swap; + int densel = 0; + + drive = real_drive(drive); + + densel = fdd[drive].densel; + + if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL) + { + densel ^= 1; + } if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) return 300; if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) return 360; if (drive_types[fdd[drive].type].flags & FLAG_525) { - return fdd[drive].densel ? 360 : 300; + return densel ? 360 : 300; } else { /* disc_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */ if (hole == 1) { - return fdd[drive].densel ? 300 : 360; + return densel ? 300 : 360; } else { @@ -171,7 +205,7 @@ int fdd_can_read_medium(int drive) { int hole = disc_hole(drive); - drive ^= fdd_swap; + drive = real_drive(drive); hole = 1 << (hole + 3); @@ -186,7 +220,12 @@ int fdd_doublestep_40(int drive) void fdd_set_type(int drive, int type) { + int old_type = fdd[drive].type; fdd[drive].type = type; + if ((drive_types[old_type].flags ^ drive_types[type].flags) & FLAG_INVERT_DENSEL) + { + fdd[drive].densel ^= 1; + } } int fdd_get_type(int drive) @@ -211,7 +250,7 @@ int fdd_is_ed(int drive) void fdd_set_head(int drive, int head) { - drive ^= fdd_swap; + drive = real_drive(drive); fdd[drive].head = head; } @@ -220,6 +259,18 @@ int fdd_get_head(int drive) return fdd[drive].head; } +int fdd_get_densel(int drive) +{ + if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL) + { + return fdd[drive].densel ^ 1; + } + else + { + return fdd[drive].densel; + } +} + void fdd_init() { } diff --git a/src/gameport.c b/src/gameport.c index 84fb021e3..6fa788491 100644 --- a/src/gameport.c +++ b/src/gameport.c @@ -197,9 +197,12 @@ void gameport_update_joystick_type() { gameport_t *gameport = gameport_global; - gameport->joystick->close(gameport->joystick_dat); - gameport->joystick = joystick_list[joystick_type]; - gameport->joystick_dat = gameport->joystick->init(); + if (gameport) + { + gameport->joystick->close(gameport->joystick_dat); + gameport->joystick = joystick_list[joystick_type]; + gameport->joystick_dat = gameport->joystick->init(); + } } void *gameport_init() diff --git a/src/ibm.h b/src/ibm.h index 2bf2cd89e..2bbc1ba9e 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -7,7 +7,7 @@ #define printf pclog /*Memory*/ -uint8_t *ram,*vram; +uint8_t *ram; uint32_t rammask; @@ -60,10 +60,8 @@ void outl(uint16_t port, uint32_t val); FILE *romfopen(char *fn, char *mode); extern int shadowbios,shadowbios_write; -extern int cache; extern int mem_size; extern int readlnum,writelnum; -extern int memwaitstate; /*Processor*/ @@ -182,8 +180,7 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128); /*x86reg regs[8];*/ uint16_t flags,eflags; -uint32_t /*cs,ds,es,ss,*/oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; -//uint16_t msw; +uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; extern int ins,output; extern int cycdiff; @@ -198,7 +195,6 @@ uint8_t *pccache2; _cs,_ds,_es,_ss are the segment structures CS,DS,ES,SS is the 16-bit data cs,ds,es,ss are defines to the bases*/ -//uint16_t CS,DS,ES,SS; #define CS _cs.seg #define DS _ds.seg #define ES _es.seg @@ -252,6 +248,7 @@ uint32_t dr[8]; extern int cycles_lost; extern int israpidcad; extern int is486; +extern int is_pentium; extern uint8_t opcode; extern int insc; extern int fpucount; @@ -291,7 +288,6 @@ typedef struct PIT PIT pit; void setpitclock(float clock); -int pitcount; float pit_timer0_freq(); @@ -325,7 +321,6 @@ typedef struct PPI } PPI; PPI ppi; -extern int key_inhibit; /*PIC*/ @@ -339,17 +334,16 @@ typedef struct PIC PIC pic,pic2; extern int pic_intpending; -int intcount; int disctime; -char discfns[2][256]; -int driveempty[2]; +char discfns[4][256]; +int driveempty[4]; -#define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_INCOLOR) && (romset=ROM_IBMAT)) -#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200) +#define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_HERCULESPLUS || gfxcard==GFX_INCOLOR) && (romset=ROM_IBMAT)) +#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_WY700 && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && gfxcard!=GFX_HERCULESPLUS && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200) #define PCJR (romset == ROM_IBMPCJR) -#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486) +#define AMIBIOS (romset==ROM_AMI386SX || romset==ROM_AMI486 || romset == ROM_WIN486) int GAMEBLASTER, GUS, SSI2001, voodoo_enabled, aha154x_enabled; extern int AMSTRAD, AT, is286, is386, PCI, TANDY; @@ -387,7 +381,7 @@ enum ROM_IBMAT386, ROM_ACER386, ROM_MEGAPC, - ROM_AMI386, + ROM_AMI386SX, ROM_AMI486, ROM_WIN486, ROM_PCI486, @@ -399,6 +393,9 @@ enum ROM_DESKPRO_386, ROM_IBMPS1_2121, + ROM_AMI386DX_OPTI495, + ROM_MR386DX_OPTI495, + ROM_DTK486, /*DTK PKM-0038S E-2 / SiS 471 / Award BIOS / SiS 85C471*/ ROM_VLI486SV2G, /*ASUS VL/I-486SV2G / SiS 471 / Award BIOS / SiS 85C471*/ ROM_R418, /*Rise Computer R418 / SiS 496/497 / Award BIOS / SMC FDC37C665*/ @@ -416,6 +413,8 @@ enum ROM_MARL, /*Intel Advanced/ML / 430HX / AMI BIOS / National Semiconductors PC87306*/ ROM_THOR, /*Intel Advanced/ATX / 430FX / AMI BIOS / National Semiconductors PC87306*/ + ROM_MRTHOR, /*Intel Advanced/ATX / 430FX / MR.BIOS / National Semiconductors PC87306*/ + ROM_POWERMATE_V,/*NEC PowerMate V / 430FX / Phoenix BIOS / SMC FDC37C665*/ ROM_MAX }; @@ -449,6 +448,7 @@ enum GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/ GFX_INCOLOR, /* Hercules InColor */ GFX_COLORPLUS, /* Plantronics ColorPlus */ + GFX_WY700, /* Wyse 700 */ GFX_COMPAQ_EGA, /*Compaq EGA*/ GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/ GFX_COMPAQ_VGA, /*Compaq/Paradise VGA*/ @@ -463,6 +463,8 @@ enum GFX_RIVATNT, GFX_RIVA128, GFX_HERCULESPLUS, + GFX_RIVATNT2, + GFX_MAX }; @@ -474,44 +476,15 @@ int cpuspeed; /*Video*/ -void (*pollvideo)(); -void pollega(); int readflash; -uint8_t hercctrl; -int slowega,egacycles,egacycles2; -extern uint8_t gdcreg[16]; extern int egareads,egawrites; -extern int cga_comp; extern int vid_resize; extern int vid_api; extern int winsizex,winsizey; -extern int chain4; - -uint8_t readvram(uint16_t addr); -void writevram(uint16_t addr, uint8_t val); -void writevramgen(uint16_t addr, uint8_t val); - -uint8_t readtandyvram(uint16_t addr); -void writetandy(uint16_t addr, uint8_t val); -void writetandyvram(uint16_t addr, uint8_t val); - -extern int et4k_b8000; extern int changeframecount; -extern uint8_t changedvram[(8192*1024)/1024]; - -void writeega_chain4(uint32_t addr, uint8_t val); -extern uint32_t svgarbank,svgawbank; - -/*Serial*/ -extern int mousedelay; /*Sound*/ -uint8_t spkstat; - -float spktime; -int rtctime; -int soundtime,gustime,gustime2,vidtime; int ppispeakon; float CGACONST; float MDACONST; @@ -523,10 +496,6 @@ int gated,speakval,speakon; /*Sound Blaster*/ -/*int sbenable,sblatchi,sblatcho,sbcount,sb_enable_i,sb_count_i; -int16_t sbdat;*/ -void setsbclock(float clock); - #define SADLIB 1 /*No DSP*/ #define SB1 2 /*DSP v1.05*/ #define SB15 3 /*DSP v2.00*/ @@ -538,11 +507,6 @@ void setsbclock(float clock); #define SND_WSS 9 /*Windows Sound System*/ #define SND_PAS16 10 /*Pro Audio Spectrum 16*/ -int sbtype; - -int clocks[3][12][4]; -int at70hz; - char pcempath[512]; @@ -557,7 +521,7 @@ typedef struct uint32_t base; } hard_disk_t; -hard_disk_t hdc[4]; +hard_disk_t hdc[6]; uint64_t hdt[128][3]; @@ -588,20 +552,14 @@ extern int ide_ter_enabled; #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define ELEMENTS(Array) (sizeof(Array) / sizeof((Array)[0])) -extern int ui_writeprot[2]; +extern int ui_writeprot[4]; void pclog(const char *format, ...); extern int nmi; -extern int times; - extern float isa_timing, bus_timing; -extern int frame; - - -uint8_t *vramp; uint64_t timer_read(); extern uint64_t timer_freq; @@ -617,7 +575,6 @@ void resetpc_cad(); extern int start_in_fullscreen; extern int window_w, window_h, window_x, window_y, window_remember; -extern int mouse_always_serial; extern uint64_t pmc[2]; diff --git a/src/ide.c b/src/ide.c index 3083cb01e..aa53183d5 100644 --- a/src/ide.c +++ b/src/ide.c @@ -145,7 +145,7 @@ IDE ide_drives[6]; IDE *ext_ide; -char ide_fn[4][512]; +char ide_fn[6][512]; int (*ide_bus_master_read_sector)(int channel, uint8_t *data); int (*ide_bus_master_write_sector)(int channel, uint8_t *data); @@ -298,6 +298,7 @@ static inline void ide_irq_lower(IDE *ide) #endif // } ide->irqstat=0; + // ide->service=0; } int get_irq(uint8_t board) @@ -307,6 +308,13 @@ int get_irq(uint8_t board) else if (board == 2) return 1 << 10; } +int get_pic_mask(uint8_t board) +{ + if (board == 0) return 1 << 6; + else if (board == 1) return 1 << 7; + else if (board == 2) return 1 << 2; +} + void ide_irq_update(IDE *ide) { #ifdef RPCEMU_IDE @@ -326,9 +334,9 @@ void ide_irq_update(IDE *ide) else if ((pic2.pend|pic2.ins)&0x40) picintc((ide->board)?(1<<15):(1<<14)); #else - if (ide->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(ide->fdisk & 2)) + if (ide->irqstat && !((pic2.pend|pic2.ins)&get_pic_mask(ide->board)) && !(ide->fdisk & 2)) picint(get_irq(ide->board)); - else if ((pic2.pend|pic2.ins)&0x40) + else if ((pic2.pend|pic2.ins)&get_pic_mask(ide->board)) picintc(get_irq(ide->board)); #endif #endif @@ -385,9 +393,15 @@ ide_padstr8(uint8_t *buf, int buf_size, const char *src) */ static void ide_identify(IDE *ide) { + int c, h, s; + memset(ide->buffer, 0, 512); //ide->buffer[1] = 101; /* Cylinders */ + + c = hdc[cur_ide[ide->board]].tracks; /* Cylinders */ + h = hdc[cur_ide[ide->board]].hpc; /* Heads */ + s = hdc[cur_ide[ide->board]].spt; /* Sectors */ ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */ ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */ @@ -399,7 +413,11 @@ static void ide_identify(IDE *ide) ide->buffer[21] = 512; /*Buffer size*/ ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/ ide->buffer[48] = 1; /*Dword transfers supported*/ - ide->buffer[49] = (1 << 9) | (1 << 8); /* LBA and DMA supported */ + ide->buffer[49] = (1 << 8); /* LBA and DMA supported */ + if ((c > 1024) || (h > 16) || (s > 63)) + { + ide->buffer[49] |= (1 << 9); + } ide->buffer[50] = 0x4000; /* Capabilities */ ide->buffer[51] = 2 << 8; /*PIO timing mode*/ ide->buffer[52] = 2 << 8; /*DMA timing mode*/ @@ -670,7 +688,13 @@ void resetide(void) idecallback[0]=idecallback[1]=0; - for (d = 0; d < 4; d++) +#ifdef MAINLINE +#define IDE_DRIVES 4 +#else +#define IDE_DRIVES 6 +#endif + + for (d = 0; d < IDE_DRIVES; d++) { ide_drives[d].packetstatus = 0xFF; @@ -691,30 +715,10 @@ void resetide(void) ide_drives[d].dma_identify_data[1] = 7 | (1 << 15); ide_drives[d].dma_identify_data[2] = 0x3f; } + + ide_drives[d].error = 1; } - /* REMOVE WHEN SUBMITTING TO MAINLINE - START */ - for (d = 4; d < 6; d++) - { - ide_drives[d].packetstatus = 0xFF; - - if ((atapi_cdrom_channel == d) && cdrom_enabled && !scsi_cdrom_enabled) - { - ide_drives[d].type = IDE_CDROM; - } - else - { - ide_drives[d].type = IDE_NONE; - } - - ide_set_signature(&ide_drives[d]); - - ide_drives[d].dma_identify_data[0] = 7; - ide_drives[d].dma_identify_data[1] = 7 | (1 << 15); - ide_drives[d].dma_identify_data[2] = 0x3f; - } - /* REMOVE WHEN SUBMITTING TO MAINLINE - END */ - cur_ide[0] = 0; cur_ide[1] = 2; @@ -804,13 +808,13 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; // if ((cr0&1) && !(eflags&VM_FLAG)) -// pclog("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, pc, ins); -// return; + // pclog("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, cpu_state.pc, ins); + // return; addr|=0x80; /* ONLY FOR EXPERIMENTAL */ addr|=0x10; /* 1F0 | 10 = 1F0, 1E8 | 10 = 1F8 */ addr&=0xFFF7; /* 1F0 & FFF7 = 1F0, 1F8 | FFF7 = 1F0 */ -// if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat); + // if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat); /*if (idedebug) */ // pclog("Write IDE %08X %02X %04X:%08X\n",addr,val,CS,pc); // int c; @@ -898,11 +902,15 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); - ide_irq_update(ide); + ide_irq_update(ide); return; case 0x1F7: /* Command register */ - if (ide->type == IDE_NONE) return; + if (ide->type == IDE_NONE) + { + ide->error=1; + return; + } // pclog("IDE command %02X drive %i\n",val,ide.drive); ide_irq_lower(ide); ide->command=val; @@ -1076,7 +1084,14 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) timer_process(); idecallback[ide_board]=500*IDE_TIME; timer_update_outstanding(); - ide->reset = ide_other->reset = 1; + if (ide->type != IDE_NONE) + { + ide->reset = 1; + } + if (ide_other->type != IDE_NONE) + { + ide->reset = 1; + } ide->atastat = ide_other->atastat = BUSY_STAT; // pclog("IDE Reset %i\n", ide_board); } @@ -1102,7 +1117,16 @@ uint8_t readide(int ide_board, uint16_t addr) // pclog("ReadIDE %04X from %04X(%08X):%08X\n", addr, CS, cs, pc); // return 0xFF; - if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return 0; + if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) + { + // pclog("Reading empty IDE channel (%04X)\n", addr); + if (addr == 0x1f7) + { + /* This is apparently required for an empty ID channel. */ + return 0x20; + } + return 0; + } // /*if (addr!=0x1F7 && addr!=0x3F6) */pclog("Read IDEb %04X %02X %02X %i %04X:%04X %i %04X\n",addr,ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,pc,ide_board, BX); //rpclog("Read IDE %08X %08X %02X\n",addr,PC,iomd.irqb.mask); switch (addr) @@ -1115,39 +1139,83 @@ uint8_t readide(int ide_board, uint16_t addr) case 0x1F1: /* Error */ // pclog("Read error %02X\n",ide.error); - temp = ide->error; + if (ide->type == IDE_NONE) + { + temp = 1; + } + else + { + temp = ide->error; + } break; case 0x1F2: /* Sector count */ // pclog("Read sector count %02X\n",ide->secount); - temp = (uint8_t)ide->secount; + if (ide->type == IDE_NONE) + { + temp = 1; + } + else + { + temp = (uint8_t)ide->secount; + } break; case 0x1F3: /* Sector */ - temp = (uint8_t)ide->sector; + if (ide->type == IDE_NONE) + { + temp = 1; + } + else + { + temp = (uint8_t)ide->sector; + } break; case 0x1F4: /* Cylinder low */ // pclog("Read cyl low %02X\n",ide.cylinder&0xFF); - temp = (uint8_t)(ide->cylinder&0xFF); + if (ide->type == IDE_NONE) + { + temp = 0xFF; + } + else + { + temp = (uint8_t)(ide->cylinder&0xFF); + } break; case 0x1F5: /* Cylinder high */ // pclog("Read cyl low %02X\n",ide.cylinder>>8); - temp = (uint8_t)(ide->cylinder>>8); + if (ide->type == IDE_NONE) + { + temp = 0xFF; + } + else + { + temp = (uint8_t)(ide->cylinder>>8); + } break; case 0x1F6: /* Drive/Head */ - temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + if (ide->type == IDE_NONE) + { + temp = (uint8_t)(((cur_ide[ide_board] & 1) ? 0x10 : 0) | 0xa0); + } + else + { + temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + } break; case 0x1F7: /* Status */ - if (ide->type == IDE_NONE) +#if 0 + if (ide->type == IDE_NONE) { // pclog("Return status 00\n"); - temp = 0; + temp = DSC_STAT; break; } +#endif ide_irq_lower(ide); if (ide->type == IDE_CDROM) { @@ -1168,7 +1236,7 @@ uint8_t readide(int ide_board, uint16_t addr) if (ide->type == IDE_NONE) { // pclog("Return status 00\n"); - temp = 0; + temp = DSC_STAT; break; } if (ide->type == IDE_CDROM) @@ -1184,8 +1252,8 @@ uint8_t readide(int ide_board, uint16_t addr) } break; } -// if (ide_board) pclog("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,pc,ide_board); - return temp; + ///* if (ide_board) */ pclog("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board); + return temp; // fatal("Bad IDE read %04X\n", addr); } @@ -1267,8 +1335,8 @@ void callbackide(int ide_board) if (ide->command==0x30) times30++; // if (times30==2240) output=1; //if (times30==2471 && ide->command==0xA0) output=1; -///*if (ide_board) */pclog("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); -// if (times30==1294) + ///*if (ide_board) */pclog("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); + // if (times30==1294) // output=1; if (ide->reset) { @@ -1654,6 +1722,7 @@ void callbackide(int ide_board) case WIN_IDENTIFY: /* Identify Device */ if (ide->type == IDE_NONE) { + ide_set_signature(ide); goto abort_cmd; } if (IDE_DRIVE_IS_CDROM(ide)) @@ -1854,7 +1923,7 @@ static int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type) } else if ((cdrom_sector_flags & 0x06) == 0x06) { - pclog("Invalid error flags\n"); + // pclog("Invalid error flags\n"); return 0; } @@ -1877,7 +1946,7 @@ static int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type) } else if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) { - pclog("Invalid subchannel data flags\n"); + // pclog("Invalid subchannel data flags\n"); return 0; } // } @@ -1892,7 +1961,7 @@ static int cdrom_LBAtoMSF_accurate(IDE *ide) int temp_pos; int m, s, f; - temp_pos = ide->cdpos; + temp_pos = ide->cdpos + 150; f = temp_pos % 75; temp_pos -= f; temp_pos /= 75; @@ -1925,27 +1994,37 @@ static int cdrom_read_data(IDE *ide, uint8_t *buffer) memset(cdrom_sector_buffer.buffer, 0, 2856); - cdrom->readsector_raw(cdrom_sector_buffer.buffer, real_pos, cdrom_sector_ismsf); - is_audio = cdrom->is_track_audio(real_pos, cdrom_sector_ismsf); + // is_audio = cdrom->is_track_audio(real_pos, cdrom_sector_ismsf); + real_sector_type = cdrom->sector_data_type(real_pos, cdrom_sector_ismsf); + // pclog("Sector type: %i\n", real_sector_type); + + if ((cdrom_sector_type > 0) && (cdrom_sector_type < 6)) + { + if (real_sector_type != cdrom_sector_type) + { + return 0; + } + } + else if (cdrom_sector_type == 6) + { + /* READ (6), READ (10), READ (12) */ + if ((real_sector_type != 2) && (real_sector_type != 4)) + { + return 0; + } + } if (!(cdrom_sector_flags & 0xf0)) /* 0x00 and 0x08 are illegal modes */ { return 0; } + + cdrom->readsector_raw(cdrom_sector_buffer.buffer, real_pos, cdrom_sector_ismsf); - if (cdrom->is_track_audio(ide->cdpos, 0)) + if (real_sector_type == 1) { - real_sector_type = 1; - - if (cdrom_sector_type > 1) - { - return 0; - } - else - { - memcpy(b, cdrom_sector_buffer.buffer, 2352); - cdrom_sector_size = 2352; - } + memcpy(b, cdrom_sector_buffer.buffer, 2352); + cdrom_sector_size = 2352; } else { @@ -1969,140 +2048,114 @@ static int cdrom_read_data(IDE *ide, uint8_t *buffer) temp_b += 4; } - switch(cdrom_sector_buffer.cdrom_sector.header[3]) - { - case 1: - real_sector_type = 2; /* Mode 1 */ - break; - case 2: - real_sector_type = 3; /* Mode 2 */ - break; - default: - return 0; - } - if (real_sector_type == 2) { - if ((cdrom_sector_type == 0) || (cdrom_sector_type == 2)) + /* Mode 1 sector, expected type is 1 type. */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ { - /* Mode 1 sector, expected type is 1 type. */ - if (cdrom_sector_flags & 0x40) /* Sub-header */ + if (!(cdrom_sector_flags & 0x10)) /* No user data */ { - if (!(cdrom_sector_flags & 0x10)) /* No user data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048); - cdrom_sector_size += 2048; - temp_b += 2048; - } - if (cdrom_sector_flags & 0x08) /* EDC/ECC */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288); - cdrom_sector_size += 288; - temp_b += 288; + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8); + cdrom_sector_size += 8; + temp_b += 8; } } - else + if (cdrom_sector_flags & 0x10) /* User data */ { - return 0; + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048); + cdrom_sector_size += 2048; + temp_b += 2048; + } + if (cdrom_sector_flags & 0x08) /* EDC/ECC */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288); + cdrom_sector_size += 288; + temp_b += 288; } } else if (real_sector_type == 3) { - if ((cdrom_sector_type == 0) || (cdrom_sector_type == 3)) + /* Mode 2 sector, non-XA mode. */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ { - /* Mode 2 sector, non-XA mode. */ - if (cdrom_sector_flags & 0x40) /* Sub-header */ - { - if (!(cdrom_sector_flags & 0x10)) /* No user data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 2328); - cdrom_sector_size += 8; - temp_b += 8; - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); - cdrom_sector_size += 2328; - temp_b += 2328; - } - } - else if (cdrom_sector_type == 4) - { - /* Mode 2 sector, XA Form 1 mode */ - if ((cdrom_sector_flags & 0xf0) == 0x30) - { - return 0; - } - if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8)) - { - return 0; - } - if (cdrom_sector_flags & 0x40) /* Sub-header */ + if (!(cdrom_sector_flags & 0x10)) /* No user data */ { memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); cdrom_sector_size += 8; temp_b += 8; } - if (cdrom_sector_flags & 0x10) /* User data */ - { - if ((cdrom_sector_flags & 0xf0) == 0x10) - { - /* The data is alone, include sub-header. */ - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2040); - cdrom_sector_size += 2040; - temp_b += 2040; - } - if (cdrom_sector_flags & 0x08) /* EDC/ECC */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data + 2040, 288); - cdrom_sector_size += 288; - temp_b += 288; - } } - else if (cdrom_sector_type == 5) + if (cdrom_sector_flags & 0x10) /* User data */ { - /* Mode 2 sector, XA Form 2 mode */ - if ((cdrom_sector_flags & 0xf0) == 0x30) - { - return 0; - } - if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8)) - { - return 0; - } - /* Mode 2 sector, XA Form 1 mode */ - if (cdrom_sector_flags & 0x40) /* Sub-header */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); - cdrom_sector_size += 2328; - temp_b += 2328; - } + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 2328); + cdrom_sector_size += 8; + temp_b += 8; + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); + cdrom_sector_size += 2328; + temp_b += 2328; } - else + } + else if (real_sector_type == 4) + { + /* Mode 2 sector, XA Form 1 mode */ + if ((cdrom_sector_flags & 0xf0) == 0x30) { return 0; } + if (((cdrom_sector_flags & 0xf8) >= 0xa8) && ((cdrom_sector_flags & 0xf8) <= 0xd8)) + { + return 0; + } + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + if ((cdrom_sector_flags & 0xf0) == 0x10) + { + /* The data is alone, include sub-header. */ + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2040); + cdrom_sector_size += 2040; + temp_b += 2040; + } + if (cdrom_sector_flags & 0x08) /* EDC/ECC */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data + 2040, 288); + cdrom_sector_size += 288; + temp_b += 288; + } + } + else if (real_sector_type == 5) + { + /* Mode 2 sector, XA Form 2 mode */ + if ((cdrom_sector_flags & 0xf0) == 0x30) + { + return 0; + } + if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8)) + { + return 0; + } + /* Mode 2 sector, XA Form 1 mode */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); + cdrom_sector_size += 2328; + temp_b += 2328; + } } else { @@ -2138,6 +2191,7 @@ static void atapicommand(int ide_board) int media; int format; int ret; + int real_pos; #if 0 pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins,SCSISense.UnitAttention); @@ -2152,6 +2206,7 @@ static void atapicommand(int ide_board) if (cdrom->medium_changed()) { + // pclog("Medium has changed...\n"); SCSICDROM_Insert(); } @@ -2240,14 +2295,16 @@ static void atapicommand(int ide_board) idebufferb[13]=SCSISense.Ascq; } } - else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING)) + else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED)) { + // pclog("CD-ROM drive is in audio phase\n"); idebufferb[2]=SENSE_ILLEGAL_REQUEST; idebufferb[12]=ASC_AUDIO_PLAY_OPERATION; idebufferb[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; } else { + // pclog("Returning Unit Attention\n"); if (SCSISense.UnitAttention) { idebufferb[2]=SENSE_UNIT_ATTENTION; @@ -2265,6 +2322,7 @@ static void atapicommand(int ide_board) { /* If the last remaining sense is unit attention, clear that condition. */ + // pclog("Unit attention cleared"); SCSISense.UnitAttention = 0; } @@ -2373,10 +2431,9 @@ static void atapicommand(int ide_board) cdrom_sector_type = (idebufferb[1] >> 2) & 7; cdrom_sector_flags = idebufferb[9] || (((uint32_t) idebufferb[10]) << 8); - ret = cdrom_read_data(ide, idebufferb); - - if (!ret) + if (ide->cdpos > (cdrom->size() - 1)) { + pclog("Trying to read beyond the end of disc\n"); ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) @@ -2387,6 +2444,18 @@ static void atapicommand(int ide_board) ide->packetstatus = ATAPI_STATUS_ERROR; idecallback[ide_board]=50*IDE_TIME; break; + } + + ret = cdrom_read_data(ide, idebufferb); + + if (!ret) + { + ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ + ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; + SCSISense.Asc = ASC_ILLEGAL_OPCODE; + ide->packetstatus = ATAPI_STATUS_ERROR; + idecallback[ide_board]=50*IDE_TIME; + break; // pclog("Bad flags bits %02X\n",idebufferb[9]); // exit(-1); } @@ -2432,6 +2501,21 @@ static void atapicommand(int ide_board) ide->cdpos=(((uint32_t) idebufferb[2])<<24)|(((uint32_t) idebufferb[3])<<16)|(((uint32_t) idebufferb[4])<<8)|((uint32_t) idebufferb[5]); } + if (ide->cdpos > (cdrom->size() - 1)) + { + pclog("Trying to read beyond the end of disc\n"); + ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ + ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + { + ide->error |= MCR_ERR; + } + SCSISense.Asc = ASC_ILLEGAL_OPCODE; + ide->packetstatus = ATAPI_STATUS_ERROR; + idecallback[ide_board]=50*IDE_TIME; + break; + } + if (!ide->cdlen) { // pclog("All done - callback set\n"); @@ -2440,11 +2524,23 @@ static void atapicommand(int ide_board) break; } - cdrom_sector_type = 0; + cdrom_sector_type = 6; cdrom_sector_flags = 0x10; ret = cdrom_read_data(ide, idebufferb); + if (!ret) + { + ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ + ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; + SCSISense.Asc = ASC_ILLEGAL_OPCODE; + ide->packetstatus = ATAPI_STATUS_ERROR; + idecallback[ide_board]=50*IDE_TIME; + break; +// pclog("Bad flags bits %02X\n",idebufferb[9]); +// exit(-1); + } + #ifndef RPCEMU_IDE readflash=1; #endif @@ -2462,23 +2558,31 @@ static void atapicommand(int ide_board) return; case GPCMD_READ_HEADER: - if (msf) - { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.SenseKey = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - break; -// pclog("Read Header MSF!\n"); -// exit(-1); - } - for (c=0;c<4;c++) idebufferb[c+4]=idebufferb[c+2]; - idebufferb[0]=1; /*2048 bytes user data*/ - idebufferb[1]=idebufferb[2]=idebufferb[3]=0; + if (cdrom->read_header) + { + cdrom->read_header(idebufferb, idebufferb); + } + else + { + ide->cdlen=(idebufferb[7]<<8)|idebufferb[8]; + ide->cdpos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; + if (msf) + { + real_pos = cdrom_LBAtoMSF_accurate(ide); + } + else + { + real_pos = ide->cdpos; + } + idebufferb[4] = (real_pos >> 24); + idebufferb[5] = ((real_pos >> 16) & 0xff); + idebufferb[6] = ((real_pos >> 8) & 0xff); + idebufferb[7] = real_pos & 0xff; + idebufferb[0]=1; /*2048 bytes user data*/ + idebufferb[1]=idebufferb[2]=idebufferb[3]=0; + } + len = 8; ide->packetstatus = ATAPI_STATUS_DATA; ide->cylinder=8; ide->secount=2; @@ -2722,14 +2826,21 @@ static void atapicommand(int ide_board) break; case GPCMD_READ_DISC_INFORMATION: - idebufferb[1] = 32; - idebufferb[2] = 0xe; /* last session complete, disc finalized */ - idebufferb[3] = 1; /* first track on disc */ - idebufferb[4] = 1; /* # of sessions */ - idebufferb[5] = 1; /* first track of last session */ - idebufferb[6] = 1; /* last track of last session */ - idebufferb[7] = 0x20; /* unrestricted use */ - idebufferb[8] = 0x00; /* CD-ROM */ + if (cdrom->read_disc_information) + { + cdrom->read_disc_information(idebufferb); + } + else + { + idebufferb[1] = 32; + idebufferb[2] = 0xe; /* last session complete, disc finalized */ + idebufferb[3] = 1; /* first track on disc */ + idebufferb[4] = 1; /* # of sessions */ + idebufferb[5] = 1; /* first track of last session */ + idebufferb[6] = 1; /* last track of last session */ + idebufferb[7] = 0x20; /* unrestricted use */ + idebufferb[8] = 0x00; /* CD-ROM */ + } len=34; ide->packetstatus = ATAPI_STATUS_DATA; @@ -2743,8 +2854,6 @@ static void atapicommand(int ide_board) case GPCMD_PLAY_AUDIO_10: case GPCMD_PLAY_AUDIO_12: case GPCMD_PLAY_AUDIO_MSF: - /*This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it*/ if (idebufferb[0] == GPCMD_PLAY_AUDIO_10) { pos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; @@ -2752,6 +2861,8 @@ static void atapicommand(int ide_board) } else if (idebufferb[0] == GPCMD_PLAY_AUDIO_MSF) { + /*This is apparently deprecated in the ATAPI spec, and apparently + has been since 1995 (!). Hence I'm having to guess most of it*/ pos=(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; len=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8]; } @@ -3019,19 +3130,24 @@ atapi_out: break; case GPCMD_READ_CDROM_CAPACITY: - atapi_command_send_init(ide, temp_command, 8, 8); - size = cdrom->size(); - idebufferb[0] = (size >> 24) & 0xff; - idebufferb[1] = (size >> 16) & 0xff; - idebufferb[2] = (size >> 8) & 0xff; - idebufferb[3] = size & 0xff; - idebufferb[4] = (2048 >> 24) & 0xff; - idebufferb[5] = (2048 >> 16) & 0xff; - idebufferb[6] = (2048 >> 8) & 0xff; - idebufferb[7] = 2048 & 0xff; - len=8; - atapi_command_ready(ide_board, len); - break; + atapi_command_send_init(ide, temp_command, 8, 8); + if (cdrom->read_capacity) + { + cdrom->read_capacity(idebufferb); + } + else + { + size = cdrom->size() - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(idebufferb, 0, 8); + idebufferb[0] = (size >> 24) & 0xff; + idebufferb[1] = (size >> 16) & 0xff; + idebufferb[2] = (size >> 8) & 0xff; + idebufferb[3] = size & 0xff; + idebufferb[6] = 8; /* 2048 = 0x0800 */ + } + len=8; + atapi_command_ready(ide_board, len); + break; case GPCMD_SEND_DVD_STRUCTURE: default: diff --git a/src/ide.h b/src/ide.h index d478ab946..bae43ae64 100644 --- a/src/ide.h +++ b/src/ide.h @@ -26,7 +26,7 @@ extern int ideboard; extern int idecallback[3]; -extern char ide_fn[4][512]; +extern char ide_fn[6][512]; extern int atapi_cdrom_channel; diff --git a/src/intel.c b/src/intel.c index e7fecfbc8..9d305df2b 100644 --- a/src/intel.c +++ b/src/intel.c @@ -67,6 +67,7 @@ void intel_batman_init() } +#if 0 uint8_t endeavor_brdconfig(uint16_t port, void *p) { // pclog("endeavor_brdconfig read port=%04x\n", port); @@ -82,3 +83,4 @@ void intel_endeavor_init() { io_sethandler(0x0079, 0x0001, endeavor_brdconfig, NULL, NULL, NULL, NULL, NULL, NULL); } +#endif diff --git a/src/intel_flash.c b/src/intel_flash.c index 79a6ecc31..d27835870 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -176,6 +176,12 @@ void *intel_flash_init(uint8_t type) case ROM_MB500N: strcpy(flash_path, "roms/mb500n/"); break; + case ROM_POWERMATE_V: + strcpy(flash_path, "roms/powermate_v/"); + break; + case ROM_P54TP4XE: + strcpy(flash_path, "roms/p54tp4xe/"); + break; case ROM_ACERM3A: strcpy(flash_path, "roms/acerm3a/"); break; @@ -188,6 +194,12 @@ void *intel_flash_init(uint8_t type) case ROM_P55VA: strcpy(flash_path, "roms/p55va/"); break; + case ROM_P55T2P4: + strcpy(flash_path, "roms/p55t2p4/"); + break; + case ROM_P55TVP4: + strcpy(flash_path, "roms/p55tvp4/"); + break; case ROM_440FX: strcpy(flash_path, "roms/440fx/"); break; @@ -197,6 +209,9 @@ void *intel_flash_init(uint8_t type) case ROM_THOR: strcpy(flash_path, "roms/thor/"); break; + case ROM_MRTHOR: + strcpy(flash_path, "roms/mrthor/"); + break; default: fatal("intel_flash_init on unsupported ROM set %i\n", romset); } diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 0d3d2f6f2..a86e4d73e 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -55,6 +55,9 @@ struct int key_wantdata; int last_irq; + + void (*mouse_write)(uint8_t val, void *p); + void *mouse_p; } keyboard_at; static uint8_t key_ctrl_queue[16]; @@ -304,8 +307,8 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) break; case 0xd4: /*Write to mouse*/ - if (mouse_write) - mouse_write(val); + if (keyboard_at.mouse_write) + keyboard_at.mouse_write(val, keyboard_at.mouse_p); break; default: @@ -587,6 +590,7 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) case 0xfe: /*Pulse output port - pin 0 selected - x86 reset*/ softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); break; case 0xff: /*Pulse output port - but no pins selected - sent by MegaPC BIOS*/ @@ -611,6 +615,12 @@ uint8_t keyboard_at_read(uint16_t port, void *priv) temp = keyboard_at.out; keyboard_at.status &= ~(STAT_OFULL/* | STAT_MFULL*/); picintc(keyboard_at.last_irq); + if (PCI) + { + /* The PIIX/PIIX3 datasheet mandates that both of these interrupts are cleared on any read of port 0x60. */ + picintc(1 << 1); + picintc(1 << 12); + } keyboard_at.last_irq = 0; break; @@ -657,8 +667,15 @@ void keyboard_at_init() keyboard_at_reset(); keyboard_send = keyboard_at_adddata_keyboard; keyboard_poll = keyboard_at_poll; - mouse_write = NULL; + keyboard_at.mouse_write = NULL; + keyboard_at.mouse_p = NULL; dtrans = 0; timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); } + +void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p) +{ + keyboard_at.mouse_write = mouse_write; + keyboard_at.mouse_p = p; +} diff --git a/src/keyboard_at.h b/src/keyboard_at.h index 957c20562..5f0d758ee 100644 --- a/src/keyboard_at.h +++ b/src/keyboard_at.h @@ -5,7 +5,7 @@ void keyboard_at_init(); void keyboard_at_reset(); void keyboard_at_poll(); void keyboard_at_adddata_keyboard_raw(uint8_t val); +void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p); -void (*mouse_write)(uint8_t val); extern int mouse_queue_start, mouse_queue_end; extern int mouse_scan; diff --git a/src/keyboard_olim24.c b/src/keyboard_olim24.c index 95f022d85..79eff4217 100644 --- a/src/keyboard_olim24.c +++ b/src/keyboard_olim24.c @@ -1,8 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include - #include "ibm.h" #include "io.h" #include "mem.h" @@ -152,7 +147,7 @@ void keyboard_olim24_write(uint16_t port, uint8_t val, void *priv) timer_process(); timer_update_outstanding(); - speaker_update(); + speaker_update(); speaker_gated = val & 1; speaker_enable = val & 2; if (speaker_enable) @@ -221,85 +216,124 @@ void keyboard_olim24_reset() mouse_scancodes[6] = 0x50; } -static int mouse_x = 0, mouse_y = 0, mouse_b = 0; -void mouse_olim24_poll(int x, int y, int b) +typedef struct mouse_olim24_t { - mouse_x += x; - mouse_y += y; + int x, y, b; +} mouse_olim24_t; - pclog("mouse_poll - %i, %i %i, %i\n", x, y, mouse_x, mouse_y); +void mouse_olim24_poll(int x, int y, int z, int b, void *p) +{ + mouse_olim24_t *mouse = (mouse_olim24_t *)p; - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - if ((b & 1) && !(mouse_b & 1)) - keyboard_olim24_adddata(mouse_scancodes[0]); - if (!(b & 1) && (mouse_b & 1)) - keyboard_olim24_adddata(mouse_scancodes[0] | 0x80); - mouse_b = (mouse_b & ~1) | (b & 1); + mouse->x += x; + mouse->y += y; + +// pclog("mouse_poll - %i, %i %i, %i\n", x, y, mouse->x, mouse->y); - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - if ((b & 2) && !(mouse_b & 2)) - keyboard_olim24_adddata(mouse_scancodes[2]); - if (!(b & 2) && (mouse_b & 2)) - keyboard_olim24_adddata(mouse_scancodes[2] | 0x80); - mouse_b = (mouse_b & ~2) | (b & 2); + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + if ((b & 1) && !(mouse->b & 1)) + keyboard_olim24_adddata(mouse_scancodes[0]); + if (!(b & 1) && (mouse->b & 1)) + keyboard_olim24_adddata(mouse_scancodes[0] | 0x80); + mouse->b = (mouse->b & ~1) | (b & 1); - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - if ((b & 4) && !(mouse_b & 4)) - keyboard_olim24_adddata(mouse_scancodes[1]); - if (!(b & 4) && (mouse_b & 4)) - keyboard_olim24_adddata(mouse_scancodes[1] | 0x80); - mouse_b = (mouse_b & ~4) | (b & 4); + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + if ((b & 2) && !(mouse->b & 2)) + keyboard_olim24_adddata(mouse_scancodes[2]); + if (!(b & 2) && (mouse->b & 2)) + keyboard_olim24_adddata(mouse_scancodes[2] | 0x80); + mouse->b = (mouse->b & ~2) | (b & 2); + + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + if ((b & 4) && !(mouse->b & 4)) + keyboard_olim24_adddata(mouse_scancodes[1]); + if (!(b & 4) && (mouse->b & 4)) + keyboard_olim24_adddata(mouse_scancodes[1] | 0x80); + mouse->b = (mouse->b & ~4) | (b & 4); if (keyboard_olim24.mouse_mode) { - if (((key_queue_end - key_queue_start) & 0xf) > 12) return; - if (!mouse_x && !mouse_y) return; + if (((key_queue_end - key_queue_start) & 0xf) > 12) + return; + if (!mouse->x && !mouse->y) + return; - mouse_y = -mouse_y; + mouse->y = -mouse->y; - if (mouse_x < -127) mouse_x = -127; - if (mouse_x > 127) mouse_x = 127; - if (mouse_x < -127) mouse_x = 0x80 | ((-mouse_x) & 0x7f); + if (mouse->x < -127) mouse->x = -127; + if (mouse->x > 127) mouse->x = 127; + if (mouse->x < -127) mouse->x = 0x80 | ((-mouse->x) & 0x7f); - if (mouse_y < -127) mouse_y = -127; - if (mouse_y > 127) mouse_y = 127; - if (mouse_y < -127) mouse_y = 0x80 | ((-mouse_y) & 0x7f); + if (mouse->y < -127) mouse->y = -127; + if (mouse->y > 127) mouse->y = 127; + if (mouse->y < -127) mouse->y = 0x80 | ((-mouse->y) & 0x7f); keyboard_olim24_adddata(0xfe); - keyboard_olim24_adddata(mouse_x); - keyboard_olim24_adddata(mouse_y); + keyboard_olim24_adddata(mouse->x); + keyboard_olim24_adddata(mouse->y); - mouse_x = mouse_y = 0; + mouse->x = mouse->y = 0; } else { - while (mouse_x < -4) + while (mouse->x < -4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - mouse_x+=4; + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + mouse->x += 4; keyboard_olim24_adddata(mouse_scancodes[3]); } - while (mouse_x > 4) + while (mouse->x > 4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - mouse_x-=4; + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + mouse->x -= 4; keyboard_olim24_adddata(mouse_scancodes[4]); } - while (mouse_y < -4) + while (mouse->y < -4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - mouse_y+=4; + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + mouse->y += 4; keyboard_olim24_adddata(mouse_scancodes[5]); } - while (mouse_y > 4) + while (mouse->y > 4) { - if (((key_queue_end - key_queue_start) & 0xf) > 14) return; - mouse_y-=4; + if (((key_queue_end - key_queue_start) & 0xf) > 14) + return; + mouse->y -= 4; keyboard_olim24_adddata(mouse_scancodes[6]); } } } +static void *mouse_olim24_init() +{ + mouse_olim24_t *mouse = (mouse_olim24_t *)malloc(sizeof(mouse_olim24_t)); + memset(mouse, 0, sizeof(mouse_olim24_t)); + + return mouse; +} + +static void mouse_olim24_close(void *p) +{ + mouse_olim24_t *mouse = (mouse_olim24_t *)p; + + free(mouse); +} + +mouse_t mouse_olim24 = +{ + "Olivetti M24 mouse", + mouse_olim24_init, + mouse_olim24_close, + mouse_olim24_poll, + MOUSE_TYPE_OLIM24 +}; + void keyboard_olim24_init() { //return; @@ -308,7 +342,6 @@ void keyboard_olim24_init() keyboard_olim24_reset(); keyboard_send = keyboard_olim24_adddata; keyboard_poll = keyboard_olim24_poll; - mouse_poll = mouse_olim24_poll; timer_add(keyboard_olim24_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL); } diff --git a/src/keyboard_olim24.h b/src/keyboard_olim24.h index 4151c1160..5ea3af04f 100644 --- a/src/keyboard_olim24.h +++ b/src/keyboard_olim24.h @@ -1,6 +1,5 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ void keyboard_olim24_init(); void keyboard_olim24_reset(); void keyboard_olim24_poll(); + +extern mouse_t mouse_olim24; diff --git a/src/mem.c b/src/mem.c index d83ed8386..d0d5e4fe6 100644 --- a/src/mem.c +++ b/src/mem.c @@ -53,12 +53,11 @@ static unsigned char isram[0x10000]; static uint8_t ff_array[0x1000]; int mem_size; -int cache=4; uint32_t biosmask; int readlnum=0,writelnum=0; int cachesize=256; -uint8_t *ram,*rom,*vram; +uint8_t *ram,*rom; uint8_t romext[32768]; static void mem_load_xtide_bios() @@ -109,9 +108,10 @@ int loadbios() int c; loadfont("roms/mda.rom", 0); - + loadfont("roms/wy700.rom", 3); + biosmask = 0xffff; - + memset(romext,0xff,0x8000); memset(rom, 0xff, 0x20000); @@ -344,7 +344,7 @@ int loadbios() fread(rom,65536,1,f); fclose(f); return 1;*/ - case ROM_AMI386: /*This uses the OPTi 82C495 chipset*/ + case ROM_AMI386SX: // f=romfopen("roms/at386/at386.bin","rb"); f=romfopen("roms/ami386/ami386.bin","rb"); if (!f) break; @@ -352,6 +352,18 @@ int loadbios() fclose(f); return 1; + case ROM_AMI386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ + f=romfopen("roms/ami386dx/OPT495SX.AMI","rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; + case ROM_MR386DX_OPTI495: /*This uses the OPTi 82C495 chipset*/ + f=romfopen("roms/mr386dx/OPT495SX.MR","rb"); + if (!f) break; + fread(rom,65536,1,f); + fclose(f); + return 1; case ROM_ACER386: f=romfopen("roms/acer386/acer386.bin","rb"); @@ -665,6 +677,24 @@ int loadbios() biosmask = 0x1ffff; return 1; +#if 0 + case ROM_POWERMATE_V: + f = romfopen("roms/powermate_v/BIOS.ROM", "rb"); /* Works */ + if (!f) break; + fread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; +#endif + + case ROM_P54TP4XE: + f = romfopen("roms/p54tp4xe/T15I0302.AWD", "rb"); + if (!f) break; + fread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; + case ROM_ACERM3A: f = romfopen("roms/acerm3a/r01-b3.bin", "rb"); if (!f) break; @@ -689,6 +719,22 @@ int loadbios() biosmask = 0x1ffff; return 1; + case ROM_P55T2P4: + f = romfopen("roms/p55t2p4/0207_J2.BIN", "rb"); + if (!f) break; + fread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; + + case ROM_P55TVP4: + f = romfopen("roms/p55tvp4/TV5I0204.AWD", "rb"); + if (!f) break; + fread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; + case ROM_440FX: f = romfopen("roms/440fx/NTMAW501.BIN", "rb"); /* Working Tyan BIOS. */ if (!f) break; @@ -726,6 +772,14 @@ int loadbios() biosmask = 0x1ffff; //is486=1; return 1; + + case ROM_MRTHOR: + f = romfopen("roms/mrthor/MR_ATX.BIO", "rb"); + if (!f) break; + fread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); @@ -991,13 +1045,6 @@ void mmu_invalidate(uint32_t addr) flushmmucache_cr3(); } -int memspeed[11]={256,320,384,512,640,768,1024,1152,1280,1536,1920}; -int memwaitstate; - -static int cachelookup[256]; -static uint8_t *cachelookup2; -static int cachelnext; - void addreadlookup(uint32_t virt, uint32_t phys) { // return; @@ -1017,17 +1064,6 @@ void addreadlookup(uint32_t virt, uint32_t phys) } - if (!cachelookup2[phys >> 12]) - { - readlnum++; - cycles-=memwaitstate; - if (cachelookup[cachelnext] != 0xffffffff) - cachelookup2[cachelookup[cachelnext]] = 0; - cachelookup[cachelnext] = phys >> 12; - cachelookup2[phys >> 12] = 1; - cachelnext = (cachelnext + 1) & (cachesize - 1); - } - if (readlookup[readlnext]!=0xFFFFFFFF) { readlookup2[readlookup[readlnext]] = -1; @@ -1059,18 +1095,6 @@ void addwritelookup(uint32_t virt, uint32_t phys) return; } - if (!cachelookup2[phys >> 12]) - { - writelnum++; - cycles-=memwaitstate; - if (cachelookup[cachelnext] != 0xffffffff) - cachelookup2[cachelookup[cachelnext]] = 0; - cachelookup[cachelnext] = phys >> 12; - cachelookup2[phys >> 12] = 1; - cachelnext = (cachelnext + 1) & (cachesize - 1); - } - - cycles-=memwaitstate; if (writelookup[writelnext] != -1) { page_lookup[writelookup[writelnext]] = NULL; @@ -1662,29 +1686,6 @@ void mem_write_nulll(uint32_t addr, uint32_t val, void *p) { } -void mem_updatecache() -{ - flushmmucache(); - if (!is386 || israpidcad) - { - cachesize=256; - memwaitstate=0; - return; - } - if (cpu_16bitbus) - memwaitstate = 512 * ((cpu_multi >= 2) ? 2 : cpu_multi); - else - memwaitstate = 384 * ((cpu_multi >= 2) ? 2 : cpu_multi); //memspeed[cpuspeed]; - switch (cache) - { - case 0: cachesize=32; break; - case 1: cachesize=64; break; - case 2: cachesize=128; break; - case 3: cachesize=256; break; - case 4: cachesize=256; memwaitstate=0; break; - } -} - void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { start_addr &= ~PAGE_MASK_MASK; @@ -1937,10 +1938,8 @@ void mem_init() ram = malloc((mem_size + 384) * 1024); rom = malloc(0x20000); - vram = malloc(0x800000); readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t)); - cachelookup2 = malloc(1024 * 1024); biosmask = 0xffff; pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t)); page_lookup = malloc((1 << 20) * sizeof(page_t *)); @@ -1988,7 +1987,7 @@ void mem_init() if (mem_size > 1024) mem_mapping_add(&ram_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); // pclog("Mem resize %i %i\n",mem_size,c); @@ -2064,7 +2063,7 @@ void mem_resize() if (mem_size > 1024) mem_mapping_add(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); @@ -2087,6 +2086,30 @@ void mem_reset_page_blocks() } } +void mem_reset() +{ + int c; + + mem_reset_page_blocks(); + + memset(isram, 0, sizeof(isram)); + for (c = 0; c < (mem_size / 256); c++) + { + isram[c] = 1; + if (c >= 0xa && c <= 0xf) + isram[c] = 0; + } + + mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(0x100000, (mem_size - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + + mem_a20_key = 2; + mem_a20_recalc(); +} + +static int port_92_reg = 0; + void mem_a20_recalc() { int state = mem_a20_key | mem_a20_alt; @@ -2105,4 +2128,47 @@ void mem_a20_recalc() mem_a20_state = state; } +static uint8_t port_92_read(uint16_t port, void *priv) +{ + return (port_92_reg & 3) | 0x24; +} + +static void port_92_write(uint16_t port, uint8_t val, void *priv) +{ + mem_a20_alt = val & 2; + mem_a20_recalc(); + + if (!(port_92_reg & 1) && (val & 1)) + { + // pclog("Port 92: Soft reset\n"); + softresetx86(); + } + + port_92_reg = val & 3; + + mem_a20_recalc(); +} + +void port_92_clear_reset() +{ + port_92_reg &= 2; +} + +void port_92_add() +{ + io_sethandler(0x0092, 0x0001, port_92_read, NULL, NULL, port_92_write, NULL, NULL, NULL); +} + +void port_92_remove() +{ + io_removehandler(0x0092, 0x0001, port_92_read, NULL, NULL, port_92_write, NULL, NULL, NULL); +} + +void port_92_reset() +{ + port_92_reg = 0; + mem_a20_alt = 0; + mem_a20_recalc(); +} + uint32_t get_phys_virt,get_phys_phys; diff --git a/src/mem.h b/src/mem.h index ee4bd527d..ada252529 100644 --- a/src/mem.h +++ b/src/mem.h @@ -37,8 +37,7 @@ extern uint8_t romext[32768]; extern int readlnum,writelnum; extern int memspeed[11]; extern int nopageerrors; -extern int cache; -extern int memwaitstate; +extern uint32_t biosmask; void mem_mapping_add(mem_mapping_t *mapping, uint32_t base, diff --git a/src/model.c b/src/model.c index 4c4955214..db7607cef 100644 --- a/src/model.c +++ b/src/model.c @@ -5,6 +5,7 @@ #include "cpu.h" #include "mem.h" #include "model.h" +#include "mouse.h" #include "io.h" #include "rom.h" @@ -38,13 +39,11 @@ #include "keyboard_xt.h" #include "lpt.h" #include "memregs.h" -#include "mouse_amstrad.h" -#include "mouse_ps2.h" -#include "mouse_serial.h" #include "neat.h" #include "nmi.h" #include "nvr.h" #include "olivetti_m24.h" +#include "opti495.h" #include "pc87306.h" #include "pci.h" #include "pic.h" @@ -63,6 +62,8 @@ #include "tandy_rom.h" #include "um8669f.h" // #include "um8881f.h" +#include "vid_pcjr.h" +#include "vid_tandy.h" #include "w83877f.h" #include "wd76c10.h" #include "xtide.h" @@ -84,6 +85,7 @@ void at_acer386sx_init(); void at_wd76c10_init(); void at_ali1429_init(); void at_headland_init(); +void at_opti495_init(); // void at_um8881f_init(); void at_sis496_init(); void at_i430vx_init(); @@ -95,11 +97,14 @@ void at_r418_init(); void at_586mc1_init(); void at_plato_init(); void at_mb500n_init(); -// void at_p54tp4xe_init(); +#if 0 +void at_powermate_v_init(); +#endif +void at_p54tp4xe_init(); void at_acerm3a_init(); void at_acerv35n_init(); -// void at_p55t2p4_init(); -// void at_p55tvp4_init(); +void at_p55t2p4_init(); +void at_p55tvp4_init(); void at_marl_init(); void at_p55va_init(); void at_i440fx_init(); @@ -108,65 +113,69 @@ int model; int AMSTRAD, AT, PCI, TANDY; -int mouse_always_serial; - MODEL models[] = { - {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init}, - {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"IBM PCjr", ROM_IBMPCJR, { "", cpus_pcjr, "", NULL, "", NULL}, 1, 0, 128, 640, 128, pcjr_init}, - {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"AMI XT clone", ROM_AMIXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"VTech Laser Turbo XT",ROM_LTXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"VTech Laser XT3", ROM_LXT3, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"Phoenix XT clone", ROM_PXXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"Juko XT clone", ROM_JUKOPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init}, - {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, 0, 128, 640, 128, tandy1k_init}, - {"Tandy 1000 HX", ROM_TANDY1000HX, { "", cpus_8088, "", NULL, "", NULL}, 1, 0, 256, 640, 128, tandy1k_init}, - {"Tandy 1000 SL/2", ROM_TANDY1000SL2,{ "", cpus_8086, "", NULL, "", NULL}, 1, 0, 512, 768, 128, tandy1ksl2_init}, - {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512, "", NULL, "", NULL}, 1, 0, 512, 640, 128, ams_init}, - {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, 0, 512, 640, 128, ams_init}, - {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, 0, 512, 640, 128, europc_init}, - {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, 0, 128, 640, 128, olim24_init}, - {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, 0, 640, 640, 0, ams_init}, - {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, 0, 640, 640, 0, ams_init}, - {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, 0, 640, 640, 0, ams_init}, - {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_init}, - {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_init}, - {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_neat_init}, - {"Award 286 clone", ROM_AWARD286, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_scat_init}, - {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, 1, 1, 16, 1, at_init}, - {"IBM PS/1 model 2011", ROM_IBMPS1_2011, { "", cpus_ps1_m2011,"", NULL, "", NULL}, 1, 1, 1, 16, 1, ps1_m2011_init}, - {"IBM PS/1 model 2121", ROM_IBMPS1_2121, { "Intel", cpus_i386, "", NULL, "", NULL}, 1, 1, 1, 16, 1, ps1_m2121_init}, - {"Compaq Deskpro 386", ROM_DESKPRO_386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 15, 1, deskpro386_init}, - {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, 1, 1, 16, 1, at_acer386sx_init}, - {"DTK 386SX clone", ROM_DTK386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 16, 1, at_neat_init}, - {"Phoenix 386 clone", ROM_PX386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 16, 1, at_init}, - {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, 1, 1, 16, 1, at_wd76c10_init}, - {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, 1, 1, 256, 1, at_headland_init}, - {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_ali1429_init}, - {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_ali1429_init}, -/* {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_um8881f_init},*/ - {"DTK PKM-0038S E-2", ROM_DTK486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_dtk486_init}, - {"Award SiS 496/497", ROM_SIS496, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_sis496_init}, - {"Rise Computer R418", ROM_R418, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, 1, 1, 256, 1, at_r418_init}, - {"Intel Premiere/PCI", ROM_REVENGE, { "Intel", cpus_Pentium5V, "", NULL, "", NULL}, 0, 1, 1, 128, 1, at_batman_init}, - {"Micro Star 586MC1", ROM_586MC1, { "Intel", cpus_Pentium5V50, "",NULL, "", NULL}, 0, 1, 1, 128, 1, at_586mc1_init}, - {"Intel Premiere/PCI II",ROM_PLATO, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 128, 1, at_plato_init}, - {"Intel Advanced/EV", ROM_ENDEAVOR, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 128, 1, at_endeavor_init}, - {"PC Partner MB500N", ROM_MB500N, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 128, 1, at_mb500n_init}, - {"Intel Advanced/ATX", ROM_THOR, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_endeavor_init}, - // {"ASUS P/I-P54TP4XE", ROM_P54TP4XE, { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 512, 1, at_p54tp4xe_init}, - // {"Intel Advanced/ML", ROM_MARL, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_marl_init}, - {"Acer M3a", ROM_ACERM3A, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_acerm3a_init}, - {"Acer V35N", ROM_ACERV35N, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_acerv35n_init}, - // {"ASUS P/I-P55T2P4", ROM_P55T2P4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_p55t2p4_init}, - {"Award 430VX PCI", ROM_430VX, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_i430vx_init}, - {"Epox P55-VA", ROM_P55VA, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55va_init}, -/* {"ASUS P/I-P55TVP4", ROM_P55TVP4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55tvp4_init}, */ - {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro, "", NULL, "", NULL}, 0, 1, 1, 1024, 1, at_i440fx_init}, - // {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro,"Klamath", cpus_Pentium2, "Deschutes", cpus_Pentium2D}, 0, 1, 1, 1024, 1, at_i440fx_init}, + {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 64, 640, 64, xt_init, NULL}, + {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"IBM PCjr", ROM_IBMPCJR, { "", cpus_pcjr, "", NULL, "", NULL}, 1, 0, 128, 640, 128, pcjr_init, &pcjr_device}, + {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"AMI XT clone", ROM_AMIXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"VTech Laser Turbo XT",ROM_LTXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"VTech Laser XT3", ROM_LXT3, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"Phoenix XT clone", ROM_PXXT, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"Juko XT clone", ROM_JUKOPC, { "", cpus_8088, "", NULL, "", NULL}, 0, 0, 128, 640, 64, xt_init, NULL}, + {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, 0, 128, 640, 128, tandy1k_init, &tandy1000_device}, + {"Tandy 1000 HX", ROM_TANDY1000HX, { "", cpus_8088, "", NULL, "", NULL}, 1, 0, 256, 640, 128, tandy1k_init, &tandy1000hx_device}, + {"Tandy 1000 SL/2", ROM_TANDY1000SL2,{ "", cpus_8086, "", NULL, "", NULL}, 1, 0, 512, 768, 128, tandy1ksl2_init, NULL}, + {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512, "", NULL, "", NULL}, 1, MODEL_AMSTRAD, 512, 640, 128, ams_init, NULL}, + {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, MODEL_AMSTRAD, 512, 640, 128, ams_init, NULL}, + {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, 0, 512, 640, 128, europc_init, NULL}, + {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, MODEL_OLIM24, 128, 640, 128, olim24_init, NULL}, + {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, MODEL_AMSTRAD, 640, 640, 0, ams_init, NULL}, + {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, MODEL_AMSTRAD, 640, 640, 0, ams_init, NULL}, + {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, MODEL_AMSTRAD, 640, 640, 0, ams_init, NULL}, + {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, MODEL_AT, 1, 16, 1, at_init, NULL}, + {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, MODEL_AT, 1, 16, 1, at_init, NULL}, + {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, MODEL_AT, 1, 16, 1, at_neat_init, NULL}, + {"Award 286 clone", ROM_AWARD286, { "", cpus_286, "", NULL, "", NULL}, 0, MODEL_AT, 1, 16, 1, at_scat_init, NULL}, + {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, MODEL_AT, 1, 16, 1, at_init, NULL}, + {"IBM PS/1 model 2011", ROM_IBMPS1_2011, { "", cpus_ps1_m2011,"", NULL, "", NULL}, 1, MODEL_AT|MODEL_PS2, 1, 16, 1, ps1_m2011_init, NULL}, + {"IBM PS/1 model 2121", ROM_IBMPS1_2121, { "Intel", cpus_i386, "", NULL, "", NULL}, 1, MODEL_AT|MODEL_PS2, 1, 16, 1, ps1_m2121_init, NULL}, + {"Compaq Deskpro 386", ROM_DESKPRO_386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, MODEL_AT, 1, 15, 1, deskpro386_init, NULL}, + {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, MODEL_AT|MODEL_PS2, 1, 16, 1, at_acer386sx_init, NULL}, + {"DTK 386SX clone", ROM_DTK386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, MODEL_AT, 1, 16, 1, at_neat_init, NULL}, + {"Phoenix 386 clone", ROM_PX386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, MODEL_AT, 1, 16, 1, at_init, NULL}, + {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, MODEL_AT|MODEL_PS2, 1, 16, 1, at_wd76c10_init, NULL}, + {"AMI 386SX clone", ROM_AMI386SX, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, MODEL_AT, 1, 256, 1, at_headland_init, NULL}, + {"MR 386DX clone", ROM_MR386DX_OPTI495, { "Intel", cpus_i386DX, "AMD", cpus_Am386DX, "Cyrix", cpus_486DLC}, 0, MODEL_AT, 1, 256, 1, at_opti495_init, NULL}, + {"AMI 386DX clone", ROM_AMI386DX_OPTI495, { "Intel", cpus_i386DX, "AMD", cpus_Am386DX, "Cyrix", cpus_486DLC}, 0, MODEL_AT, 1, 256, 1, at_opti495_init, NULL}, + {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, MODEL_AT, 1, 256, 1, at_ali1429_init, NULL}, + {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, MODEL_AT, 1, 256, 1, at_ali1429_init, NULL}, +/* {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, MODEL_AT, 1, 256, 1, at_um8881f_init, NULL},*/ + {"DTK PKM-0038S E-2", ROM_DTK486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, MODEL_AT, 1, 256, 1, at_dtk486_init, NULL}, + {"Award SiS 496/497", ROM_SIS496, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, MODEL_AT, 1, 256, 1, at_sis496_init, NULL}, + {"Rise Computer R418", ROM_R418, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, MODEL_AT, 1, 256, 1, at_r418_init, NULL}, + {"Intel Premiere/PCI", ROM_REVENGE, { "Intel", cpus_Pentium5V, "", NULL, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 128, 1, at_batman_init, NULL}, + {"Micro Star 586MC1", ROM_586MC1, { "Intel", cpus_Pentium5V50, "",NULL, "", NULL}, 0, MODEL_AT, 1, 128, 1, at_586mc1_init, NULL}, + {"Intel Premiere/PCI II",ROM_PLATO, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 128, 1, at_plato_init, NULL}, + {"Intel Advanced/EV", ROM_ENDEAVOR, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 128, 1, at_endeavor_init, NULL}, + {"PC Partner MB500N", ROM_MB500N, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 128, 1, at_mb500n_init, NULL}, +#if 0 + {"NEC PowerMate V", ROM_POWERMATE_V, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 128, 1, at_powermate_v_init, NULL}, +#endif + {"Intel Advanced/ATX", ROM_THOR, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 256, 1, at_endeavor_init, NULL}, + {"MR Intel Advanced/ATX", ROM_MRTHOR, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 256, 1, at_endeavor_init, NULL}, + {"ASUS P/I-P54TP4XE", ROM_P54TP4XE, { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 512, 1, at_p54tp4xe_init, NULL}, + // {"Intel Advanced/ML", ROM_MARL, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 512, 1, at_marl_init, NULL}, + {"Acer M3a", ROM_ACERM3A, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 512, 1, at_acerm3a_init, NULL}, + {"Acer V35N", ROM_ACERV35N, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 512, 1, at_acerv35n_init, NULL}, + {"ASUS P/I-P55T2P4", ROM_P55T2P4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 512, 1, at_p55t2p4_init, NULL}, + {"Award 430VX PCI", ROM_430VX, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 256, 1, at_i430vx_init, NULL}, + {"Epox P55-VA", ROM_P55VA, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 256, 1, at_p55va_init, NULL}, + {"ASUS P/I-P55TVP4", ROM_P55TVP4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 256, 1, at_p55tvp4_init, NULL}, + {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro, "", NULL, "", NULL}, 0, MODEL_AT|MODEL_PS2, 1, 1024, 1, at_i440fx_init, NULL}, + // {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro,"Klamath", cpus_Pentium2, "Deschutes", cpus_Pentium2D}, 0, MODEL_AT|MODEL_PS2, 1, 1024, 1, at_i440fx_init, NULL}, {"", -1, {"", 0, "", 0, "", 0}, 0,0,0, 0} }; @@ -199,6 +208,12 @@ char *model_getname() return models[model].name; } + +device_t *model_getdevice(int model) +{ + return models[model].device; +} + void common_init() { dma_init(); @@ -216,7 +231,6 @@ void xt_init() mem_add_bios(); pit_set_out_func(1, pit_refresh_timer_xt); keyboard_xt_init(); - mouse_serial_init(); xtide_init(); nmi_init(); if (joystick_type != 7) device_add(&gameport_device); @@ -241,7 +255,6 @@ void tandy1k_init() common_init(); mem_add_bios(); keyboard_tandy_init(); - mouse_serial_init(); if (romset == ROM_TANDY) device_add(&sn76489_device); else @@ -258,7 +271,6 @@ void tandy1ksl2_init() common_init(); mem_add_bios(); keyboard_tandy_init(); - mouse_serial_init(); device_add(&pssj_device); xtide_init(); nmi_init(); @@ -274,7 +286,6 @@ void ams_init() mem_add_bios(); amstrad_init(); keyboard_amstrad_init(); - mouse_amstrad_init(); nvr_init(); xtide_init(); nmi_init(); @@ -288,7 +299,6 @@ void europc_init() mem_add_bios(); jim_init(); keyboard_xt_init(); - mouse_serial_init(); xtide_init(); nmi_init(); if (joystick_type != 7) device_add(&gameport_device); @@ -299,7 +309,6 @@ void olim24_init() common_init(); mem_add_bios(); keyboard_olim24_init(); - mouse_serial_init(); nvr_init(); olivetti_m24_init(); xtide_init(); @@ -317,8 +326,6 @@ void at_init() dma16_init(); ide_init(); keyboard_at_init(); - if (models[model].init == at_init) - mouse_serial_init(); nvr_init(); pic2_init(); if (joystick_type != 7) device_add(&gameport_device); @@ -327,7 +334,6 @@ void at_init() void deskpro386_init() { at_init(); - mouse_serial_init(); compaq_init(); } @@ -340,7 +346,6 @@ void ps1_common_init() dma16_init(); ide_init(); keyboard_at_init(); - mouse_ps2_init(); nvr_init(); pic2_init(); fdc_set_dskchg_activelow(); @@ -365,28 +370,24 @@ void ps1_m2121_init() void at_neat_init() { at_init(); - mouse_serial_init(); neat_init(); } void at_scat_init() { at_init(); - mouse_serial_init(); scat_init(); } void at_acer386sx_init() { at_init(); - mouse_ps2_init(); acer386sx_init(); } void at_wd76c10_init() { at_init(); - mouse_ps2_init(); wd76c10_init(); } @@ -394,21 +395,24 @@ void at_headland_init() { at_init(); headland_init(); - mouse_serial_init(); +} + +void at_opti495_init() +{ + at_init(); + opti495_init(); } void at_ali1429_init() { at_init(); ali1429_init(); - mouse_serial_init(); if (atapi_cdrom_channel <= 1) ide_sec_disable(); } /* void at_um8881f_init() { at_init(); - mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); um8881f_init(); } */ @@ -417,7 +421,6 @@ void at_dtk486_init() { at_init(); memregs_init(); - mouse_serial_init(); sis85c471_init(); if (atapi_cdrom_channel <= 1) ide_sec_disable(); } @@ -426,7 +429,6 @@ void at_sis496_init() { at_init(); memregs_init(); - mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); device_add(&sis496_device); if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); @@ -434,33 +436,32 @@ void at_sis496_init() void at_r418_init() { - at_init(); - memregs_init(); - mouse_serial_init(); - pci_init(PCI_CONFIG_TYPE_1, 0, 31); + at_sis496_init(); fdc37c665_init(); - device_add(&sis496_device); - if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } -void at_batman_init() +void at_premiere_common_init() { at_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); + memregs_init(); pci_init(PCI_CONFIG_TYPE_2, 0xd, 0x10); - i430lx_init(); - sio_init(1); + sio_init(1); fdc37c665_init(); intel_batman_init(); device_add(&intel_flash_bxt_ami_device); if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } +void at_batman_init() +{ + at_premiere_common_init(); + i430lx_init(); +} + void at_586mc1_init() { at_init(); memregs_init(); - mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_2, 0xd, 0x10); i430lx_init(); sio_init(1); @@ -470,27 +471,18 @@ void at_586mc1_init() void at_plato_init() { - at_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); - pci_init(PCI_CONFIG_TYPE_2, 0xd, 0x10); + at_premiere_common_init(); i430nx_init(); - sio_init(1); - fdc37c665_init(); - /* It seems it uses the same interface as Batman. */ - intel_batman_init(); - device_add(&intel_flash_bxt_ami_device); - if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } void at_advanced_common_init() { at_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); + memregs_init(); pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); i430fx_init(); piix_init(7); - // pc87306_init(); - intel_endeavor_init(); + pc87306_init(); if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } @@ -511,37 +503,45 @@ void at_marl_init() void at_mb500n_init() { at_init(); - mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); i430fx_init(); piix_init(7); fdc37c665_init(); - intel_endeavor_init(); device_add(&intel_flash_bxt_device); if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } #if 0 -void at_p54tp4xe_init() +void at_powermate_v_init() { at_init(); memregs_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); - pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); + pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430fx_init(); piix_init(7); fdc37c665_init(); - intel_endeavor_init(); + acerm3a_io_init(); device_add(&intel_flash_bxt_device); if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } #endif +void at_p54tp4xe_init() +{ + at_init(); + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); + i430fx_init(); + piix_init(7); + fdc37c665_init(); + device_add(&intel_flash_bxt_device); + if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); +} + void at_acerm3a_init() { at_init(); memregs_init(); - mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); i430hx_init(); piix3_init(7); @@ -555,7 +555,6 @@ void at_acerv35n_init() { at_init(); memregs_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); i430hx_init(); piix3_init(7); @@ -565,12 +564,10 @@ void at_acerv35n_init() if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } -#if 0 void at_p55t2p4_init() { at_init(); memregs_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430hx_init(); piix3_init(7); @@ -578,13 +575,11 @@ void at_p55t2p4_init() device_add(&intel_flash_bxt_device); if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } -#endif void at_i430vx_init() { at_init(); memregs_init(); - mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430vx_init(); piix3_init(7); @@ -593,34 +588,23 @@ void at_i430vx_init() if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } -// rom_t ami_ec_rom; - -#if 0 void at_p55tvp4_init() { at_init(); memregs_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430vx_init(); piix3_init(7); w83877f_init(); device_add(&intel_flash_bxt_device); - /* rom_init(&ami_ec_rom, "roms/AMIINT13.BIN", 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); - pc87306_init(); - - intel_endeavor_init(); */ - if ((atapi_cdrom_channel >= 4) && (atapi_cdrom_channel <= 5) && cdrom_enabled && !scsi_cdrom_enabled) ide_ter_init(); } -#endif void at_p55va_init() { at_init(); memregs_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430vx_init(); piix3_init(7); @@ -633,7 +617,6 @@ void at_i440fx_init() { at_init(); memregs_init(); - mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i440fx_init(); piix3_init(7); @@ -651,4 +634,6 @@ void model_init() fdc_update_is_nsc(0); ide_ter_enabled = 0; models[model].init(); + if (models[model].device) + device_add(models[model].device); } diff --git a/src/model.h b/src/model.h index 4fc692609..8eb2cc152 100644 --- a/src/model.h +++ b/src/model.h @@ -1,6 +1,14 @@ -/* Copyright holders: Sarah Walker +/* Copyright holders: Sarah Walker, Tohka see COPYING for more details */ +#define MODEL_AT 1 +#define MODEL_PS2 2 +#define MODEL_AMSTRAD 4 +#define MODEL_OLIM24 8 +#define MODEL_NEC 16 +#define MODEL_FUJITSU 32 +#define MODEL_RM 64 + typedef struct { char name[24]; @@ -11,10 +19,11 @@ typedef struct CPU *cpus; } cpu[5]; int fixed_gfxcard; - int is_at; + int flags; int min_ram, max_ram; int ram_granularity; void (*init)(); + struct device_t *device; } MODEL; extern MODEL models[]; @@ -26,3 +35,4 @@ int model_getromset(); int model_getmodel(int romset); char *model_getname(); void model_init(); +struct device_t *model_getdevice(int model); diff --git a/src/mouse.c b/src/mouse.c index bb6d68bcb..467dde2e9 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -1,7 +1,50 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include "ibm.h" #include "mouse.h" +#include "amstrad.h" +#include "mouse_ps2.h" +#include "mouse_serial.h" +#include "keyboard_olim24.h" -void (*mouse_poll)(int x, int y, int b); +static mouse_t *mouse_list[] = +{ + &mouse_serial_microsoft, + &mouse_ps2_2_button, + &mouse_intellimouse, + &mouse_amstrad, + &mouse_olim24, + NULL +}; + +static mouse_t *cur_mouse; +static void *mouse_p; +int mouse_type = 0; + +void mouse_emu_init() +{ + cur_mouse = mouse_list[mouse_type]; + mouse_p = cur_mouse->init(); +} + +void mouse_emu_close() +{ + if (cur_mouse) + cur_mouse->close(mouse_p); + cur_mouse = NULL; +} + +void mouse_poll(int x, int y, int z, int b) +{ + if (cur_mouse) + cur_mouse->poll(x, y, z, b, mouse_p); +} + +char *mouse_get_name(int mouse) +{ + if (!mouse_list[mouse]) + return NULL; + return mouse_list[mouse]->name; +} +int mouse_get_type(int mouse) +{ + return mouse_list[mouse]->type; +} diff --git a/src/mouse.h b/src/mouse.h index 5d55c3121..29a19b78e 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -1,8 +1,24 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern void (*mouse_poll)(int x, int y, int b); +void mouse_emu_init(); +void mouse_emu_close(); +void mouse_poll(int x, int y, int z, int b); -extern int mousepos; -extern int mousedelay; +char *mouse_get_name(int mouse); +int mouse_get_type(int mouse); +#define MOUSE_TYPE_SERIAL 0 +#define MOUSE_TYPE_PS2 1 +#define MOUSE_TYPE_AMSTRAD 2 +#define MOUSE_TYPE_OLIM24 3 + +#define MOUSE_TYPE_3BUTTON (1 << 31) + +typedef struct +{ + char name[80]; + void *(*init)(); + void (*close)(void *p); + uint8_t (*poll)(int x, int y, int z, int b, void *p); + int type; +} mouse_t; + +extern int mouse_type; diff --git a/src/mouse_amstrad.c b/src/mouse_amstrad.c deleted file mode 100644 index e880f15c9..000000000 --- a/src/mouse_amstrad.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright holders: SA1988, Curt Coder - see COPYING for more details -*/ -#include "ibm.h" -#include "io.h" -#include "mouse.h" -#include "mouse_amstrad.h" - -static int amstrad_x = 0, amstrad_y = 0, amstrad_b = 0; - -uint8_t mouse_amstrad_read(uint16_t port, void *priv) -{ - switch (port) - { - case 0x78: - return amstrad_x; - - case 0x7a: - return amstrad_y; - } - return 0xff; -} - -void mouse_amstrad_write(uint16_t port, uint8_t val, void *priv) -{ - switch (port) - { - case 0x78: - amstrad_x = 0; - break; - - case 0x7a: - amstrad_y = 0; - break; - } -} - -void mouse_amstrad_poll(int x, int y, int b) -{ - if (!x && !y && b==amstrad_b) return; - - amstrad_b=b; - if (x > amstrad_x) - amstrad_x+=3; - else - amstrad_x-=3; - - amstrad_x = x; - - if (y > amstrad_y) - amstrad_y+=3; - else - amstrad_y-=3; - - amstrad_y = y; -} - -void mouse_amstrad_init() -{ - mouse_poll = mouse_amstrad_poll; - io_sethandler(0x0078, 0x0001, mouse_amstrad_read, NULL, NULL, mouse_amstrad_write, NULL, NULL, NULL); - io_sethandler(0x007a, 0x0001, mouse_amstrad_read, NULL, NULL, mouse_amstrad_write, NULL, NULL, NULL); -} diff --git a/src/mouse_amstrad.h b/src/mouse_amstrad.h deleted file mode 100644 index 922397d7b..000000000 --- a/src/mouse_amstrad.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: SA1988 - see COPYING for more details -*/ -void mouse_amstrad_init(); diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index db45e78f0..15d2019f9 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -1,6 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include "ibm.h" #include "keyboard_at.h" #include "mouse.h" @@ -19,7 +16,7 @@ enum #define MOUSE_ENABLE 0x20 #define MOUSE_SCALE 0x10 -static struct +typedef struct mouse_ps2_t { int mode; @@ -30,56 +27,63 @@ static struct uint8_t command; int cd; -} mouse_ps2; + + int x, y, z, b; + + int is_intellimouse; + int intellimouse_mode; + + uint8_t last_data[6]; +} mouse_ps2_t; -void mouse_ps2_write(uint8_t val) +void mouse_ps2_write(uint8_t val, void *p) { - // pclog("PS/2 Mouse: Write %02X\n", val); - - if (mouse_ps2.cd) + mouse_ps2_t *mouse = (mouse_ps2_t *)p; + + if (mouse->cd) { - mouse_ps2.cd = 0; - switch (mouse_ps2.command) + mouse->cd = 0; + switch (mouse->command) { case 0xe8: /*Set mouse resolution*/ - mouse_ps2.resolution = val; + mouse->resolution = val; keyboard_at_adddata_mouse(0xfa); break; case 0xf3: /*Set sample rate*/ - mouse_ps2.sample_rate = val; + mouse->sample_rate = val; keyboard_at_adddata_mouse(0xfa); break; // default: -// fatal("mouse_ps2 : Bad data write %02X for command %02X\n", val, mouse_ps2.command); +// fatal("mouse_ps2 : Bad data write %02X for command %02X\n", val, mouse->command); } } else { uint8_t temp; - mouse_ps2.command = val; - switch (mouse_ps2.command) + mouse->command = val; + switch (mouse->command) { case 0xe6: /*Set scaling to 1:1*/ - mouse_ps2.flags &= ~MOUSE_SCALE; + mouse->flags &= ~MOUSE_SCALE; keyboard_at_adddata_mouse(0xfa); break; case 0xe7: /*Set scaling to 2:1*/ - mouse_ps2.flags |= MOUSE_SCALE; + mouse->flags |= MOUSE_SCALE; keyboard_at_adddata_mouse(0xfa); break; case 0xe8: /*Set mouse resolution*/ - mouse_ps2.cd = 1; + mouse->cd = 1; keyboard_at_adddata_mouse(0xfa); break; case 0xe9: /*Status request*/ keyboard_at_adddata_mouse(0xfa); - temp = mouse_ps2.flags; + temp = mouse->flags; if (mouse_buttons & 1) temp |= 1; if (mouse_buttons & 2) @@ -87,105 +91,162 @@ void mouse_ps2_write(uint8_t val) if (mouse_buttons & 4) temp |= 3; keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(mouse_ps2.resolution); - keyboard_at_adddata_mouse(mouse_ps2.sample_rate); + keyboard_at_adddata_mouse(mouse->resolution); + keyboard_at_adddata_mouse(mouse->sample_rate); break; case 0xf2: /*Read ID*/ keyboard_at_adddata_mouse(0xfa); - keyboard_at_adddata_mouse(0x00); + if (mouse->intellimouse_mode) + keyboard_at_adddata_mouse(0x03); + else + keyboard_at_adddata_mouse(0x00); break; case 0xf3: /*Set sample rate*/ - mouse_ps2.cd = 1; + mouse->cd = 1; keyboard_at_adddata_mouse(0xfa); break; case 0xf4: /*Enable*/ - mouse_ps2.flags |= MOUSE_ENABLE; + mouse->flags |= MOUSE_ENABLE; keyboard_at_adddata_mouse(0xfa); break; case 0xf5: /*Disable*/ - mouse_ps2.flags &= ~MOUSE_ENABLE; + mouse->flags &= ~MOUSE_ENABLE; keyboard_at_adddata_mouse(0xfa); break; case 0xff: /*Reset*/ - mouse_ps2.mode = MOUSE_STREAM; - mouse_ps2.flags = 0; + mouse->mode = MOUSE_STREAM; + mouse->flags = 0; + mouse->intellimouse_mode = 0; keyboard_at_adddata_mouse(0xfa); keyboard_at_adddata_mouse(0xaa); keyboard_at_adddata_mouse(0x00); break; // default: -// fatal("mouse_ps2 : Bad command %02X\n", val, mouse_ps2.command); +// fatal("mouse_ps2 : Bad command %02X\n", val, mouse->command); } } + + if (mouse->is_intellimouse) + { + int c; + + for (c = 0; c < 5; c++) + mouse->last_data[c] = mouse->last_data[c+1]; + + mouse->last_data[5] = val; + + if (mouse->last_data[0] == 0xf3 && mouse->last_data[1] == 0xc8 && + mouse->last_data[2] == 0xf3 && mouse->last_data[3] == 0x64 && + mouse->last_data[4] == 0xf3 && mouse->last_data[5] == 0x50) + mouse->intellimouse_mode = 1; + } } -static int ps2_x = 0, ps2_y = 0, ps2_b = 0; -int first_time = 1; -void mouse_ps2_poll(int x, int y, int b) +void mouse_ps2_poll(int x, int y, int z, int b, void *p) { + mouse_ps2_t *mouse = (mouse_ps2_t *)p; uint8_t packet[3] = {0x08, 0, 0}; - if (!x && !y && b == ps2_b && !first_time){ - // pclog("PS/2 Mouse: X is 0, Y is 0, and B is PS2_B\n"); - return; - } - - if (first_time) first_time = 0; + + if (!x && !y && !z && b == mouse->b) + return; if (!mouse_scan) - { - // pclog("PS/2 Mouse: Not scanning\n"); return; - } - ps2_x += x; - ps2_y -= y; - if (mouse_ps2.mode == MOUSE_STREAM && (mouse_ps2.flags & MOUSE_ENABLE) && + + mouse->x += x; + mouse->y -= y; + mouse->z -= z; + if (mouse->mode == MOUSE_STREAM && (mouse->flags & MOUSE_ENABLE) && ((mouse_queue_end - mouse_queue_start) & 0xf) < 13) { - ps2_b = b; + mouse->b = b; // pclog("Send packet : %i %i\n", ps2_x, ps2_y); - if (ps2_x > 255) - ps2_x = 255; - if (ps2_x < -256) - ps2_x = -256; - if (ps2_y > 255) - ps2_y = 255; - if (ps2_y < -256) - ps2_y = -256; - if (ps2_x < 0) - packet[0] |= 0x10; - if (ps2_y < 0) - packet[0] |= 0x20; + if (mouse->x > 255) + mouse->x = 255; + if (mouse->x < -256) + mouse->x = -256; + if (mouse->y > 255) + mouse->y = 255; + if (mouse->y < -256) + mouse->y = -256; + if (mouse->z < -8) + mouse->z = -8; + if (mouse->z > 7) + mouse->z = 7; + if (mouse->x < 0) + packet[0] |= 0x10; + if (mouse->y < 0) + packet[0] |= 0x20; if (mouse_buttons & 1) - packet[0] |= 1; + packet[0] |= 1; if (mouse_buttons & 2) - packet[0] |= 2; - if (mouse_buttons & 4) - packet[0] |= 4; - packet[1] = ps2_x & 0xff; - packet[2] = ps2_y & 0xff; - - ps2_x = ps2_y = 0; - + packet[0] |= 2; + if ((mouse_buttons & 4) && (mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON)) + packet[0] |= 4; + packet[1] = mouse->x & 0xff; + packet[2] = mouse->y & 0xff; + keyboard_at_adddata_mouse(packet[0]); keyboard_at_adddata_mouse(packet[1]); keyboard_at_adddata_mouse(packet[2]); + if (mouse->intellimouse_mode) + keyboard_at_adddata_mouse(mouse->z); + + mouse->x = mouse->y = mouse->z = 0; } - - // pclog("PS/2 Mouse: Poll\n"); } - -void mouse_ps2_init() +void *mouse_ps2_init() { - mouse_poll = mouse_ps2_poll; - mouse_write = mouse_ps2_write; - mouse_ps2.cd = 0; - mouse_ps2.flags = 0; - mouse_ps2.mode = MOUSE_STREAM; + mouse_ps2_t *mouse = (mouse_ps2_t *)malloc(sizeof(mouse_ps2_t)); + memset(mouse, 0, sizeof(mouse_ps2_t)); + +// mouse_poll = mouse_ps2_poll; +// mouse_write = mouse_ps2_write; + mouse->cd = 0; + mouse->flags = 0; + mouse->mode = MOUSE_STREAM; + + keyboard_at_set_mouse(mouse_ps2_write, mouse); + + return mouse; } + +void *mouse_intellimouse_init() +{ + mouse_ps2_t *mouse = mouse_ps2_init(); + + mouse->is_intellimouse = 1; + + return mouse; +} + +void mouse_ps2_close(void *p) +{ + mouse_ps2_t *mouse = (mouse_ps2_t *)p; + + free(mouse); +} + +mouse_t mouse_ps2_2_button = +{ + "2-button mouse (PS/2)", + mouse_ps2_init, + mouse_ps2_close, + mouse_ps2_poll, + MOUSE_TYPE_PS2 +}; +mouse_t mouse_intellimouse = +{ + "Microsoft Intellimouse (PS/2)", + mouse_intellimouse_init, + mouse_ps2_close, + mouse_ps2_poll, + MOUSE_TYPE_PS2 | MOUSE_TYPE_3BUTTON +}; diff --git a/src/mouse_ps2.h b/src/mouse_ps2.h index 4f93e00e0..645e3cf73 100644 --- a/src/mouse_ps2.h +++ b/src/mouse_ps2.h @@ -1,4 +1,2 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -void mouse_ps2_init(); +extern mouse_t mouse_ps2_2_button; +extern mouse_t mouse_intellimouse; diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 0b9456bbd..f05e64d9e 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -1,23 +1,28 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include "ibm.h" #include "mouse.h" #include "pic.h" #include "serial.h" #include "timer.h" -static int oldb=0; - -void mouse_serial_poll(int x, int y, int b) +typedef struct mouse_serial_t { - uint8_t mousedat[3]; - - if (!(serial1.ier & 1)) - return; - if (!x && !y && b==oldb) return; + int mousepos, mousedelay; + int oldb; + SERIAL *serial; +} mouse_serial_t; - oldb=b; +void mouse_serial_poll(int x, int y, int z, int b, void *p) +{ + mouse_serial_t *mouse = (mouse_serial_t *)p; + SERIAL *serial = mouse->serial; + uint8_t mousedat[3]; + + if (!(serial->ier & 1)) + return; + if (!x && !y && b == mouse->oldb) + return; + + mouse->oldb = b; if (x>127) x=127; if (y>127) y=127; if (x<-128) x=-128; @@ -32,44 +37,62 @@ void mouse_serial_poll(int x, int y, int b) mousedat[1]=x&0x3F; mousedat[2]=y&0x3F; - if (!(serial1.mctrl&0x10)) + if (!(serial->mctrl & 0x10)) { - // pclog("Serial data %02X %02X %02X\n", mousedat[0], mousedat[1], mousedat[2]); - serial_write_fifo(&serial1, mousedat[0]); - serial_write_fifo(&serial1, mousedat[1]); - serial_write_fifo(&serial1, mousedat[2]); +// pclog("Serial data %02X %02X %02X\n", mousedat[0], mousedat[1], mousedat[2]); + serial_write_fifo(mouse->serial, mousedat[0]); + serial_write_fifo(mouse->serial, mousedat[1]); + serial_write_fifo(mouse->serial, mousedat[2]); } } -void mouse_serial_rcr(void *p) +void mouse_serial_rcr(SERIAL *serial, void *p) { - mousepos=-1; - mousedelay=5000 * (1 << TIMER_SHIFT); + mouse_serial_t *mouse = (mouse_serial_t *)p; + + mouse->mousepos = -1; + mouse->mousedelay = 5000 * (1 << TIMER_SHIFT); } void mousecallback(void *p) { - SERIAL *serial = (SERIAL *)p; - mousedelay = 0; - if (mousepos == -1) + mouse_serial_t *mouse = (mouse_serial_t *)p; + + mouse->mousedelay = 0; + if (mouse->mousepos == -1) { - mousepos = 0; -/* serial_fifo_read = serial_fifo_write = 0; - serial.lsr &= ~1;*/ - serial_write_fifo(serial, 'M'); + mouse->mousepos = 0; + serial_write_fifo(mouse->serial, 'M'); } -/* else if (serial_fifo_read != serial_fifo_write) - { - serial.iir=4; - serial.lsr|=1; - if (serial.mctrl&8) picint(0x10); - }*/ } -void mouse_serial_init() +void *mouse_serial_init() { - mouse_poll = mouse_serial_poll; + mouse_serial_t *mouse = (mouse_t *)malloc(sizeof(mouse_serial_t)); + memset(mouse, 0, sizeof(mouse_serial_t)); + + mouse->serial = &serial1; serial1.rcr_callback = mouse_serial_rcr; - timer_add(mousecallback, &mousedelay, &mousedelay, &serial1); + serial1.rcr_callback_p = mouse; + timer_add(mousecallback, &mouse->mousedelay, &mouse->mousedelay, mouse); + + return mouse; } +void mouse_serial_close(void *p) +{ + mouse_serial_t *mouse = (mouse_serial_t *)p; + + free(mouse); + + serial1.rcr_callback = NULL; +} + +mouse_t mouse_serial_microsoft = +{ + "Microsoft 2-button mouse (serial)", + mouse_serial_init, + mouse_serial_close, + mouse_serial_poll, + MOUSE_TYPE_SERIAL +}; diff --git a/src/mouse_serial.h b/src/mouse_serial.h index 8021bfd7c..94e744d44 100644 --- a/src/mouse_serial.h +++ b/src/mouse_serial.h @@ -1,4 +1 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -void mouse_serial_init(); +extern mouse_t mouse_serial_microsoft; diff --git a/src/nvr.c b/src/nvr.c index 1c9082657..f5e632724 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -15,6 +15,8 @@ int nvr_dosave = 0; static int nvr_onesec_time = 0, nvr_onesec_cnt = 0; +static int rtctime; + void getnvrtime() { time_get(nvrram); @@ -214,7 +216,7 @@ void loadnvr() case ROM_DESKPRO_386: f = romfopen(nvr_concat("deskpro386.nvr"), "rb"); break; case ROM_ACER386: f = romfopen(nvr_concat("acer386.nvr"), "rb"); nvrmask = 127; break; case ROM_MEGAPC: f = romfopen(nvr_concat("megapc.nvr"), "rb"); nvrmask = 127; break; - case ROM_AMI386: f = romfopen(nvr_concat("ami386.nvr"), "rb"); nvrmask = 127; break; + case ROM_AMI386SX: f = romfopen(nvr_concat("ami386.nvr"), "rb"); nvrmask = 127; break; case ROM_AMI486: f = romfopen(nvr_concat("ami486.nvr"), "rb"); nvrmask = 127; break; case ROM_WIN486: f = romfopen(nvr_concat("win486.nvr"), "rb"); nvrmask = 127; break; case ROM_PCI486: f = romfopen(nvr_concat("hot-433.nvr"), "rb"); nvrmask = 127; break; @@ -224,17 +226,26 @@ void loadnvr() case ROM_ENDEAVOR: f = romfopen(nvr_concat("endeavor.nvr"), "rb"); nvrmask = 127; break; case ROM_PX386: f = romfopen(nvr_concat("px386.nvr"), "rb"); nvrmask = 127; break; case ROM_DTK386: f = romfopen(nvr_concat("dtk386.nvr"), "rb"); nvrmask = 127; break; + case ROM_MR386DX_OPTI495: f = romfopen(nvr_concat("mr386dx_opti495.nvr"), "rb"); nvrmask = 127; break; + case ROM_AMI386DX_OPTI495: f = romfopen(nvr_concat("ami386dx_opti495.nvr"), "rb"); nvrmask = 127; break; case ROM_DTK486: f = romfopen(nvr_concat("dtk486.nvr"), "rb"); nvrmask = 127; break; case ROM_R418: f = romfopen(nvr_concat("r418.nvr"), "rb"); nvrmask = 127; break; case ROM_586MC1: f = romfopen(nvr_concat("586mc1.nvr"), "rb"); nvrmask = 127; break; case ROM_PLATO: f = romfopen(nvr_concat("plato.nvr"), "rb"); nvrmask = 127; break; case ROM_MB500N: f = romfopen(nvr_concat("mb500n.nvr"), "rb"); nvrmask = 127; break; +#if 0 + case ROM_POWERMATE_V: f = romfopen(nvr_concat("powermate_v.nvr"), "rb"); nvrmask = 127; break; +#endif + case ROM_P54TP4XE: f = romfopen(nvr_concat("p54tp4xe.nvr"), "rb"); nvrmask = 127; break; case ROM_ACERM3A: f = romfopen(nvr_concat("acerm3a.nvr"), "rb"); nvrmask = 127; break; case ROM_ACERV35N: f = romfopen(nvr_concat("acerv35n.nvr"), "rb"); nvrmask = 127; break; case ROM_P55VA: f = romfopen(nvr_concat("p55va.nvr"), "rb"); nvrmask = 127; break; + case ROM_P55T2P4: f = romfopen(nvr_concat("p55t2p4.nvr"), "rb"); nvrmask = 127; break; + case ROM_P55TVP4: f = romfopen(nvr_concat("p55tvp4.nvr"), "rb"); nvrmask = 127; break; case ROM_440FX: f = romfopen(nvr_concat("440fx.nvr"), "rb"); nvrmask = 127; break; case ROM_MARL: f = romfopen(nvr_concat("marl.nvr"), "rb"); nvrmask = 127; break; case ROM_THOR: f = romfopen(nvr_concat("thor.nvr"), "rb"); nvrmask = 127; break; + case ROM_MRTHOR: f = romfopen(nvr_concat("mrthor.nvr"), "rb"); nvrmask = 127; break; default: return; } if (!f) @@ -282,7 +293,7 @@ void savenvr() case ROM_DESKPRO_386: f = romfopen(nvr_concat("deskpro386.nvr"), "wb"); break; case ROM_ACER386: f = romfopen(nvr_concat("acer386.nvr"), "wb"); break; case ROM_MEGAPC: f = romfopen(nvr_concat("megapc.nvr"), "wb"); break; - case ROM_AMI386: f = romfopen(nvr_concat("ami386.nvr"), "wb"); break; + case ROM_AMI386SX: f = romfopen(nvr_concat("ami386.nvr"), "wb"); break; case ROM_AMI486: f = romfopen(nvr_concat("ami486.nvr"), "wb"); break; case ROM_WIN486: f = romfopen(nvr_concat("win486.nvr"), "wb"); break; case ROM_PCI486: f = romfopen(nvr_concat("hot-433.nvr"), "wb"); break; @@ -292,17 +303,26 @@ void savenvr() case ROM_ENDEAVOR: f = romfopen(nvr_concat("endeavor.nvr"), "wb"); break; case ROM_PX386: f = romfopen(nvr_concat("px386.nvr"), "wb"); break; case ROM_DTK386: f = romfopen(nvr_concat("dtk386.nvr"), "wb"); break; + case ROM_MR386DX_OPTI495: f = romfopen(nvr_concat("mr386dx_opti495.nvr"), "wb"); break; + case ROM_AMI386DX_OPTI495: f = romfopen(nvr_concat("ami386dx_opti495.nvr"), "wb"); break; case ROM_DTK486: f = romfopen(nvr_concat("dtk486.nvr"), "wb"); break; case ROM_R418: f = romfopen(nvr_concat("r418.nvr"), "wb"); break; case ROM_586MC1: f = romfopen(nvr_concat("586mc1.nvr"), "wb"); break; case ROM_PLATO: f = romfopen(nvr_concat("plato.nvr"), "wb"); break; case ROM_MB500N: f = romfopen(nvr_concat("mb500n.nvr"), "wb"); break; +#if 0 + case ROM_POWERMATE_V: f = romfopen(nvr_concat("powermate_v.nvr"), "wb"); break; +#endif + case ROM_P54TP4XE: f = romfopen(nvr_concat("p54tp4xe.nvr"), "wb"); break; case ROM_ACERM3A: f = romfopen(nvr_concat("acerm3a.nvr"), "wb"); break; case ROM_ACERV35N: f = romfopen(nvr_concat("acerv35n.nvr"), "wb"); break; case ROM_P55VA: f = romfopen(nvr_concat("p55va.nvr"), "wb"); break; + case ROM_P55T2P4: f = romfopen(nvr_concat("p55t2p4.nvr"), "wb"); break; + case ROM_P55TVP4: f = romfopen(nvr_concat("p55tvp4.nvr"), "wb"); break; case ROM_440FX: f = romfopen(nvr_concat("440fx.nvr"), "wb"); break; case ROM_MARL: f = romfopen(nvr_concat("marl.nvr"), "wb"); break; case ROM_THOR: f = romfopen(nvr_concat("thor.nvr"), "wb"); break; + case ROM_MRTHOR: f = romfopen(nvr_concat("mrthor.nvr"), "wb"); break; default: return; } fwrite(nvrram,128,1,f); diff --git a/src/opti.c b/src/opti495.c similarity index 84% rename from src/opti.c rename to src/opti495.c index a2fb4e09f..c173c5be3 100644 --- a/src/opti.c +++ b/src/opti495.c @@ -1,14 +1,14 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ /*OPTi 82C495 emulation This is the chipset used in the AMI386 model*/ #include "ibm.h" +#include "cpu.h" +#include "io.h" +#include "mem.h" -uint8_t optiregs[0x10]; -int optireg; +static uint8_t optiregs[0x10]; +static int optireg; -void writeopti(uint16_t addr, uint8_t val) +static void opti495_write(uint16_t addr, uint8_t val, void *p) { switch (addr) { @@ -17,23 +17,50 @@ void writeopti(uint16_t addr, uint8_t val) break; case 0x24: printf("Writing OPTI reg %02X %02X\n",optireg,val); - if (optireg>=0x20 && optireg<=0x2C) optiregs[optireg-0x20]=val; + if (optireg>=0x20 && optireg<=0x2C) + { + optiregs[optireg-0x20]=val; + if (optireg == 0x21) + { + cpu_cache_ext_enabled = val & 0x10; + cpu_update_waitstates(); + } + if (optireg == 0x22) + { + shadowbios = !(val & 0x80); + shadowbios_write = val & 0x80; + //pclog("shadowbios %i %02x\n", shadowbios, val); + if (shadowbios) + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); +// if (shadowbios) +// fatal("Here\n"); + } + } break; } } -uint8_t readopti(uint16_t addr) +static uint8_t opti495_read(uint16_t addr, void *p) { switch (addr) { case 0x24: - printf("Read OPTI reg %02X\n",optireg); + //printf("Read OPTI reg %02X\n",optireg); if (optireg>=0x20 && optireg<=0x2C) return optiregs[optireg-0x20]; break; } return 0xFF; } +void opti495_init() +{ + io_sethandler(0x0022, 0x0001, opti495_read, NULL, NULL, opti495_write, NULL, NULL, NULL); + io_sethandler(0x0024, 0x0001, opti495_read, NULL, NULL, opti495_write, NULL, NULL, NULL); + optiregs[0x22-0x20] = 0x80; +} + /*Details for the chipset from Ralph Brown's interrupt list This describes the OPTi 82C493, the 82C495 seems similar except there is one more register (2C) diff --git a/src/opti495.h b/src/opti495.h new file mode 100644 index 000000000..814f313fa --- /dev/null +++ b/src/opti495.h @@ -0,0 +1 @@ +void opti495_init(); diff --git a/src/pc.c b/src/pc.c index 19e73df96..2e85b9091 100644 --- a/src/pc.c +++ b/src/pc.c @@ -9,7 +9,6 @@ #include "device.h" #include "ali1429.h" -#include "amstrad.h" #include "cdrom-ioctl.h" #include "disc.h" #include "mem.h" @@ -46,6 +45,7 @@ #include "timer.h" #include "vid_voodoo.h" #include "video.h" +#include "amstrad.h" #include "nethandler.h" #define NE2000 1 #define RTL8029AS 2 @@ -58,7 +58,6 @@ int path_len; int window_w, window_h, window_x, window_y, window_remember; int start_in_fullscreen = 0; -int frame = 0; int scsi_cdrom_enabled; int cdrom_enabled; @@ -75,7 +74,6 @@ extern int readlnum,writelnum; void fullspeed(); int framecount,fps; -int intcount; int output; int atfullspeed; @@ -115,15 +113,15 @@ uint8_t cgastat; int pollmouse_delay = 2; void pollmouse() { - int x,y; + int x, y, z; // return; pollmouse_delay--; if (pollmouse_delay) return; pollmouse_delay = 2; mouse_poll_host(); - mouse_get_mickeys(&x,&y); + mouse_get_mickeys(&x, &y, &z); if (mouse_poll) - mouse_poll(x, y, mouse_buttons); + mouse_poll(x, y, z, mouse_buttons); // if (mousecapture) position_mouse(64,64); } @@ -187,7 +185,6 @@ void pc_reset() { cpu_set(); resetx86(); - mem_updatecache(); //timer_reset(); dma_reset(); fdc_reset(); @@ -288,6 +285,8 @@ void initpc(int argc, char *argv[]) disc_load(0, discfns[0]); disc_load(1, discfns[1]); + disc_load(2, discfns[2]); + disc_load(3, discfns[3]); //loadfont(); loadnvr(); @@ -386,6 +385,7 @@ void resetpchard() saveconfig(); device_close_all(); + mouse_emu_close(); device_init(); midi_close(); @@ -398,6 +398,7 @@ void resetpchard() disc_reset(); model_init(); + mouse_emu_init(); // mem_add_bios(); video_init(); speaker_init(); @@ -435,6 +436,8 @@ void resetpchard() keyboard_at_reset(); + cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; + // output=3; if ((cdrom_drive == -1) || (cdrom_drive == 0)) @@ -539,19 +542,16 @@ void runpc() egareads=egawrites=0; cycles_lost = 0; mmuflush=0; - intcount=0; - intcount=pitcount=0; emu_fps = frames; frames = 0; } if (win_title_update) { win_title_update=0; - sprintf(s, "86Box v%s - %i%% - %s - %s - %s", emulator_version, fps, model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press F12-F8 or middle button to release mouse"); + sprintf(s, "86Box v%s - %i%% - %s - %s - %s", emulator_version, fps, model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? "Press F12-F8 to release mouse" : "Press F12-F8 or middle button to release mouse")); set_window_title(s); } done++; - frame++; } void fullspeed() @@ -577,7 +577,6 @@ void speedchanged() setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed); else setpitclock(14318184.0); - mem_updatecache(); nvr_recalc(); } @@ -591,6 +590,8 @@ void closepc() // while (1) runpc(); disc_close(0); disc_close(1); + disc_close(2); + disc_close(3); dumpregs(); closevideo(); device_close_all(); @@ -610,8 +611,6 @@ void closepc() END_OF_MAIN();*/ -int cga_comp=0; - void loadconfig(char *fn) { int c, d; @@ -649,6 +648,8 @@ void loadconfig(char *fn) cpu = config_get_int(NULL, "cpu", 0); cpu_use_dynarec = config_get_int(NULL, "cpu_use_dynarec", 0); + cpu_waitstates = config_get_int(NULL, "cpu_waitstates", 0); + gfxcard = config_get_int(NULL, "gfxcard", 0); video_speed = config_get_int(NULL, "video_speed", 3); sound_card_current = config_get_int(NULL, "sndcard", SB2); @@ -666,9 +667,19 @@ void loadconfig(char *fn) else strcpy(discfns[1], ""); ui_writeprot[1] = config_get_int(NULL, "disc_b_writeprot", 0); + p = (char *)config_get_string(NULL, "disc_3", ""); + if (p) strcpy(discfns[2], p); + else strcpy(discfns[2], ""); + ui_writeprot[2] = config_get_int(NULL, "disc_3_writeprot", 0); + + p = (char *)config_get_string(NULL, "disc_4", ""); + if (p) strcpy(discfns[3], p); + else strcpy(discfns[3], ""); + ui_writeprot[3] = config_get_int(NULL, "disc_4_writeprot", 0); + mem_size = config_get_int(NULL, "mem_size", 4096); - if (mem_size < (models[model].is_at ? models[model].min_ram*1024 : models[model].min_ram)) - mem_size = (models[model].is_at ? models[model].min_ram*1024 : models[model].min_ram); + if (mem_size < ((models[model].flags & MODEL_AT) ? models[model].min_ram*1024 : models[model].min_ram)) + mem_size = ((models[model].flags & MODEL_AT) ? models[model].min_ram*1024 : models[model].min_ram); cdrom_drive = config_get_int(NULL, "cdrom_drive", 0); old_cdrom_drive = cdrom_drive; @@ -683,10 +694,6 @@ void loadconfig(char *fn) if (p) strcpy(iso_path, p); else strcpy(iso_path, ""); - slowega = config_get_int(NULL, "slow_video", 1); - cache = config_get_int(NULL, "cache", 3); - cga_comp = config_get_int(NULL, "cga_composite", 0); - vid_resize = config_get_int(NULL, "vid_resize", 0); vid_api = config_get_int(NULL, "vid_api", 0); video_fullscreen_scale = config_get_int(NULL, "video_fullscreen_scale", 0); @@ -716,16 +723,29 @@ void loadconfig(char *fn) p = (char *)config_get_string(NULL, "hdf_fn", ""); if (p) strcpy(ide_fn[3], p); else strcpy(ide_fn[3], ""); + hdc[4].spt = config_get_int(NULL, "hdg_sectors", 0); + hdc[4].hpc = config_get_int(NULL, "hdg_heads", 0); + hdc[4].tracks = config_get_int(NULL, "hdg_cylinders", 0); + p = (char *)config_get_string(NULL, "hdg_fn", ""); + if (p) strcpy(ide_fn[4], p); + else strcpy(ide_fn[4], ""); + hdc[5].spt = config_get_int(NULL, "hdh_sectors", 0); + hdc[5].hpc = config_get_int(NULL, "hdh_heads", 0); + hdc[5].tracks = config_get_int(NULL, "hdh_cylinders", 0); + p = (char *)config_get_string(NULL, "hdh_fn", ""); + if (p) strcpy(ide_fn[5], p); + else strcpy(ide_fn[5], ""); - fdd_set_type(0, config_get_int(NULL, "drive_a_type", 7)); - fdd_set_type(1, config_get_int(NULL, "drive_b_type", 7)); + fdd_set_type(0, config_get_int(NULL, "drive_a_type", 1)); + fdd_set_type(1, config_get_int(NULL, "drive_b_type", 1)); + fdd_set_type(2, config_get_int(NULL, "drive_3_type", 1)); + fdd_set_type(3, config_get_int(NULL, "drive_4_type", 1)); force_43 = config_get_int(NULL, "force_43", 0); enable_overscan = config_get_int(NULL, "enable_overscan", 0); enable_flash = config_get_int(NULL, "enable_flash", 1); enable_sync = config_get_int(NULL, "enable_sync", 1); - mouse_always_serial = config_get_int(NULL, "mouse_always_serial", 0); window_w = config_get_int(NULL, "window_w", 0); window_h = config_get_int(NULL, "window_h", 0); @@ -734,6 +754,7 @@ void loadconfig(char *fn) window_remember = config_get_int(NULL, "window_remember", 0); joystick_type = config_get_int(NULL, "joystick_type", 0); + mouse_type = config_get_int(NULL, "mouse_type", 0); for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { @@ -806,19 +827,21 @@ void saveconfig() config_set_int(NULL, "cpu_manufacturer", cpu_manufacturer); config_set_int(NULL, "cpu", cpu); config_set_int(NULL, "cpu_use_dynarec", cpu_use_dynarec); + config_set_int(NULL, "cpu_waitstates", cpu_waitstates); config_set_int(NULL, "gfxcard", gfxcard); config_set_int(NULL, "video_speed", video_speed); config_set_int(NULL, "sndcard", sound_card_current); config_set_int(NULL, "cpu_speed", cpuspeed); config_set_int(NULL, "has_fpu", hasfpu); - config_set_int(NULL, "slow_video", slowega); - config_set_int(NULL, "cache", cache); - config_set_int(NULL, "cga_composite", cga_comp); config_set_string(NULL, "disc_a", discfns[0]); config_set_int(NULL, "disc_a_writeprot", ui_writeprot[0]); config_set_string(NULL, "disc_b", discfns[1]); config_set_int(NULL, "disc_b_writeprot", ui_writeprot[1]); + config_set_string(NULL, "disc_3", discfns[2]); + config_set_int(NULL, "disc_3_writeprot", ui_writeprot[2]); + config_set_string(NULL, "disc_4", discfns[3]); + config_set_int(NULL, "disc_4_writeprot", ui_writeprot[3]); config_set_int(NULL, "mem_size", mem_size); config_set_int(NULL, "cdrom_drive", cdrom_drive); config_set_int(NULL, "cdrom_enabled", cdrom_enabled); @@ -850,18 +873,28 @@ void saveconfig() config_set_int(NULL, "hdf_heads", hdc[3].hpc); config_set_int(NULL, "hdf_cylinders", hdc[3].tracks); config_set_string(NULL, "hdf_fn", ide_fn[3]); + config_set_int(NULL, "hdg_sectors", hdc[4].spt); + config_set_int(NULL, "hdg_heads", hdc[4].hpc); + config_set_int(NULL, "hdg_cylinders", hdc[4].tracks); + config_set_string(NULL, "hdg_fn", ide_fn[4]); + config_set_int(NULL, "hdh_sectors", hdc[5].spt); + config_set_int(NULL, "hdh_heads", hdc[5].hpc); + config_set_int(NULL, "hdh_cylinders", hdc[5].tracks); + config_set_string(NULL, "hdh_fn", ide_fn[5]); config_set_int(NULL, "drive_a_type", fdd_get_type(0)); config_set_int(NULL, "drive_b_type", fdd_get_type(1)); + config_set_int(NULL, "drive_3_type", fdd_get_type(2)); + config_set_int(NULL, "drive_4_type", fdd_get_type(3)); config_set_int(NULL, "force_43", force_43); config_set_int(NULL, "enable_overscan", enable_overscan); config_set_int(NULL, "enable_flash", enable_flash); config_set_int(NULL, "enable_sync", enable_sync); - config_set_int(NULL, "mouse_always_serial", mouse_always_serial); config_set_int(NULL, "joystick_type", joystick_type); + config_set_int(NULL, "mouse_type", mouse_type); for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) { diff --git a/src/pc.rc b/src/pc.rc index 4c0a1f8dd..1fa343d29 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -18,13 +18,21 @@ BEGIN END POPUP "&Disc" BEGIN - MENUITEM "Change drive &A:...", IDM_DISC_A - MENUITEM "Change drive A (&Write-protected):...", IDM_DISC_A_WP - MENUITEM "&Eject drive A:", IDM_EJECT_A + MENUITEM "Change FDD& 1...", IDM_DISC_1 + MENUITEM "Change FDD 1 (&Write-protected)...", IDM_DISC_1_WP + MENUITEM "&Eject FDD 1", IDM_EJECT_1 MENUITEM SEPARATOR - MENUITEM "Change drive &B:...", IDM_DISC_B - MENUITEM "Change drive B (W&rite-protected):...", IDM_DISC_B_WP - MENUITEM "E&ject drive B:", IDM_EJECT_B + MENUITEM "Change FDD &2...", IDM_DISC_2 + MENUITEM "Change FDD 2 (W&rite-protected)...", IDM_DISC_2_WP + MENUITEM "E&ject FDD 2", IDM_EJECT_2 + MENUITEM SEPARATOR + MENUITEM "Change FDD &3...", IDM_DISC_3 + MENUITEM "Change FDD 3 (W&rite-protected)...", IDM_DISC_3_WP + MENUITEM "E&ject FDD 3", IDM_EJECT_3 + MENUITEM SEPARATOR + MENUITEM "Change FDD &4...", IDM_DISC_4 + MENUITEM "Change FDD 4 (W&rite-protected)...", IDM_DISC_4_WP + MENUITEM "E&ject FDD 4", IDM_EJECT_4 MENUITEM SEPARATOR MENUITEM "&Configure hard discs...",IDM_HDCONF POPUP "C&D-ROM" @@ -73,7 +81,7 @@ BEGIN POPUP "&Video" BEGIN MENUITEM "&Resizeable window",IDM_VID_RESIZE - MENUITEM "Remember size && position",IDM_VID_REMEMBER + MENUITEM "R&emember size && position",IDM_VID_REMEMBER MENUITEM SEPARATOR MENUITEM "&DirectDraw", IDM_VID_DDRAW MENUITEM "Direct&3D 9", IDM_VID_D3D @@ -87,6 +95,11 @@ BEGIN MENUITEM "&Integer scale", IDM_VID_FS_INT END MENUITEM SEPARATOR + MENUITEM "F&orce 4:3 display ratio", IDM_VID_FORCE43 + MENUITEM "E&GA/(S)VGA overscan", IDM_VID_OVERSCAN + MENUITEM SEPARATOR + MENUITEM "D&isc activity flash", IDM_VID_FLASH + MENUITEM SEPARATOR MENUITEM "Take s&creenshot\tCtrl+F11", IDM_VID_SCREENSHOT END MENUITEM "&Status", IDM_STATUS @@ -99,141 +112,170 @@ BEGIN VK_F12, IDM_FILE_RESET_CAD, CONTROL, VIRTKEY END -ConfigureDlg DIALOGEX 0, 0, 248+40, 248+60 +ConfigureDlg DIALOGEX 0, 0, 252+40, 236+80 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Configure 86Box" FONT 9, "Segoe UI" BEGIN - DEFPUSHBUTTON "OK",IDOK,64,284,50,14, WS_TABSTOP - PUSHBUTTON "Cancel",IDCANCEL,128,284,50,14, WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,64,292,50,14, WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,128,292,50,14, WS_TABSTOP COMBOBOX IDC_COMBO1,62,16,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure", IDC_CONFIGUREMOD, 224, 16, 40, 14, WS_TABSTOP COMBOBOX IDC_COMBOVID,62,36,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure", IDC_CONFIGUREVID, 224, 36, 40, 14, WS_TABSTOP COMBOBOX IDC_COMBOCPUM,62,56,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO3,62,76,102,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Dynamic Recompiler",IDC_CHECKDYNAREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,169,76,99,10 - COMBOBOX IDC_COMBOCHC,62,96,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOSPD,162,96,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBOSND,62,116,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOWS, 62,96,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOSPD,62,116,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBOSND,162,116,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure", IDC_CONFIGURESND, 224, 116, 40, 14, WS_TABSTOP EDITTEXT IDC_MEMTEXT, 62, 136, 36, 14, ES_AUTOHSCROLL | ES_NUMBER CONTROL "", IDC_MEMSPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_SETBUDDYINT, 98, 136, 12, 14 LTEXT "MB", IDC_TEXT_MB, 98, 136, 10, 10 - CONTROL "CMS / Game Blaster",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,172,102,10 - CONTROL "Gravis Ultrasound",IDC_CHECKGUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,188,102,10 - CONTROL "Innovation SSI-2001",IDC_CHECKSSI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,204,102,10 - CONTROL "Composite CGA",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,220,102,10 - CONTROL "Enable time sync",IDC_CHECKSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,236,102,10 + CONTROL "CMS / Game Blaster",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,192,102,10 + CONTROL "Gravis Ultrasound",IDC_CHECKGUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,208,102,10 - CONTROL "Force 4:3 display ratio",IDC_CHECKFORCE43,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,172,102,10 - CONTROL "EGA/(S)VGA overscan",IDC_CHECKOVERSCAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,188,102,10 - CONTROL "Disk activity flash",IDC_CHECKFLASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,204,102,10 - CONTROL "Ser.mouse inst.of PS/2",IDC_CHECKSERIAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,220,102,10 + CONTROL "Innovation SSI-2001",IDC_CHECKSSI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,192,102,10 + CONTROL "Enable time sync",IDC_CHECKSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,208,102,10 - CONTROL "Voodoo Graphics",IDC_CHECKVOODOO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,236,102,10 - PUSHBUTTON "Configure", IDC_CONFIGUREVOODOO, 224, 236, 40, 14, WS_TABSTOP + CONTROL "Voodoo Graphics",IDC_CHECKVOODOO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,224,102,10 + PUSHBUTTON "Configure", IDC_CONFIGUREVOODOO, 224, 224, 40, 14, WS_TABSTOP - LTEXT "Joystick :",IDC_STATIC,15,252,40,10 - COMBOBOX IDC_COMBOJOY,62,252,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "Joystick 1...",IDC_JOY1,16,268,50,14, WS_TABSTOP - PUSHBUTTON "Joystick 2...",IDC_JOY2,80,268,50,14, WS_TABSTOP - DEFPUSHBUTTON "Joystick 3...",IDC_JOY3,144,268,50,14, WS_TABSTOP - PUSHBUTTON "Joystick 4...",IDC_JOY4,208,268,50,14, WS_TABSTOP + LTEXT "Mouse :",IDC_STATIC,15,240,40,10 + COMBOBOX IDC_COMBOMOUSE,62,240,157,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + + LTEXT "Joystick :",IDC_STATIC,15,260,40,10 + COMBOBOX IDC_COMBOJOY,62,260,157,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "Joystick 1...",IDC_JOY1,16,276,50,14, WS_TABSTOP + PUSHBUTTON "Joystick 2...",IDC_JOY2,80,276,50,14, WS_TABSTOP + DEFPUSHBUTTON "Joystick 3...",IDC_JOY3,144,276,50,14, WS_TABSTOP + PUSHBUTTON "Joystick 4...",IDC_JOY4,208,276,50,14, WS_TABSTOP LTEXT "Machine :",IDC_STATIC,15,16,40,10 LTEXT "Video :",IDC_STATIC,15,36,34,10 LTEXT "CPU type :",IDC_STATIC,15,56,34,10 LTEXT "CPU :",IDC_STATIC,15,76,34,10 - LTEXT "Cache :",IDC_STATIC,15,96,40,10 - LTEXT "Vid. speed :",IDC_STATIC,125,96,34,10 - LTEXT "Soundcard :",IDC_STATIC,15,116,40,10 + LTEXT "Waitstates :",IDC_STATIC,15,96,40,10 + LTEXT "Vid. speed :",IDC_STATIC,15,116,40,10 + LTEXT "Soundcard:",IDC_STATIC,125,116,34,10 LTEXT "Network :",IDC_STATIC,125,136,34,10 COMBOBOX IDC_COMBONET,162,136,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure", IDC_CONFIGURENET, 224, 136, 40, 14, WS_TABSTOP LTEXT "Memory :",IDC_STATIC,15,136,40,10 - LTEXT "Drive A: :",IDC_STATIC,15,156,40,10 - LTEXT "Drive B: :",IDC_STATIC,125,156,40,10 - COMBOBOX IDC_COMBODRA,62,156,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBODRB,162,156,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "FDD 1 :",IDC_STATIC,15,156,40,10 + LTEXT "FDD 2 :",IDC_STATIC,125,156,40,10 + COMBOBOX IDC_COMBODR1,62,156,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBODR2,162,156,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "FDD 3 :",IDC_STATIC,15,176,40,10 + LTEXT "FDD 4 :",IDC_STATIC,125,176,40,10 + COMBOBOX IDC_COMBODR3,62,176,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBODR4,162,176,57,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END -HdConfDlg DIALOGEX 0, 0, 210, 286+4*16 +HdConfDlg DIALOGEX 0, 0, 210, DLG_HEIGHT STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Configure Hard Discs" FONT 9, "Segoe UI" BEGIN - DEFPUSHBUTTON "OK",IDOK,31+12,264+64,50,14 - PUSHBUTTON "Cancel",IDCANCEL,101+12,264+64,50,14 + DEFPUSHBUTTON "OK",IDOK,31+12,CMD_BASE,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101+12,CMD_BASE,50,14 - LTEXT "C:",IDC_STATIC,7,6,27,10 - RADIOBUTTON "Hard drive", IDC_CHDD, 7+64, 6, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_CCDROM, 7+128, 6, 53, 12 , WS_TABSTOP - EDITTEXT IDC_EDIT_C_FN, 7, 6+16, 136, 12, WS_DISABLED - PUSHBUTTON "...",IDC_CFILE,7 + 136, 6+16, 16, 14 - PUSHBUTTON "New",IDC_CNEW,7 + 136 + 16, 6+16, 24, 14 - PUSHBUTTON "Eject", IDC_EJECTC, 7 + 136 + 16 + 24, 6+16, 24, 14 + LTEXT "C:",IDC_STATIC,7,C_BASE+2,27,10 + RADIOBUTTON "Hard drive", IDC_CHDD, 7+64, C_BASE, 53, 12 , WS_TABSTOP + RADIOBUTTON "CD-ROM", IDC_CCDROM, 7+128, C_BASE, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_C_FN, 7, C_BASE+16, 136, 12, WS_DISABLED + PUSHBUTTON "...",IDC_CFILE,7 + 136, C_BASE+16, 16, 14 + PUSHBUTTON "New",IDC_CNEW,7 + 136 + 16, C_BASE+16, 24, 14 + PUSHBUTTON "Eject", IDC_EJECTC, 7 + 136 + 16 + 24, C_BASE+16, 24, 14 - EDITTEXT IDC_EDIT_C_SPT,36,22+16,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_C_HPC,94,22+16,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_C_CYL,152,22+16,28,12, WS_DISABLED - LTEXT "Sectors:",IDC_STATIC,7,22+16,27,10 - LTEXT "Heads:",IDC_STATIC,63,22+16,29,8 - LTEXT "Cylinders:",IDC_STATIC,120,22+16,32,12 - LTEXT "", IDC_TEXT_C_SIZE, 7, 38+16, 136, 12 + EDITTEXT IDC_EDIT_C_SPT,15,C_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_C_HPC,48,C_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_C_CYL,81,C_BASE+32,28,12, WS_DISABLED + LTEXT "S:",IDC_STATIC,7,C_BASE+34,8,12 + LTEXT "H:",IDC_STATIC,40,C_BASE+34,8,12 + LTEXT "C:",IDC_STATIC,73,C_BASE+34,8,12 + LTEXT "", IDC_TEXT_C_SIZE, 118, C_BASE+34, 89, 12 - LTEXT "D:",IDC_STATIC,7,60+16,27,10 - RADIOBUTTON "Hard drive", IDC_DHDD, 7+64, 60+16, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_DCDROM, 7+128, 60+16, 53, 12 , WS_TABSTOP - EDITTEXT IDC_EDIT_D_FN, 7, 60+32, 136, 12, WS_DISABLED - PUSHBUTTON "...",IDC_DFILE,7 + 136, 60+32, 16, 14 - PUSHBUTTON "New",IDC_DNEW,7 + 136 + 16, 60+32, 24, 14 - PUSHBUTTON "Eject", IDC_EJECTD, 7 + 136 + 16 + 24, 60+32, 24, 14 + LTEXT "D:",IDC_STATIC,7,D_BASE+2,27,10 + RADIOBUTTON "Hard drive", IDC_DHDD, 7+64, D_BASE, 53, 12 , WS_TABSTOP + RADIOBUTTON "CD-ROM", IDC_DCDROM, 7+128, D_BASE, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_D_FN, 7, D_BASE+16, 136, 12, WS_DISABLED + PUSHBUTTON "...",IDC_DFILE,7 + 136, D_BASE+16, 16, 14 + PUSHBUTTON "New",IDC_DNEW,7 + 136 + 16, D_BASE+16, 24, 14 + PUSHBUTTON "Eject", IDC_EJECTD, 7 + 136 + 16 + 24, D_BASE+16, 24, 14 - EDITTEXT IDC_EDIT_D_SPT,36,76+32,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_D_HPC,94,76+32,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_D_CYL,152,76+32,28,12, WS_DISABLED - LTEXT "Sectors:",IDC_STATIC,7,76+32,27,10 - LTEXT "Heads:",IDC_STATIC,63,76+32,29,8 - LTEXT "Cylinders:",IDC_STATIC,120,76+32,32,12 - LTEXT "", IDC_TEXT_D_SIZE, 7, 92+32, 136, 12 + EDITTEXT IDC_EDIT_D_SPT,15,D_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_D_HPC,48,D_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_D_CYL,81,D_BASE+32,28,12, WS_DISABLED + LTEXT "S:",IDC_STATIC,7,D_BASE+34,8,12 + LTEXT "H:",IDC_STATIC,40,D_BASE+34,8,12 + LTEXT "C:",IDC_STATIC,73,D_BASE+34,8,12 + LTEXT "", IDC_TEXT_D_SIZE, 118, D_BASE+34, 89, 12 - LTEXT "E:",IDC_STATIC,7,114+32,27,10 - RADIOBUTTON "Hard drive", IDC_EHDD, 7+64, 114+32, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_ECDROM, 7+128, 114+32, 53, 12 , WS_TABSTOP - EDITTEXT IDC_EDIT_E_FN, 7, 114+48, 136, 12, WS_DISABLED - PUSHBUTTON "...",IDC_EFILE,7 + 136, 114+48, 16, 14 - PUSHBUTTON "New",IDC_ENEW,7 + 136 + 16, 114+48, 24, 14 - PUSHBUTTON "Eject", IDC_EJECTE, 7 + 136 + 16 + 24, 114+48, 24, 14 + LTEXT "E:",IDC_STATIC,7,E_BASE+2,27,10 + RADIOBUTTON "Hard drive", IDC_EHDD, 7+64, E_BASE, 53, 12 , WS_TABSTOP + RADIOBUTTON "CD-ROM", IDC_ECDROM, 7+128, E_BASE, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_E_FN, 7, E_BASE+16, 136, 12, WS_DISABLED + PUSHBUTTON "...",IDC_EFILE,7 + 136, E_BASE+16, 16, 14 + PUSHBUTTON "New",IDC_ENEW,7 + 136 + 16, E_BASE+16, 24, 14 + PUSHBUTTON "Eject", IDC_EJECTE, 7 + 136 + 16 + 24, E_BASE+16, 24, 14 - EDITTEXT IDC_EDIT_E_SPT,36,130+48,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_E_HPC,94,130+48,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_E_CYL,152,130+48,28,12, WS_DISABLED - LTEXT "Sectors:",IDC_STATIC,7,130+48,27,10 - LTEXT "Heads:",IDC_STATIC,63,130+48,29,8 - LTEXT "Cylinders:",IDC_STATIC,120,130+48,32,12 - LTEXT "", IDC_TEXT_E_SIZE, 7, 146+48, 136, 12 + EDITTEXT IDC_EDIT_E_SPT,15,E_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_E_HPC,48,E_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_E_CYL,81,E_BASE+32,28,12, WS_DISABLED + LTEXT "S:",IDC_STATIC,7,E_BASE+34,8,12 + LTEXT "H:",IDC_STATIC,40,E_BASE+34,8,12 + LTEXT "C:",IDC_STATIC,73,E_BASE+34,8,12 + LTEXT "", IDC_TEXT_E_SIZE, 118, E_BASE+34, 89, 12 - LTEXT "F:",IDC_STATIC,7,168+48,27,10 - RADIOBUTTON "Hard drive", IDC_FHDD, 7+64, 168+48, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_FCDROM, 7+128, 168+48, 53, 12 , WS_TABSTOP - EDITTEXT IDC_EDIT_F_FN, 7, 168+64, 136, 12, WS_DISABLED - PUSHBUTTON "...",IDC_FFILE,7 + 136, 168+64, 16, 14 - PUSHBUTTON "New",IDC_FNEW,7 + 136 + 16, 168+64, 24, 14 - PUSHBUTTON "Eject", IDC_EJECTF, 7 + 136 + 16 + 24, 168+64, 24, 14 + LTEXT "F:",IDC_STATIC,7,F_BASE+2,27,10 + RADIOBUTTON "Hard drive", IDC_FHDD, 7+64, F_BASE, 53, 12 , WS_TABSTOP + RADIOBUTTON "CD-ROM", IDC_FCDROM, 7+128, F_BASE, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_F_FN, 7, F_BASE+16, 136, 12, WS_DISABLED + PUSHBUTTON "...",IDC_FFILE,7 + 136, F_BASE+16, 16, 14 + PUSHBUTTON "New",IDC_FNEW,7 + 136 + 16, F_BASE+16, 24, 14 + PUSHBUTTON "Eject", IDC_EJECTF, 7 + 136 + 16 + 24, F_BASE+16, 24, 14 - EDITTEXT IDC_EDIT_F_SPT,36,184+64,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_F_HPC,94,184+64,16,12, WS_DISABLED - EDITTEXT IDC_EDIT_F_CYL,152,184+64,28,12, WS_DISABLED - LTEXT "Sectors:",IDC_STATIC,7,184+64,27,10 - LTEXT "Heads:",IDC_STATIC,63,184+64,29,8 - LTEXT "Cylinders:",IDC_STATIC,120,184+64,32,12 - LTEXT "", IDC_TEXT_F_SIZE, 7, 200+64, 136, 12 + EDITTEXT IDC_EDIT_F_SPT,15,F_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_F_HPC,48,F_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_F_CYL,81,F_BASE+32,28,12, WS_DISABLED + LTEXT "S:",IDC_STATIC,7,F_BASE+34,8,12 + LTEXT "H:",IDC_STATIC,40,F_BASE+34,8,12 + LTEXT "C:",IDC_STATIC,73,F_BASE+34,8,12 + LTEXT "", IDC_TEXT_F_SIZE, 118, F_BASE+34, 89, 12 - LTEXT "G:",IDC_STATIC,7,222+64,27,10 - RADIOBUTTON "CD-ROM", IDC_GCDROM, 7+128, 222+64, 53, 12 , WS_TABSTOP + LTEXT "G:",IDC_STATIC,7,G_BASE+2,27,10 + RADIOBUTTON "Hard drive", IDC_GHDD, 7+64, G_BASE, 53, 12 , WS_TABSTOP + RADIOBUTTON "CD-ROM", IDC_GCDROM, 7+128, G_BASE, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_G_FN, 7, G_BASE+16, 136, 12, WS_DISABLED + PUSHBUTTON "...",IDC_GFILE,7 + 136, G_BASE+16, 16, 14 + PUSHBUTTON "New",IDC_GNEW,7 + 136 + 16, G_BASE+16, 24, 14 + PUSHBUTTON "Eject", IDC_EJECTG, 7 + 136 + 16 + 24, G_BASE+16, 24, 14 - LTEXT "H:",IDC_STATIC,7,238+64,27,10 - RADIOBUTTON "CD-ROM", IDC_HCDROM, 7+128, 238+64, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_G_SPT,15,G_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_G_HPC,48,G_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_G_CYL,81,G_BASE+32,28,12, WS_DISABLED + LTEXT "S:",IDC_STATIC,7,G_BASE+34,8,12 + LTEXT "H:",IDC_STATIC,40,G_BASE+34,8,12 + LTEXT "C:",IDC_STATIC,73,G_BASE+34,8,12 + LTEXT "", IDC_TEXT_G_SIZE, 118, G_BASE+34, 89, 12 + + LTEXT "H:",IDC_STATIC,7,H_BASE+2,27,10 + RADIOBUTTON "Hard drive", IDC_HHDD, 7+64, H_BASE, 53, 12 , WS_TABSTOP + RADIOBUTTON "CD-ROM", IDC_HCDROM, 7+128, H_BASE, 53, 12 , WS_TABSTOP + EDITTEXT IDC_EDIT_H_FN, 7, H_BASE+16, 136, 12, WS_DISABLED + PUSHBUTTON "...",IDC_HFILE,7 + 136, H_BASE+16, 16, 14 + PUSHBUTTON "New",IDC_HNEW,7 + 136 + 16, H_BASE+16, 24, 14 + PUSHBUTTON "Eject", IDC_EJECTH, 7 + 136 + 16 + 24, H_BASE+16, 24, 14 + + EDITTEXT IDC_EDIT_H_SPT,15,H_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_H_HPC,48,H_BASE+32,16,12, WS_DISABLED + EDITTEXT IDC_EDIT_H_CYL,81,H_BASE+32,28,12, WS_DISABLED + LTEXT "S:",IDC_STATIC,7,H_BASE+34,8,12 + LTEXT "H:",IDC_STATIC,40,H_BASE+34,8,12 + LTEXT "C:",IDC_STATIC,73,H_BASE+34,8,12 + LTEXT "", IDC_TEXT_H_SIZE, 118, H_BASE+34, 89, 12 END diff --git a/src/pc87306.c b/src/pc87306.c index 61aa985e2..1c0b26daa 100644 --- a/src/pc87306.c +++ b/src/pc87306.c @@ -13,7 +13,6 @@ #include "fdd.h" #include "io.h" #include "lpt.h" -#include "mouse_serial.h" #include "serial.h" #include "pc87306.h" @@ -23,29 +22,36 @@ static uint8_t pc87306_regs[29]; static uint8_t pc87306_gpio[2] = {0xFF, 0xFF}; static uint8_t tries; static uint16_t lpt_port; +static int power_down = 0; void pc87306_gpio_remove(); void pc87306_gpio_init(); void pc87306_gpio_write(uint16_t port, uint8_t val, void *priv) { + if (port & 1) + { + return; + } pc87306_gpio[port & 1] = val; } uint8_t uart_int1() { - return ((pc87306_regs[0x1C] >> 2) & 1) ? 4 : 3; + /* 0: IRQ3, 1: IRQ4 */ + return ((pc87306_regs[0x1C] >> 2) & 1) ? 3 : 4; } uint8_t uart_int2() { - return ((pc87306_regs[0x1C] >> 6) & 1) ? 4 : 3; + return ((pc87306_regs[0x1C] >> 6) & 1) ? 3 : 4; } uint8_t uart1_int() { uint8_t temp; temp = ((pc87306_regs[1] >> 2) & 1) ? 3 : 4; /* 0 = IRQ 4, 1 = IRQ 3 */ + // pclog("UART 1 set to IRQ %i\n", (pc87306_regs[0x1C] & 1) ? uart_int1() : temp); return (pc87306_regs[0x1C] & 1) ? uart_int1() : temp; } @@ -53,9 +59,39 @@ uint8_t uart2_int() { uint8_t temp; temp = ((pc87306_regs[1] >> 4) & 1) ? 3 : 4; /* 0 = IRQ 4, 1 = IRQ 3 */ + // pclog("UART 2 set to IRQ %i\n", (pc87306_regs[0x1C] & 1) ? uart_int2() : temp); return (pc87306_regs[0x1C] & 1) ? uart_int2() : temp; } +void lpt1_handler() +{ + int temp; + if (pc87306_regs[0x1B] & 0x10) + { + temp = (pc87306_regs[0x1B] & 0x20) >> 5; + if (temp) + { + lpt_port = 0x378; + } + else + { + lpt_port = 0x278; + } + } + else + { + temp = pc87306_regs[0x01] & 3; + switch (temp) + { + case 0: lpt_port = 0x378; + case 1: lpt_port = 0x3bc; + case 2: lpt_port = 0x278; + } + } + lpt1_init(lpt_port); + pc87306_regs[0x19] = lpt_port >> 2; +} + void serial1_handler() { int temp; @@ -124,7 +160,7 @@ void pc87306_write(uint16_t port, uint8_t val, void *priv) if (index) { - pc87306_curreg = val; + pc87306_curreg = val & 0x1f; // pclog("Register set to: %02X\n", val); tries = 0; return; @@ -135,10 +171,13 @@ void pc87306_write(uint16_t port, uint8_t val, void *priv) { if (pc87306_curreg <= 28) valxor = val ^ pc87306_regs[pc87306_curreg]; if (pc87306_curreg == 0xF) pc87306_gpio_remove(); - if (pc87306_curreg <= 28) pc87306_regs[pc87306_curreg] = val; - // pclog("Register %02X set to: %02X\n", pc87306_regs[pc87306_curreg], val); + if ((pc87306_curreg <= 28) && (pc87306_curreg != 8)) + { + pc87306_regs[pc87306_curreg] = val; + // pclog("Register %02X set to: %02X (was: %02X)\n", pc87306_curreg, val, pc87306_regs[pc87306_curreg]); + } tries = 0; - if (pc87306_curreg <= 28) goto process_value; + if ((pc87306_curreg <= 28) && (pc87306_curreg != 8)) goto process_value; } else { @@ -155,32 +194,10 @@ process_value: if (valxor & 1) { lpt1_remove(); - lpt2_remove(); } if ((valxor & 1) && (val & 1)) { - if (pc87306_regs[0x1B] & 0x10) - { - temp = (pc87306_regs[0x1B] & 0x20) >> 5; - if (temp) - { - lpt1_init(0x378); break; - } - else - { - lpt1_init(0x278); break; - } - } - else - { - temp = pc87306_regs[1] & 3; - switch (temp) - { - case 0: lpt1_init(0x378); break; - case 1: lpt1_init(0x3bc); break; - case 2: lpt1_init(0x278); break; - } - } + lpt1_handler(); } if (valxor & 2) @@ -189,13 +206,15 @@ process_value: if (val & 2) { serial1_handler(); - // if (mouse_always_serial) mouse_serial_init(); } } if (valxor & 4) { serial2_remove(); - if (val & 4) serial2_handler(); + if (val & 4) + { + serial2_handler(); + } } break; @@ -205,30 +224,7 @@ process_value: lpt1_remove(); if (pc87306_regs[0] & 1) { - if (pc87306_regs[0x1B] & 0x10) - { - temp = (pc87306_regs[0x1B] & 0x20) >> 5; - if (temp) - { - lpt_port = 0x378; break; - } - else - { - lpt_port = 0x278; break; - } - } - else - { - temp = val & 3; - switch (temp) - { - case 0: lpt_port = 0x378; break; - case 1: lpt_port = 0x3bc; break; - case 2: lpt_port = 0x278; break; - } - } - lpt1_init(lpt_port); - pc87306_regs[0x19] = lpt_port >> 2; + lpt1_handler(); } } @@ -239,7 +235,6 @@ process_value: if (pc87306_regs[0] & 2) { serial1_handler(); - // if (mouse_always_serial) mouse_serial_init(); } } @@ -247,11 +242,30 @@ process_value: { serial2_remove(); - if (pc87306_regs[0] & 4) serial2_handler(); + if (pc87306_regs[0] & 4) + { + serial2_handler(); + } + } + break; + case 2: + lpt1_remove(); + serial1_remove(); + serial2_remove(); + if (val & 1) + { + pc87306_regs[0] &= 0xb0; + } + else + { + lpt1_handler(); + serial1_handler(); + // serial2_handler(); + pc87306_regs[0] |= 0x4b; } break; case 9: - // pclog("Setting DENSEL polarity to: %i (before: %i)\n", (val & 0x40 ? 1 : 0), fdc_get_densel_polarity()); + pclog("Setting DENSEL polarity to: %i (before: %i)\n", (val & 0x40 ? 1 : 0), fdc_get_densel_polarity()); fdc_update_enh_mode((val & 4) ? 1 : 0); fdc_update_densel_polarity((val & 0x40) ? 1 : 0); break; @@ -267,7 +281,6 @@ process_value: if (pc87306_regs[0] & 2) { serial1_handler(); - // if (mouse_always_serial) mouse_serial_init(); } if (pc87306_regs[0] & 4) serial2_handler(); } @@ -277,6 +290,10 @@ process_value: uint8_t pc87306_gpio_read(uint16_t port, void *priv) { + if (port & 1) + { + return 0xfb; /* Bit 2 clear, since we don't emulate the on-board audio. */ + } return pc87306_gpio[port & 1]; } @@ -286,14 +303,35 @@ uint8_t pc87306_read(uint16_t port, void *priv) uint8_t index; index = (port & 1) ? 0 : 1; + tries = 0; + if (index) - return pc87306_curreg; + { + // pclog("PC87306: Read value %02X at the index register\n", pc87306_curreg & 0x1f); + return pc87306_curreg & 0x1f; + } else { if (pc87306_curreg >= 28) + { + // pclog("PC87306: Read invalid at data register, index %02X\n", pc87306_curreg); return 0xff; + } + else if (pc87306_curreg == 8) + { + // pclog("PC87306: Read ID at data register, index 08\n"); + return 0x70; + } + else if (pc87306_curreg == 5) + { + // pclog("PC87306: Read value %02X at data register, index 05\n", pc87306_regs[pc87306_curreg] | 4); + return pc87306_regs[pc87306_curreg] | 4; + } else + { + // pclog("PC87306: Read value %02X at data register, index %02X\n", pc87306_regs[pc87306_curreg], pc87306_curreg); return pc87306_regs[pc87306_curreg]; + } } } @@ -309,13 +347,19 @@ void pc87306_gpio_init() void pc87306_init() { - pc87306_regs[0] = 0xF; - pc87306_regs[1] = 0x11; + memset(pc87306_regs, 0, 29); + lpt2_remove(); + + // pc87306_regs[0] = 0xF; + pc87306_regs[0] = 0x4B; + // pc87306_regs[1] = 0x11; + pc87306_regs[1] = 0x01; pc87306_regs[3] = 2; pc87306_regs[5] = 0xD; pc87306_regs[8] = 0x70; pc87306_regs[9] = 0xFF; pc87306_regs[0xF] = 0x1E; + pc87306_regs[0x12] = 0x30; pc87306_regs[0x19] = 0xDE; pc87306_regs[0x1B] = 0x10; pc87306_regs[0x1C] = 0; diff --git a/src/pci.c b/src/pci.c index 4bbc6e221..7a2b3cbd0 100644 --- a/src/pci.c +++ b/src/pci.c @@ -33,14 +33,14 @@ uint32_t pci_cf8_read(uint16_t port, void *p) void pci_write(uint16_t port, uint8_t val, void *priv) { -// pclog("pci_write: port=%04x val=%02x %08x:%08x\n", port, val, cs, pc); + // pclog("pci_write: port=%04x val=%02x %08x:%08x\n", port, val, cs, cpu_state.pc); switch (port) { case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: if (!pci_enable) return; -// pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, pc); + // pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, cpu_state.pc); if (!pci_bus && pci_card_write[pci_card]) pci_card_write[pci_card](pci_func, pci_index | (port & 3), val, pci_priv[pci_card]); @@ -51,14 +51,14 @@ void pci_write(uint16_t port, uint8_t val, void *priv) uint8_t pci_read(uint16_t port, void *priv) { -// pclog("pci_read: port=%04x %08x:%08x\n", port, cs, pc); + // pclog("pci_read: port=%04x %08x:%08x\n", port, cs, cpu_state.pc); switch (port) { case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: if (!pci_enable) return 0xff; -// pclog("PCI read bus %i card %i func %i index %02X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3)); + // pclog("PCI read bus %i card %i func %i index %02X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3)); if (!pci_bus && pci_card_read[pci_card]) return pci_card_read[pci_card](pci_func, pci_index | (port & 3), pci_priv[pci_card]); @@ -91,7 +91,7 @@ void pci_type2_write(uint16_t port, uint8_t val, void *priv) pci_card = (port >> 8) & 0xf; pci_index = port & 0xff; -// pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, pc); + // pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, cpu_state.pc); if (!pci_bus && pci_card_write[pci_card]) pci_card_write[pci_card](pci_func, pci_index | (port & 3), val, pci_priv[pci_card]); @@ -114,7 +114,7 @@ uint8_t pci_type2_read(uint16_t port, void *priv) pci_card = (port >> 8) & 0xf; pci_index = port & 0xff; -// pclog("PCI read bus %i card %i func %i index %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), CS, pc); + // pclog("PCI read bus %i card %i func %i index %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), CS, cpu_state.pc); if (!pci_bus && pci_card_write[pci_card]) return pci_card_read[pci_card](pci_func, pci_index | (port & 3), pci_priv[pci_card]); diff --git a/src/pic.c b/src/pic.c index 66cf5f3fa..8c65326ac 100644 --- a/src/pic.c +++ b/src/pic.c @@ -9,15 +9,20 @@ int pic_intpending; void pic_updatepending() { + uint16_t temp_pending = 0; if ((pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); else pic.pend &= ~(1 << 2); pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; if (!((pic.mask | pic.mask2) & (1 << 2))) - pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2); + { + temp_pending = ((pic2.pend&~pic2.mask)&~pic2.mask2); + temp_pending <<= 8; + pic_intpending |= temp_pending; + } /* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); - pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2));*/ + pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2)); */ } @@ -45,6 +50,7 @@ void pic_update_mask(uint8_t *mask, uint8_t ins) if (ins & (1 << c)) { *mask = 0xff << c; + // pclog("Mask is: %02X\n", *mask); return; } } @@ -73,9 +79,10 @@ static void pic_autoeoi() void pic_write(uint16_t addr, uint8_t val, void *priv) { int c; -// pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc); + // if (addr&1) pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,cpu_state.pc); if (addr&1) { + // pclog("PIC ICW is: %i\n", pic.icw); switch (pic.icw) { case 0: /*OCW1*/ @@ -85,7 +92,7 @@ void pic_write(uint16_t addr, uint8_t val, void *priv) break; case 1: /*ICW2*/ pic.vector=val&0xF8; -// printf("PIC vector now %02X\n",pic.vector); + // printf("PIC vector now %02X\n",pic.vector); // output=1; if (pic.icw1&2) pic.icw=3; else pic.icw=2; @@ -96,7 +103,7 @@ void pic_write(uint16_t addr, uint8_t val, void *priv) break; case 3: /*ICW4*/ pic.icw4 = val; -// pclog("ICW4 = %02x\n", val); + // pclog("ICW4 = %02x\n", val); pic.icw=0; break; } @@ -105,6 +112,7 @@ void pic_write(uint16_t addr, uint8_t val, void *priv) { if (val&16) /*ICW1*/ { + // pclog("ICW1 = %02x\n", val); pic.mask = 0; pic.mask2=0; pic.icw=1; @@ -120,7 +128,7 @@ void pic_write(uint16_t addr, uint8_t val, void *priv) // pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7)); pic.ins&=~(1<<(val&7)); pic_update_mask(&pic.mask2, pic.ins); - if (val == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2) + if ((val&7) == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); // pic.pend&=(1<<(val&7)); // if ((val&7)==1) pollkeywaiting(); @@ -285,6 +293,7 @@ int pic_current[16]; void picint(uint16_t num) { + int old_pend = pic_intpending; if (AT && num == (1 << 2)) num = 1 << 9; // pclog("picint : %04X\n", num); @@ -299,8 +308,15 @@ void picint(uint16_t num) { pic.pend|=num; } -// pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend); +/* if (num == 0x40) +{ + pclog("picint : PEND now %02X %02X\n", pic.pend, pic2.pend); +} */ pic_updatepending(); +/* if (num == 0x40) + { + pclog("Processing FDC interrupt, pending: %s, previously pending: %s, masked: %s, masked (2): %s, T: %s, I: %s\n", (pic_intpending & num) ? "yes" : "no", (old_pend & num) ? "yes" : "no", (pic.mask & num) ? "yes" : "no", (pic.mask2 & num) ? "yes" : "no", (flags & 0x100) ? "yes" : "no", (flags&I_FLAG) ? "yes" : "no"); + } */ } void picintlevel(uint16_t num) diff --git a/src/piix.c b/src/piix.c index c6a9775ca..e1e41814c 100644 --- a/src/piix.c +++ b/src/piix.c @@ -35,10 +35,11 @@ void piix_write(int func, int addr, uint8_t val, void *priv) switch (addr) { case 0x04: - card_piix_ide[0x04] = (card_piix_ide[0x04] & ~5) | (val & 5); + card_piix_ide[0x04] = (val & 5) | 2; break; case 0x07: - card_piix_ide[0x07] = (card_piix_ide[0x07] & ~0x38) | (val & 0x38); + card_piix_ide[0x07] = val & 0x3e; + // card_piix_ide[0x07] = (card_piix_ide[0x07] & ~0x38) | (val & 0x38); break; case 0x0d: card_piix_ide[0x0d] = val; @@ -86,7 +87,7 @@ void piix_write(int func, int addr, uint8_t val, void *priv) if (card_piix_ide[0x04] & 1) io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); } -// pclog("PIIX write %02X %02X\n", addr, val); + // pclog("PIIX write %02X %02X\n", addr, val); } else { @@ -97,7 +98,32 @@ void piix_write(int func, int addr, uint8_t val, void *priv) case 0x0e: return; } - if (addr == 0x6A) + if (addr == 0x4C) + { + if (!((val ^ card_piix[addr]) & 0x80)) + { + card_piix[addr] = val; + return; + } + + card_piix[addr] = val; + if (val & 0x80) + { + if (piix_type == 3) + { + dma_alias_remove(); + } + else + { + dma_alias_remove_piix(); + } + } + else + { + dma_alias_set(); + } + } + else if (addr == 0x6A) { if (piix_type == 1) card_piix[addr] = (val & 0xFC) | (card_piix[addr] | 3); @@ -117,11 +143,11 @@ uint8_t piix_read(int func, int addr, void *priv) if (func == 1) /*IDE*/ { -// pclog("PIIX IDE read %02X %02X\n", addr, card_piix_ide[addr]); + // pclog("PIIX IDE read %02X %02X\n", addr, card_piix_ide[addr]); if (addr == 4) { - return (card_piix_ide[addr] & 4) | 3; + return (card_piix_ide[addr] & 5) | 2; } else if (addr == 5) { @@ -141,7 +167,7 @@ uint8_t piix_read(int func, int addr, void *priv) } else if (addr == 0x20) { - return card_piix_ide[addr] & 0xF1; + return (card_piix_ide[addr] & 0xF0) | 1; } else if (addr == 0x22) { @@ -470,10 +496,10 @@ void piix_bus_master_set_irq(int channel) piix_busmaster[channel].status |= 4; } -void piix_init(int card) +static int reset_reg = 0; + +void piix_reset() { - pci_add_specific(card, piix_read, piix_write, NULL); - memset(card_piix, 0, 256); card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ card_piix[0x02] = 0x2e; card_piix[0x03] = 0x12; /*82371FB (PIIX)*/ @@ -509,16 +535,10 @@ void piix_init(int card) card_piix_ide[0x3c] = 14; /* Default IRQ */ card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00; card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00; - - piix_type = 1; - - ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq); } -void piix3_init(int card) +void piix3_reset() { - pci_add_specific(card, piix_read, piix_write, NULL); - memset(card_piix, 0, 256); card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ card_piix[0x02] = 0x00; card_piix[0x03] = 0x70; /*82371SB (PIIX3)*/ @@ -556,8 +576,78 @@ void piix3_init(int card) card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00; card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00; card_piix_ide[0x44] = 0x00; +} + +static uint8_t rc_read(uint16_t port, void *priv) +{ + return reset_reg & 0xfb; +} + +static void rc_write(uint16_t port, uint8_t val, void *priv) +{ + if (!(reset_reg & 4) && (val & 4)) + { + if (reset_reg & 2) + { + // pclog("PIIX: Hard reset\n"); + resetpchard(); + } + else + { + // pclog("PIIX: Soft reset\n"); + if (piix_type == 3) + { + piix3_reset(); + } + else + { + piix_reset(); + } + resetide(); + softresetx86(); + } + } + reset_reg = val; +} + +void piix_init(int card) +{ + pci_add_specific(card, piix_read, piix_write, NULL); + + piix_reset(); + + reset_reg = 0; + + piix_type = 1; + + ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq); + + io_sethandler(0x0cf9, 0x0001, rc_read, NULL, NULL, rc_write, NULL, NULL, NULL); + + port_92_reset(); + + port_92_add(); + + dma_alias_set(); +} + +void piix3_init(int card) +{ + pci_add_specific(card, piix_read, piix_write, NULL); + + piix3_reset(); + + reset_reg = 0; piix_type = 3; ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq); + + io_sethandler(0x0cf9, 0x0001, rc_read, NULL, NULL, rc_write, NULL, NULL, NULL); + + port_92_reset(); + + port_92_add(); + + dma_alias_set(); } diff --git a/src/pit.c b/src/pit.c index a74390676..b9804eefb 100644 --- a/src/pit.c +++ b/src/pit.c @@ -59,7 +59,6 @@ void pit_reset() pit.m[0]=pit.m[1]=pit.m[2]=0; pit.ctrls[0]=pit.ctrls[1]=pit.ctrls[2]=0; pit.thit[0]=1; - spkstat=0; pit.gate[0] = pit.gate[1] = 1; pit.gate[2] = 0; pit.using_timer[0] = pit.using_timer[1] = pit.using_timer[2] = 1; diff --git a/src/plat-mouse.h b/src/plat-mouse.h index c92413702..ff248f301 100644 --- a/src/plat-mouse.h +++ b/src/plat-mouse.h @@ -9,7 +9,7 @@ extern "C" { void mouse_close(); extern int mouse_buttons; void mouse_poll_host(); - void mouse_get_mickeys(int *x, int *y); + void mouse_get_mickeys(int *x, int *y, int *z); extern int mousecapture; #ifdef __cplusplus } diff --git a/src/ps1.c b/src/ps1.c index 081527a21..3fb016b45 100644 --- a/src/ps1.c +++ b/src/ps1.c @@ -216,7 +216,10 @@ void ps1_m2121_write(uint16_t port, uint8_t val, void *p) { case 0x0092: if (val & 1) + { softresetx86(); + cpu_set_edx(); + } ps1_92 = val & ~1; mem_a20_alt = val & 2; mem_a20_recalc(); diff --git a/src/resources.h b/src/resources.h index 80abe729c..3c6f26096 100644 --- a/src/resources.h +++ b/src/resources.h @@ -5,13 +5,13 @@ #define IDM_FILE_HRESET 40001 #define IDM_FILE_EXIT 40002 #define IDM_FILE_RESET_CAD 40003 -#define IDM_DISC_A 40010 -#define IDM_DISC_B 40011 -#define IDM_EJECT_A 40012 -#define IDM_EJECT_B 40013 +#define IDM_DISC_1 40010 +#define IDM_DISC_2 40011 +#define IDM_EJECT_1 40012 +#define IDM_EJECT_2 40013 #define IDM_HDCONF 40014 -#define IDM_DISC_A_WP 40015 -#define IDM_DISC_B_WP 40016 +#define IDM_DISC_1_WP 40015 +#define IDM_DISC_2_WP 40016 #define IDM_CONFIG 40020 #define IDM_CONFIG_LOAD 40021 #define IDM_CONFIG_SAVE 40022 @@ -25,7 +25,16 @@ #define IDM_VID_FS_43 40072 #define IDM_VID_FS_SQ 40073 #define IDM_VID_FS_INT 40074 -#define IDM_VID_SCREENSHOT 40075 +#define IDM_VID_FORCE43 40075 +#define IDM_VID_OVERSCAN 40076 +#define IDM_VID_FLASH 40077 +#define IDM_VID_SCREENSHOT 40078 +#define IDM_DISC_3 40079 +#define IDM_DISC_4 40080 +#define IDM_EJECT_3 40081 +#define IDM_EJECT_4 40082 +#define IDM_DISC_3_WP 40083 +#define IDM_DISC_4_WP 40084 #define IDM_CDROM_ISO 40100 #define IDM_CDROM_EMPTY 40200 #define IDM_CDROM_REAL 40200 @@ -56,28 +65,25 @@ #define IDC_COMBO386 1005 #define IDC_COMBO486 1006 #define IDC_COMBOSND 1007 -#define IDC_COMBOCHC 1008 -#define IDC_COMBONET 1009 +#define IDC_COMBONET 1008 #define IDC_COMBOCPUM 1060 #define IDC_COMBOSPD 1061 -#define IDC_COMBODRA 1062 -#define IDC_COMBODRB 1063 +#define IDC_COMBODR1 1062 +#define IDC_COMBODR2 1063 #define IDC_COMBOJOY 1064 +#define IDC_COMBOWS 1065 +#define IDC_COMBOMOUSE 1066 +#define IDC_COMBODR3 1067 +#define IDC_COMBODR4 1068 #define IDC_CHECK1 1010 #define IDC_CHECK2 1011 #define IDC_CHECK3 1012 -#define IDC_CHECK4 1013 -#define IDC_CHECKGUS 1014 -#define IDC_CHECKSSI 1015 -#define IDC_CHECKVOODOO 1016 -#define IDC_CHECKDYNAREC 1017 -#define IDC_CHECK_AHA154X 1018 +#define IDC_CHECKGUS 1013 +#define IDC_CHECKSSI 1014 +#define IDC_CHECKVOODOO 1015 +#define IDC_CHECKDYNAREC 1016 #define IDC_STATIC 1020 -#define IDC_CHECKFORCE43 1021 -#define IDC_CHECKOVERSCAN 1022 -#define IDC_CHECKFLASH 1023 #define IDC_CHECKSYNC 1024 -#define IDC_CHECKSERIAL 1025 #define IDC_EDIT1 1030 #define IDC_EDIT2 1031 #define IDC_EDIT3 1032 @@ -103,6 +109,14 @@ #define IDC_FNEW 1063 #define IDC_EJECTE 1064 #define IDC_EJECTF 1065 +#define IDC_EDITG 1066 +#define IDC_GFILE 1067 +#define IDC_GNEW 1068 +#define IDC_EDITH 1069 +#define IDC_HFILE 1070 +#define IDC_HNEW 1071 +#define IDC_EJECTG 1072 +#define IDC_EJECTH 1073 #define IDC_MEMSPIN 1070 #define IDC_MEMTEXT 1071 #define IDC_CHDD 1080 @@ -113,8 +127,10 @@ #define IDC_ECDROM 1085 #define IDC_FHDD 1086 #define IDC_FCDROM 1087 -#define IDC_GCDROM 1088 -#define IDC_HCDROM 1089 +#define IDC_GHDD 1088 +#define IDC_GCDROM 1089 +#define IDC_HHDD 1090 +#define IDC_HCDROM 1091 #define IDC_STEXT1 1100 #define IDC_STEXT2 1101 #define IDC_STEXT3 1102 @@ -138,19 +154,30 @@ #define IDC_EDIT_F_SPT 1209 #define IDC_EDIT_F_HPC 1210 #define IDC_EDIT_F_CYL 1211 +#define IDC_EDIT_G_SPT 1212 +#define IDC_EDIT_G_HPC 1213 +#define IDC_EDIT_G_CYL 1214 +#define IDC_EDIT_H_SPT 1215 +#define IDC_EDIT_H_HPC 1216 +#define IDC_EDIT_H_CYL 1217 #define IDC_TEXT_C_SIZE 1220 #define IDC_TEXT_D_SIZE 1221 #define IDC_TEXT_E_SIZE 1222 #define IDC_TEXT_F_SIZE 1223 +#define IDC_TEXT_G_SIZE 1224 +#define IDC_TEXT_H_SIZE 1225 #define IDC_EDIT_C_FN 1230 #define IDC_EDIT_D_FN 1231 #define IDC_EDIT_E_FN 1232 #define IDC_EDIT_F_FN 1233 +#define IDC_EDIT_G_FN 1234 +#define IDC_EDIT_H_FN 1235 #define IDC_CONFIGUREVID 1200 #define IDC_CONFIGURESND 1201 #define IDC_CONFIGUREVOODOO 1202 -#define IDC_CONFIGURENET 1203 +#define IDC_CONFIGUREMOD 1203 +#define IDC_CONFIGURENET 1204 #define IDC_JOY1 1210 #define IDC_JOY2 1211 #define IDC_JOY3 1212 @@ -160,3 +187,13 @@ #define WM_RESETD3D WM_USER #define WM_LEAVEFULLSCREEN WM_USER + 1 + +#define C_BASE 6 /* End at 38. */ +#define D_BASE 60 /* End at 92. */ +#define E_BASE 114 /* End at 146. */ +#define F_BASE 168 /* End at 200. */ +#define G_BASE 222 /* End at 254. */ +#define H_BASE 276 /* End at 308. */ +#define CMD_BASE 334 +#define DLG_HEIGHT 366 + diff --git a/src/scat.c b/src/scat.c index 0c133b5fa..af50ce936 100644 --- a/src/scat.c +++ b/src/scat.c @@ -211,6 +211,7 @@ void scat_write(uint16_t port, uint8_t val, void *priv) if ((~scat_port_92 & val) & 1) { softresetx86(); + cpu_set_edx(); } scat_port_92 = val; break; diff --git a/src/scattergather.c b/src/scattergather.c index a14fcaa29..8965d4bac 100644 --- a/src/scattergather.c +++ b/src/scattergather.c @@ -16,7 +16,6 @@ static uint8_t *SegmentBufferGet(SGBUF *SegmentBuf, uint32_t Data) if (SegmentBuf->SegmentIndex == SegmentBuf->SegmentNum && !SegmentBuf->SegmentLeft) { - Data = 0; return NULL; } @@ -33,8 +32,6 @@ static uint8_t *SegmentBufferGet(SGBUF *SegmentBuf, uint32_t Data) SegmentBuf->SegmentPtrCur = SegmentBuf->SegmentPtr[SegmentBuf->SegmentIndex].Address; SegmentBuf->SegmentLeft = SegmentBuf->SegmentPtr[SegmentBuf->SegmentIndex].Length; } - - Data = DataSize; } else SegmentBuf->SegmentPtrCur = (uint8_t *)SegmentBuf->SegmentPtrCur + DataSize; @@ -76,18 +73,42 @@ uint32_t SegmentBufferCopy(SGBUF *SegmentDst, SGBUF *SegmentSrc, uint32_t Copy) uint32_t SegmentBufferCopyFromBuf(SGBUF *SegmentBuf, uint8_t *BufSrc, uint32_t Copy) { uint32_t Left = Copy; - while (Left) { - uint32_t ThisCopy = Left; - uint8_t *BufDst = SegmentBufferGet(SegmentBuf, ThisCopy); - + uint32_t ThisCopy = MIN(MIN(SegmentBuf->SegmentLeft, Left), (uint32_t)BufSrc); if (!ThisCopy) break; + uint32_t Tmp = ThisCopy; + uint8_t *BufDst = SegmentBufferGet(SegmentBuf, Tmp); + + memcpy(BufDst, BufSrc, ThisCopy); + BufDst += ThisCopy; + BufSrc -= ThisCopy; + Left -= ThisCopy; + } + + return Copy - Left; +} + +uint32_t SegmentBufferCopyToBuf(SGBUF *SegmentBuf, uint8_t *BufDst, uint32_t Copy) +{ + uint32_t Left = Copy; + while (Left) + { + uint32_t ThisCopy = MIN(MIN(SegmentBuf->SegmentLeft, Left), (uint32_t)BufDst); + if (!ThisCopy) + break; + + uint32_t Tmp = ThisCopy; + uint8_t *BufSrc = SegmentBufferGet(SegmentBuf, Tmp); + + memcpy(BufSrc, BufDst, ThisCopy); + + BufSrc += ThisCopy; + BufDst -= ThisCopy; Left -= ThisCopy; - BufSrc = (void *)((uintptr_t)BufSrc + ThisCopy); } return Copy - Left; diff --git a/src/scattergather.h b/src/scattergather.h index 4c8b98b42..99c142ae1 100644 --- a/src/scattergather.h +++ b/src/scattergather.h @@ -3,7 +3,7 @@ typedef struct SGSEG { - uint8_t Address[128*512]; + uint8_t Address[512]; uint32_t Length; } SGSEG; diff --git a/src/scsi.c b/src/scsi.c index 2ab735eac..bdf5c28c0 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -14,42 +14,6 @@ int ScsiCallback[7] = {0,0,0,0,0,0,0}; uint8_t scsi_cdrom_id = 3; /*common setting*/ -uint8_t SCSIDeviceIsPresent(SCSI *Scsi) -{ - return (scsi_cdrom_id < 7 && Scsi->LunType != SCSI_NONE); -} - -void SCSIReadTransfer(SCSI *Scsi, uint8_t Id) -{ - if (Scsi->LunType == SCSI_CDROM) - { - SCSICDROM_CallRead(Scsi, Id); - } - - pclog("SCSI: Read Transfer\n"); - SGBUF SegmentBuffer; - SegmentBufferInit(&SegmentBuffer, &Scsi->SegmentData, 1); - pfnIoRequestCopyFromBuffer(0, &SegmentBuffer, Scsi->SegmentData.Length); -} - -void SCSIWriteTransfer(SCSI *Scsi, uint8_t Id) -{ - if (Scsi->LunType == SCSI_CDROM) - { - if ((Scsi->CdbLength >= prefix_len + 4) && (page_flags[page_current] & PAGE_CHANGEABLE)) - { - mode_pages_in[page_current][Scsi->CdbLength - prefix_len - 4] = Scsi->Cdb[Scsi->CdbLength - 2]; - mode_pages_in[page_current][Scsi->CdbLength - prefix_len - 3] = Scsi->Cdb[Scsi->CdbLength - 1]; - } - } - - pclog("SCSI: Write Transfer\n"); - - SGBUF SegmentBuffer; - SegmentBufferInit(&SegmentBuffer, &Scsi->SegmentData, 1); - pfnIoRequestCopyToBuffer(0, &SegmentBuffer, Scsi->SegmentData.Length); -} - void SCSIQueryResidual(SCSI *Scsi, uint32_t *Residual) { *Residual = ScsiStatus == SCSI_STATUS_OK ? 0 : Scsi->SegmentData.Length; @@ -87,31 +51,37 @@ static uint32_t SCSICopyToBuffer(uint32_t OffSrc, SGBUF *SegmentBuffer, return Copied; } -void SCSISendCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb, uint8_t CdbLength, - uint32_t BufferLength, uint8_t *SenseBufferPointer, - uint8_t SenseBufferLength) +void SCSIWriteTransfer(SCSI *Scsi, uint8_t Id) +{ + if ((Scsi->BufferPosition >= prefix_len + 4) && (page_flags[page_current] & PAGE_CHANGEABLE)) + { + mode_pages_in[page_current][Scsi->BufferPosition - prefix_len - 4] = Scsi->SegmentData.Address[Scsi->BufferPosition - 2]; + mode_pages_in[page_current][Scsi->BufferPosition - prefix_len - 3] = Scsi->SegmentData.Address[Scsi->BufferPosition - 1]; + } + SGBUF SegmentBuffer; + SCSICopyToBuffer(Scsi->SegmentData.Length, &SegmentBuffer, 1); + pfnIoRequestCopyToBuffer(0, &SegmentBuffer, Scsi->SegmentData.Length); +} + +void SCSIReadTransfer(SCSI *Scsi, uint8_t Id) +{ + SCSICDROM_ReadCallback(Scsi, Id); + + SGBUF SegmentBuffer; + SCSICopyFromBuffer(Scsi->SegmentData.Length, &SegmentBuffer, 1); + pfnIoRequestCopyFromBuffer(0, &SegmentBuffer, Scsi->SegmentData.Length); +} + +void SCSISendCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb, uint8_t CdbLength, uint32_t DataBufferLength, uint8_t *SenseBufferPointer, uint8_t SenseBufferLength) { uint32_t i; for (i = 0; i < CdbLength; i++) - pclog("Cdb[%d]=%02X\n", i, Cdb[i]); + pclog("Cdb[%d]=0x%02X\n", i, Cdb[i]); - Scsi->SegmentData.Length = BufferLength; Scsi->CdbLength = CdbLength; - if (SCSIDeviceIsPresent(Scsi)) - { - if (Scsi->LunType == SCSI_CDROM) - { - pclog("SCSI CD-ROM in ID %d\n", Id); - SCSICDROM_RunCommand(Scsi, Id, Cdb); - } - } - else - { - pclog("SCSI Device not present\n"); - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, 0x00, 0x00); - } + pclog("SCSI CD-ROM in ID %d\n", Id); + SCSICDROM_RunCommand(Scsi, Id, Cdb, SenseBufferLength, SenseBufferPointer, DataBufferLength); } void SCSIReset(SCSI *Scsi, uint8_t Id) @@ -119,8 +89,6 @@ void SCSIReset(SCSI *Scsi, uint8_t Id) page_flags[GPMODE_CDROM_AUDIO_PAGE] &= 0xFD; /* Clear changed flag for CDROM AUDIO mode page. */ memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */ - ScsiCallback[Id] = 0; - if (scsi_cdrom_enabled) { if (cdrom_enabled) @@ -131,8 +99,7 @@ void SCSIReset(SCSI *Scsi, uint8_t Id) else { Scsi->LunType = SCSI_NONE; - } - + } pfnIoRequestCopyFromBuffer = SCSICopyFromBuffer; pfnIoRequestCopyToBuffer = SCSICopyToBuffer; diff --git a/src/scsi.h b/src/scsi.h index bdd47ac4f..4514aa104 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -181,6 +181,11 @@ extern int prev_status; #define SCSI_HDD 1 /*not present yet*/ #define SCSI_CDROM 2 +// extern sector_buffer_t cdrom_sector_buffer; + +// extern int cdrom_sector_type, cdrom_sector_flags; +// extern int cdrom_sector_size, cdrom_sector_ismsf; + typedef struct SCSI { uint8_t Cdb[32]; @@ -188,9 +193,13 @@ typedef struct SCSI SGBUF SegmentBuffer; int SectorLen; int SectorLba; + int BufferLength; int BufferPosition; SGSEG SegmentData; int LunType; + uint8_t PacketStatus; + int ReadCDCallback; + int RequestSenseEnabled; void *p; } SCSI; @@ -198,15 +207,14 @@ SCSI ScsiDrives[7]; void SCSIQueryResidual(SCSI *Scsi, uint32_t *Residual); -void SCSISendCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb, uint8_t CdbLength, - uint32_t BufferLength, uint8_t *SenseBufferPointer, - uint8_t SenseBufferLength); +void SCSISendCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb, uint8_t CdbLength, + uint32_t DataBufferLength, uint8_t *SenseBufferPointer, + uint8_t SenseBufferLength); uint32_t (*pfnIoRequestCopyFromBuffer)(uint32_t OffDst, SGBUF *SegmentBuffer, uint32_t Copy); uint32_t (*pfnIoRequestCopyToBuffer)(uint32_t OffSrc, SGBUF *SegmentBuffer, - uint32_t Copy); - + uint32_t Copy); void SCSIReadTransfer(SCSI *Scsi, uint8_t Id); void SCSIWriteTransfer(SCSI *Scsi, uint8_t Id); @@ -217,6 +225,8 @@ extern uint8_t SCSICDROMSetProfile(uint8_t *buf, uint8_t *index, uint16_t profil extern int SCSICDROMReadDVDStructure(int format, const uint8_t *packet, uint8_t *buf); extern uint32_t SCSICDROMEventStatus(uint8_t *buffer); +extern void SCSICDROM_ReadyHandler(int IsReady); extern void SCSICDROM_Insert(); +// extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); #endif \ No newline at end of file diff --git a/src/scsi_cdrom.c b/src/scsi_cdrom.c index 4aafc59e6..928f4053c 100644 --- a/src/scsi_cdrom.c +++ b/src/scsi_cdrom.c @@ -14,6 +14,49 @@ #define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) + +typedef struct __attribute__((packed)) +{ + uint8_t user_data[2048]; + uint8_t ecc[288]; +} m1_data_t; + +typedef struct __attribute__((packed)) +{ + uint8_t sub_header[8]; + uint8_t user_data[2328]; +} m2_data_t; + +typedef union __attribute__((packed)) +{ + m1_data_t m1_data; + m2_data_t m2_data; + uint8_t raw_data[2352]; +} sector_data_t; + +typedef struct __attribute__((packed)) +{ + uint8_t sync[12]; + uint8_t header[4]; + sector_data_t data; + uint8_t c2[296]; + uint8_t subchannel_raw[96]; + uint8_t subchannel_q[16]; + uint8_t subchannel_rw[96]; +} cdrom_sector_t; + +typedef union __attribute__((packed)) +{ + cdrom_sector_t cdrom_sector; + uint8_t buffer[2856]; +} sector_buffer_t; + +sector_buffer_t cdrom_sector_buffer; + +int cdrom_sector_type, cdrom_sector_flags; +int cdrom_sector_size, cdrom_sector_ismsf; + uint8_t ScsiStatus = SCSI_STATUS_OK; /* Table of all ATAPI commands and their flags, needed for the new disc change / not ready handler. */ @@ -186,10 +229,11 @@ uint32_t SCSICDROMModeSense(uint8_t *buf, uint32_t pos, uint8_t type) /* &2A - CD-ROM capabilities and mechanical status */ buf[pos++] = GPMODE_CAPABILITIES_PAGE; buf[pos++] = 0x12; /* Page length */ - buf[pos++] = 0; buf[pos++] = 0; /* CD-R methods */ - buf[pos++] = 1; /* Supports audio play, not multisession */ - buf[pos++] = 0; /* Some other stuff not supported */ - buf[pos++] = 0; /* Some other stuff not supported (lock state + eject) */ + buf[pos++] = 7; buf[pos++] = 0; /* Supports reading CD-R and CD-E */ + buf[pos++] = 0; /* Does not support writing any type of CD */ + buf[pos++] = 0x71; /* Supportsd audio play, Mode 2 Form 1, Mode 2 Form 2, and Multi-Session */ + buf[pos++] = 0x1d; /* Some other stuff not supported (lock state + eject), but C2 and CD DA are supported, as are the R-W subchannel data in both raw + and interlaved & corrected formats */ buf[pos++] = 0; /* Some other stuff not supported */ buf[pos++] = (uint8_t) (CDROM_SPEED >> 8); buf[pos++] = (uint8_t) CDROM_SPEED; /* Maximum speed */ @@ -365,12 +409,8 @@ uint32_t SCSICDROMEventStatus(uint8_t *buffer) void SCSICDROM_Insert() { + // pclog("SCSICDROM_Insert()\n"); SCSISense.UnitAttention=1; -#if 0 - SCSISense.SenseKey=SENSE_UNIT_ATTENTION; - SCSISense.Asc=ASC_MEDIUM_MAY_HAVE_CHANGED; - SCSISense.Ascq=0; -#endif } int cd_status = CD_STATUS_EMPTY; @@ -379,18 +419,328 @@ int prev_status; static uint8_t ScsiPrev; static int SenseCompleted; -void SCSIClearSense(uint8_t Command, int IgnoreUA) +static int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type) { - if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA) + if ((cdrom_sector_flags & 0x06) == 0x02) + { + /* Add error flags. */ + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 294); + cdrom_sector_size += 294; + } + else if ((cdrom_sector_flags & 0x06) == 0x04) + { + /* Add error flags. */ + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296); + cdrom_sector_size += 296; + } + else if ((cdrom_sector_flags & 0x06) == 0x06) + { + pclog("Invalid error flags\n"); + return 0; + } + + /* if (real_sector_type == 1) + { */ + if ((cdrom_sector_flags & 0x700) == 0x100) + { + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96); + cdrom_sector_size += 96; + } + else if ((cdrom_sector_flags & 0x700) == 0x200) + { + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16); + cdrom_sector_size += 16; + } + else if ((cdrom_sector_flags & 0x700) == 0x400) + { + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96); + cdrom_sector_size += 96; + } + else if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) + { + pclog("Invalid subchannel data flags\n"); + return 0; + } + // } + + // pclog("CD-ROM sector size after processing: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags); + + return cdrom_sector_size; +} + +static int SCSICDROM_LBAtoMSF_accurate(SCSI *Scsi) +{ + int temp_pos; + int m, s, f; + + temp_pos = Scsi->SectorLba; + f = temp_pos % 75; + temp_pos -= f; + temp_pos /= 75; + s = temp_pos % 60; + temp_pos -= s; + temp_pos /= 60; + m = temp_pos; + + return ((m << 16) | (s << 8) | f); +} + +static int SCSICDROMReadData(SCSI *Scsi, uint8_t *buffer) +{ + int real_sector_type; + uint8_t *b; + uint8_t *temp_b; + int is_audio; + int real_pos; + + b = temp_b = buffer; + + if (cdrom_sector_ismsf) + { + real_pos = SCSICDROM_LBAtoMSF_accurate(Scsi); + } + else + { + real_pos = Scsi->SectorLba; + } + + memset(cdrom_sector_buffer.buffer, 0, 2856); + + cdrom->readsector_raw(cdrom_sector_buffer.buffer, real_pos, cdrom_sector_ismsf); + is_audio = cdrom->is_track_audio(real_pos, cdrom_sector_ismsf); + + if (!(cdrom_sector_flags & 0xf0)) /* 0x00 and 0x08 are illegal modes */ + { + return 0; + } + + if (cdrom->is_track_audio(Scsi->SectorLba, 0)) + { + real_sector_type = 1; + + if (cdrom_sector_type > 1) + { + return 0; + } + else + { + memcpy(b, cdrom_sector_buffer.buffer, 2352); + cdrom_sector_size = 2352; + } + } + else + { + if ((cdrom_sector_flags & 0x18) == 0x08) /* EDC/ECC without user data is an illegal mode */ + { + return 0; + } + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) /* Sync */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12); + cdrom_sector_size += 12; + temp_b += 12; + } + if (cdrom_sector_flags & 0x20) /* Header */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4); + cdrom_sector_size += 4; + temp_b += 4; + } + + switch(cdrom_sector_buffer.cdrom_sector.header[3]) + { + case 1: + real_sector_type = 2; /* Mode 1 */ + break; + case 2: + real_sector_type = 3; /* Mode 2 */ + break; + default: + return 0; + } + + if (real_sector_type == 2) + { + if ((cdrom_sector_type == 0) || (cdrom_sector_type == 2)) + { + /* Mode 1 sector, expected type is 1 type. */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + if (!(cdrom_sector_flags & 0x10)) /* No user data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048); + cdrom_sector_size += 2048; + temp_b += 2048; + } + if (cdrom_sector_flags & 0x08) /* EDC/ECC */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288); + cdrom_sector_size += 288; + temp_b += 288; + } + } + else + { + return 0; + } + } + else if (real_sector_type == 3) + { + if ((cdrom_sector_type == 0) || (cdrom_sector_type == 3)) + { + /* Mode 2 sector, non-XA mode. */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + if (!(cdrom_sector_flags & 0x10)) /* No user data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 2328); + cdrom_sector_size += 8; + temp_b += 8; + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); + cdrom_sector_size += 2328; + temp_b += 2328; + } + } + else if (cdrom_sector_type == 4) + { + /* Mode 2 sector, XA Form 1 mode */ + if ((cdrom_sector_flags & 0xf0) == 0x30) + { + return 0; + } + if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8)) + { + return 0; + } + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + if ((cdrom_sector_flags & 0xf0) == 0x10) + { + /* The data is alone, include sub-header. */ + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2040); + cdrom_sector_size += 2040; + temp_b += 2040; + } + if (cdrom_sector_flags & 0x08) /* EDC/ECC */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data + 2040, 288); + cdrom_sector_size += 288; + temp_b += 288; + } + } + else if (cdrom_sector_type == 5) + { + /* Mode 2 sector, XA Form 2 mode */ + if ((cdrom_sector_flags & 0xf0) == 0x30) + { + return 0; + } + if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8)) + { + return 0; + } + /* Mode 2 sector, XA Form 1 mode */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); + cdrom_sector_size += 2328; + temp_b += 2328; + } + } + else + { + return 0; + } + } + else + { + return 0; + } + } + + // pclog("CD-ROM sector size: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags); + return cdrom_add_error_and_subchannel(b, real_sector_type); +} + +void SCSIClearSense(uint8_t Command) +{ + if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION)) { ScsiPrev=Command; - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; } } -void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) +static void SCSICDROM_CommandInit(SCSI *Scsi, uint8_t command, int req_length, int alloc_length) { + if (Scsi->BufferLength == 0xffff) + Scsi->BufferLength = 0xfffe; + + if ((Scsi->BufferLength & 1) && !(alloc_length <= Scsi->BufferLength)) + { + pclog("Odd byte count (0x%04x) to SCSI command 0x%02x, using 0x%04x\n", Scsi->SegmentData.Length, command, Scsi->BufferLength - 1); + Scsi->BufferLength--; + } + + if (alloc_length < 0) + fatal("Allocation length < 0\n"); + if (alloc_length == 0) + alloc_length = Scsi->BufferLength; + + if ((Scsi->BufferLength > req_length) || (Scsi->BufferLength == 0)) + Scsi->BufferLength = req_length; + if (Scsi->BufferLength > alloc_length) + Scsi->BufferLength = alloc_length; +} + +static void SCSICDROM_CommandReady(SCSI *Scsi, uint8_t Id, int packlen) +{ + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=packlen; + SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); + SCSIReadTransfer(Scsi, Id); +} + +void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb, uint8_t *SenseBufferPointer, uint8_t SenseBufferLength, int len) +{ + int pos; + int temp_command; + int alloc_length; + int ret; uint8_t RCdMode = 0; int c; int Msf; @@ -402,6 +752,7 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) unsigned PreambleLen; int TocFormat; uint8_t Index = 0; + int max_len; int Media; int Format; int DVDRet; @@ -412,23 +763,48 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) if (cdrom->medium_changed()) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSICDROM_Insert(); } - if ((Scsi->Cdb[0]!=GPCMD_REQUEST_SENSE) && (Scsi->Cdb[0]!=GPCMD_TEST_UNIT_READY)) + if (!cdrom->ready() && SCSISense.UnitAttention) { - /* GPCMD_TEST_UNIT_READY is NOT supposed to clear sense! */ - SCSIClearSense(Scsi->Cdb[0], 1); + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + SCSISense.UnitAttention = 0; } - - if ((SCSICommandTable[Scsi->Cdb[0]] & CHECK_READY) && !cdrom->ready()) + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (!(SCSICommandTable[Scsi->Cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); + pclog("UNIT ATTENTION: Command not allowed to pass through\n"); + SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; return; } + if (Scsi->Cdb[0] == GPCMD_READ_TOC_PMA_ATIP) + { + SCSISense.UnitAttention = 0; + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + clear the UNIT ATTENTION condition if it's set. */ + if (Scsi->Cdb[0]!=GPCMD_REQUEST_SENSE) + { + SCSIClearSense(Scsi->Cdb[0]); + } + + /* Next it's time for NOT READY. */ + if ((SCSICommandTable[Scsi->Cdb[0]] & CHECK_READY) && !cdrom->ready()) + { + pclog("Not ready\n"); + SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + return; + } + prev_status = cd_status; cd_status = cdrom->status(); if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED))) @@ -440,62 +816,83 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) SenseCompleted = 0; } - pclog("SCSI Command 0x%02X, Status %02X, Sense Key %02X, Asc %02X, Ascq %02X\n", Scsi->Cdb[0], ScsiStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); - switch (Scsi->Cdb[0]) { case GPCMD_TEST_UNIT_READY: - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); ScsiCallback[Id]=50*SCSI_TIME; break; case GPCMD_REQUEST_SENSE: - /*Will return 18 bytes of 0*/ - memset(Scsi->SegmentData.Address, 0, 512); + alloc_length = Scsi->Cdb[4]; + temp_command = Scsi->Cdb[0]; + SCSICDROM_CommandInit(Scsi, temp_command, 18, alloc_length); + + SenseBufferPointer[0]=0x80|0x70; - Scsi->SegmentData.Address[0]=0x80|0x70; - - if ((SCSISense.SenseKey >= 0) || (cd_status < CD_STATUS_PLAYING)) + if ((SCSISense.SenseKey > 0) || (cd_status < CD_STATUS_PLAYING)) { if (SenseCompleted) { - Scsi->SegmentData.Address[2]=SENSE_ILLEGAL_REQUEST; - Scsi->SegmentData.Address[12]=ASC_AUDIO_PLAY_OPERATION; - Scsi->SegmentData.Address[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + SenseBufferPointer[2]=SENSE_ILLEGAL_REQUEST; + SenseBufferPointer[12]=ASC_AUDIO_PLAY_OPERATION; + SenseBufferPointer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; } else { - Scsi->SegmentData.Address[2]=SCSISense.SenseKey; - Scsi->SegmentData.Address[12]=SCSISense.Asc; - Scsi->SegmentData.Address[13]=SCSISense.Ascq; + SenseBufferPointer[2]=SCSISense.SenseKey; + SenseBufferPointer[12]=SCSISense.Asc; + SenseBufferPointer[13]=SCSISense.Ascq; } } + else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING)) + { + SenseBufferPointer[2]=SENSE_ILLEGAL_REQUEST; + SenseBufferPointer[12]=ASC_AUDIO_PLAY_OPERATION; + SenseBufferPointer[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + } else { - Scsi->SegmentData.Address[2]=SENSE_ILLEGAL_REQUEST; - Scsi->SegmentData.Address[12]=ASC_AUDIO_PLAY_OPERATION; - Scsi->SegmentData.Address[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + if (SCSISense.UnitAttention) + { + SenseBufferPointer[2]=SENSE_UNIT_ATTENTION; + SenseBufferPointer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + SenseBufferPointer[13]=0; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + } } - Scsi->SegmentData.Address[7]=10; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, 18); - SCSIReadTransfer(Scsi, Id); + SenseBufferPointer[7]=10; - SCSIClearSense(Scsi->Cdb[0], 0); - ScsiCallback[Id]=60*SCSI_TIME; + // pclog("REQUEST SENSE start\n"); + SCSICDROM_CommandReady(Scsi, Id, (SenseBufferLength > 0) ? SenseBufferLength : 18); + + if (SenseBufferPointer[2] == SENSE_UNIT_ATTENTION) + { + /* If the last remaining sense is unit attention, clear + that condition. */ + SCSISense.UnitAttention = 0; + } + + /* Clear the sense stuff as per the spec. */ + SCSIClearSense(temp_command); break; case GPCMD_SET_SPEED: - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=50*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; + ScsiCallback[Id]=50*SCSI_TIME; break; case GPCMD_MECHANISM_STATUS: - Scsi->SegmentData.Length=(Scsi->Cdb[7]<<16)|(Scsi->Cdb[8]<<8)|Scsi->Cdb[9]; + len=(Scsi->Cdb[7]<<16)|(Scsi->Cdb[8]<<8)|Scsi->Cdb[9]; + if (len == 0) + fatal("Zero allocation length to MECHANISM STATUS not impl.\n"); + + SCSICDROM_CommandInit(Scsi, Scsi->Cdb[0], 8, alloc_length); + Scsi->SegmentData.Address[0] = 0; Scsi->SegmentData.Address[1] = 0; Scsi->SegmentData.Address[2] = 0; @@ -504,13 +901,12 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) Scsi->SegmentData.Address[5] = 1; Scsi->SegmentData.Address[6] = 0; Scsi->SegmentData.Address[7] = 0; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, 8); - SCSIReadTransfer(Scsi, Id); + // len = 8; + + SCSICDROM_CommandReady(Scsi, Id, 8); - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_READ_TOC_PMA_ATIP: @@ -520,113 +916,149 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) switch (TocFormat) { case 0: /*Normal*/ - Scsi->SegmentData.Length = Scsi->Cdb[8]|(Scsi->Cdb[7]<<8); - Scsi->SegmentData.Length = cdrom->readtoc(Scsi->SegmentData.Address, Scsi->Cdb[6], Msf, Scsi->SegmentData.Length, 0); + len = Scsi->Cdb[8]|(Scsi->Cdb[7]<<8); + len = cdrom->readtoc(Scsi->SegmentData.Address, Scsi->Cdb[6], Msf, len, 0); break; case 1: /*Multi session*/ - Scsi->SegmentData.Length = Scsi->Cdb[8]|(Scsi->Cdb[7]<<8); - Scsi->SegmentData.Length = cdrom->readtoc_session(Scsi->SegmentData.Address, Msf, Scsi->SegmentData.Length); + len = Scsi->Cdb[8]|(Scsi->Cdb[7]<<8); + len = cdrom->readtoc_session(Scsi->SegmentData.Address, Msf, len); Scsi->SegmentData.Address[0] = 0; Scsi->SegmentData.Address[1] = 0xA; break; case 2: /*Raw*/ - Scsi->SegmentData.Length = Scsi->Cdb[8]|(Scsi->Cdb[7]<<8); - Scsi->SegmentData.Length = cdrom->readtoc_raw(Scsi->SegmentData.Address, Scsi->SegmentData.Length); + len = Scsi->Cdb[8]|(Scsi->Cdb[7]<<8); + len = cdrom->readtoc_raw(Scsi->SegmentData.Address, len); break; default: - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - ScsiCallback[Id]=50*SCSI_TIME; - return; - } - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); - - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; - return; - - case GPCMD_READ_CD: - RCdMode = Scsi->Cdb[9] & 0xF8; - if ((RCdMode != 0x10) && (RCdMode != 0xF8)) - { ScsiStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; break; } - - Scsi->SectorLen=(Scsi->Cdb[6]<<16)|(Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; - Scsi->SectorLba=(Scsi->Cdb[2]<<24)|(Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; - if (RCdMode == 0x10) - cdrom->readsector(Scsi->SegmentData.Address,Scsi->SectorLba); - else - cdrom->readsector_raw(Scsi->SegmentData.Address,Scsi->SectorLba, 0); - - readcdmode = (RCdMode == 0xF8); + Scsi->BufferLength=len; + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=len; + + SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - Scsi->SectorLba++; - Scsi->SectorLen--; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, (Scsi->Cdb[9]==0x10) ? 2048 : 2352); - SCSIReadTransfer(Scsi, Id); - SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; - return; + ScsiStatus = SCSI_STATUS_OK; + break; + + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + if (Scsi->Cdb[0] == GPCMD_READ_CD_MSF) + { + Scsi->SectorLba=MSFtoLBA(Scsi->Cdb[3],Scsi->Cdb[4],Scsi->Cdb[5]); + Scsi->SectorLen=MSFtoLBA(Scsi->Cdb[6],Scsi->Cdb[7],Scsi->Cdb[8]); + + Scsi->SectorLen -= Scsi->SectorLba; + Scsi->SectorLen++; + + cdrom_sector_ismsf = 1; + } + else + { + Scsi->SectorLen=(Scsi->Cdb[6]<<16)|(Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; + Scsi->SectorLba=(Scsi->Cdb[2]<<24)|(Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; + + cdrom_sector_ismsf = 0; + } + + cdrom_sector_type = (Scsi->Cdb[1] >> 2) & 7; + cdrom_sector_flags = Scsi->Cdb[9] || (((uint32_t) Scsi->Cdb[10]) << 8); + + ret = SCSICDROMReadData(Scsi, Scsi->SegmentData.Address); + + if (!ret) + { + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; + ScsiCallback[Id]=50*SCSI_TIME; + break; + } + + pclog("SCSI Read CD command: LBA %04X, Length %04X\n", Scsi->SectorLba, Scsi->SectorLen); + + Scsi->SectorLba++; + Scsi->SectorLen--; + + Scsi->BufferLength=cdrom_sector_size; + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=cdrom_sector_size; + + SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); + SCSIReadTransfer(Scsi, Id); + + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; + return; case GPCMD_READ_6: case GPCMD_READ_10: case GPCMD_READ_12: + cdrom_sector_ismsf = 0; + + if (Scsi->Cdb[0] == GPCMD_READ_6) { - readcdmode = 0; - - if (Scsi->Cdb[0] == GPCMD_READ_6) - { - Scsi->SectorLen=Scsi->Cdb[4]; - Scsi->SectorLba=((((uint32_t) Scsi->Cdb[1]) & 0x1f)<<16)|(((uint32_t) Scsi->Cdb[2])<<8)|((uint32_t) Scsi->Cdb[3]); - } - else if (Scsi->Cdb[0] == GPCMD_READ_10) - { - Scsi->SectorLen=(Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; - Scsi->SectorLba=(Scsi->Cdb[2]<<24)|(Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; - } - else - { - Scsi->SectorLen=(((uint32_t) Scsi->Cdb[6])<<24)|(((uint32_t) Scsi->Cdb[7])<<16)|(((uint32_t) Scsi->Cdb[8])<<8)|((uint32_t) Scsi->Cdb[9]); - Scsi->SectorLba=(((uint32_t) Scsi->Cdb[2])<<24)|(((uint32_t) Scsi->Cdb[3])<<16)|(((uint32_t) Scsi->Cdb[4])<<8)|((uint32_t) Scsi->Cdb[5]); - } - - if (!Scsi->SectorLen) - { - SCSISenseCodeOk(); - ScsiCallback[Id]=20*SCSI_TIME; - break; - } - - cdrom->readsector(Scsi->SegmentData.Address, Scsi->SectorLba); - - Scsi->SectorLba++; - Scsi->SectorLen--; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, 2048); - SCSIReadTransfer(Scsi, Id); - - SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SectorLen=Scsi->Cdb[4]; + Scsi->SectorLba=((((uint32_t) Scsi->Cdb[1]) & 0x1f)<<16)|(((uint32_t) Scsi->Cdb[2])<<8)|((uint32_t) Scsi->Cdb[3]); } - return; + else if (Scsi->Cdb[0] == GPCMD_READ_10) + { + Scsi->SectorLen=(Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; + Scsi->SectorLba=(Scsi->Cdb[2]<<24)|(Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; + } + else + { + Scsi->SectorLen=(((uint32_t) Scsi->Cdb[6])<<24)|(((uint32_t) Scsi->Cdb[7])<<16)|(((uint32_t) Scsi->Cdb[8])<<8)|((uint32_t) Scsi->Cdb[9]); + Scsi->SectorLba=(((uint32_t) Scsi->Cdb[2])<<24)|(((uint32_t) Scsi->Cdb[3])<<16)|(((uint32_t) Scsi->Cdb[4])<<8)|((uint32_t) Scsi->Cdb[5]); + } + + if (!Scsi->SectorLen) + { + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; + ScsiCallback[Id]=20*SCSI_TIME; + break; + } + + cdrom_sector_type = 0; + cdrom_sector_flags = 0x10; + + pclog("SCSI Read command: LBA %04X, Length %04X\n", Scsi->SectorLba, Scsi->SectorLen); + + ret = SCSICDROMReadData(Scsi, Scsi->SegmentData.Address); + + Scsi->SectorLba++; + Scsi->SectorLen--; + + Scsi->BufferLength=2048; + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=2048; + + SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); + SCSIReadTransfer(Scsi, Id); + + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; + break; case GPCMD_READ_HEADER: if (Msf) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; break; } @@ -636,98 +1068,110 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) Scsi->SegmentData.Address[0] = 1; /*2048 bytes user data*/ Scsi->SegmentData.Address[1] = Scsi->SegmentData.Address[2] = Scsi->SegmentData.Address[3] = 0; - Scsi->SegmentData.Length = 8; + Scsi->BufferLength=8; + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=8; SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); SCSIReadTransfer(Scsi, Id); - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; return; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: + temp_command = Scsi->Cdb[0]; + if (Scsi->Cdb[0] == GPCMD_MODE_SENSE_6) { - Scsi->SegmentData.Length = Scsi->Cdb[4]; + len = Scsi->Cdb[4]; } else { - Scsi->SegmentData.Length = (Scsi->Cdb[8]|(Scsi->Cdb[7]<<8)); + len = (Scsi->Cdb[8]|(Scsi->Cdb[7]<<8)); } + Temp=Scsi->Cdb[2] & 0x3F; - memset(Scsi->SegmentData.Address, 0, Scsi->SegmentData.Length); + memset(Scsi->SegmentData.Address, 0, len); + alloc_length = len; if (!(mode_sense_pages[Temp] & IMPLEMENTED)) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - ScsiCallback[Id]=60*SCSI_TIME; - break; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + ScsiCallback[Id]=50*SCSI_TIME; + return; } if (Scsi->Cdb[0] == GPCMD_MODE_SENSE_6) { - Scsi->SegmentData.Length = SCSICDROMModeSense(Scsi->SegmentData.Address, 4, Temp); + len = SCSICDROMModeSense(Scsi->SegmentData.Address, 4, Temp); Scsi->SegmentData.Address[0] = Scsi->SegmentData.Length - 1; Scsi->SegmentData.Address[1] = 3; /*120mm data CD-ROM*/ } else { - Scsi->SegmentData.Length = SCSICDROMModeSense(Scsi->SegmentData.Address, 8, Temp); + len = SCSICDROMModeSense(Scsi->SegmentData.Address, 8, Temp); Scsi->SegmentData.Address[0] = (Scsi->SegmentData.Length - 2)>>8; Scsi->SegmentData.Address[1] = (Scsi->SegmentData.Length - 2)&255; Scsi->SegmentData.Address[2] = 3; /*120mm data CD-ROM*/ } - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); + SCSICDROM_CommandInit(Scsi, temp_command, len, alloc_length); - ScsiStatus = SCSI_STATUS_OK; + SCSICDROM_CommandReady(Scsi, Id, len); + SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; return; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: if (Scsi->Cdb[0] == GPCMD_MODE_SELECT_6) { - Scsi->SegmentData.Length = Scsi->Cdb[4]; + len = Scsi->Cdb[4]; prefix_len = 6; } else { - Scsi->SegmentData.Length = (Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; + len = (Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; prefix_len = 10; } page_current = Scsi->Cdb[2]; if (page_flags[page_current] & PAGE_CHANGEABLE) page_flags[GPMODE_CDROM_AUDIO_PAGE] |= PAGE_CHANGED; - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIWriteTransfer(Scsi, Id); - - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); + Scsi->BufferLength=len; ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=len; + + SegmentBufferCopyToBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); + SCSIWriteTransfer(Scsi, Id); + + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; return; case GPCMD_GET_CONFIGURATION: { + temp_command = Scsi->Cdb[0]; /* XXX: could result in alignment problems in some architectures */ - Scsi->SegmentData.Length = (Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; - + len = (Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; + alloc_length = len; + Index = 0; /* only feature 0 is supported */ if (Scsi->Cdb[2] != 0 || Scsi->Cdb[3] != 0) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; - break; + return; } /* @@ -737,39 +1181,39 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) * * Only a problem if the feature/profiles grow. */ - if (Scsi->SegmentData.Length > 512) /* XXX: assume 1 sector */ - Scsi->SegmentData.Length = 512; + if (alloc_length > 512) /* XXX: assume 1 sector */ + alloc_length = 512; - memset(Scsi->SegmentData.Address, 0, Scsi->SegmentData.Length); + memset(Scsi->SegmentData.Address, 0, alloc_length); /* * the number of sectors from the media tells us which profile * to use as current. 0 means there is no media */ - if (Scsi->SegmentData.Length > CD_MAX_SECTORS ) + if (len > CD_MAX_SECTORS ) { Scsi->SegmentData.Address[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; Scsi->SegmentData.Address[7] = MMC_PROFILE_DVD_ROM & 0xff; } - else if (Scsi->SegmentData.Length <= CD_MAX_SECTORS) + else if (len <= CD_MAX_SECTORS) { Scsi->SegmentData.Address[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; Scsi->SegmentData.Address[7] = MMC_PROFILE_CD_ROM & 0xff; } Scsi->SegmentData.Address[10] = 0x02 | 0x01; /* persistent and current */ - Scsi->SegmentData.Length = 12; /* headers: 8 + 4 */ - Scsi->SegmentData.Length += SCSICDROMSetProfile(Scsi->SegmentData.Address, &Index, MMC_PROFILE_DVD_ROM); - Scsi->SegmentData.Length += SCSICDROMSetProfile(Scsi->SegmentData.Address, &Index, MMC_PROFILE_CD_ROM); - Scsi->SegmentData.Address[0] = ((Scsi->SegmentData.Length-4) >> 24) & 0xff; - Scsi->SegmentData.Address[1] = ((Scsi->SegmentData.Length-4) >> 16) & 0xff; - Scsi->SegmentData.Address[2] = ((Scsi->SegmentData.Length-4) >> 8) & 0xff; - Scsi->SegmentData.Address[3] = (Scsi->SegmentData.Length-4) & 0xff; + alloc_length = 12; /* headers: 8 + 4 */ + alloc_length += SCSICDROMSetProfile(Scsi->SegmentData.Address, &Index, MMC_PROFILE_DVD_ROM); + alloc_length += SCSICDROMSetProfile(Scsi->SegmentData.Address, &Index, MMC_PROFILE_CD_ROM); + Scsi->SegmentData.Address[0] = ((alloc_length-4) >> 24) & 0xff; + Scsi->SegmentData.Address[1] = ((alloc_length-4) >> 16) & 0xff; + Scsi->SegmentData.Address[2] = ((alloc_length-4) >> 8) & 0xff; + Scsi->SegmentData.Address[3] = (alloc_length-4) & 0xff; - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); + SCSICDROM_CommandInit(Scsi, temp_command, len, alloc_length); + + SCSICDROM_CommandReady(Scsi, Id, len); - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; } break; @@ -792,7 +1236,7 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) uint8_t notification_class; uint8_t supported_events; } *gesn_event_header; - unsigned int used_len = Scsi->SegmentData.Length; + unsigned int used_len; gesn_cdb = (void *)Scsi->Cdb; gesn_event_header = (void *)Scsi->SegmentData.Address; @@ -801,8 +1245,8 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) if (!(gesn_cdb->polled & 0x01)) { /* asynchronous mode */ /* Only pollign is supported, asynchronous mode is not. */ - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; ScsiCallback[Id]=50*SCSI_TIME; return; } @@ -842,19 +1286,17 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) used_len = sizeof(*gesn_event_header); } gesn_event_header->len = used_len - sizeof(*gesn_event_header); + + SCSICDROM_CommandInit(Scsi, temp_command, len, alloc_length); + + SCSICDROM_CommandReady(Scsi, Id, len); - Scsi->SegmentData.Length = used_len; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); - - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; } break; - case GPCMD_READ_DISC_INFORMATION: + case GPCMD_READ_DISC_INFORMATION: Scsi->SegmentData.Address[1] = 32; Scsi->SegmentData.Address[2] = 0xe; /* last session complete, disc finalized */ Scsi->SegmentData.Address[3] = 1; /* first track on disc */ @@ -863,104 +1305,119 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) Scsi->SegmentData.Address[6] = 1; /* last track of last session */ Scsi->SegmentData.Address[7] = 0x20; /* unrestricted use */ Scsi->SegmentData.Address[8] = 0x00; /* CD-ROM */ - Scsi->SegmentData.Length = 34; + + len=34; + Scsi->BufferLength=len; + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=len; SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); + SCSIReadTransfer(Scsi, Id); - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_PLAY_AUDIO_10: case GPCMD_PLAY_AUDIO_12: case GPCMD_PLAY_AUDIO_MSF: /*This is apparently deprecated in the SCSI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it*/ + has been since 1995 (!). Hence I'm having to guess most of it*/ if (Scsi->Cdb[0] == GPCMD_PLAY_AUDIO_10) { - Scsi->BufferPosition = (Scsi->Cdb[2]<<24)|(Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; - Scsi->SegmentData.Length = (Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; + pos = (Scsi->Cdb[2]<<24)|(Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; + len = (Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; } else if (Scsi->Cdb[0] == GPCMD_PLAY_AUDIO_MSF) { - Scsi->BufferPosition = (Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; - Scsi->SegmentData.Length = (Scsi->Cdb[6]<<16)|(Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; + pos = (Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; + len = (Scsi->Cdb[6]<<16)|(Scsi->Cdb[7]<<8)|Scsi->Cdb[8]; } else { - Scsi->BufferPosition = (Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; - Scsi->SegmentData.Length = (Scsi->Cdb[7]<<16)|(Scsi->Cdb[8]<<8)|Scsi->Cdb[9]; + pos = (Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; + len = (Scsi->Cdb[7]<<16)|(Scsi->Cdb[8]<<8)|Scsi->Cdb[9]; } if ((cdrom_drive < 1) || (cdrom_drive == 200) || (cd_status <= CD_STATUS_DATA_ONLY) || - !cdrom->is_track_audio(Scsi->BufferPosition, (Scsi->Cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0)) + !cdrom->is_track_audio(pos, (Scsi->Cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0)) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_MODE_FOR_THIS_TRACK, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; ScsiCallback[Id]=50*SCSI_TIME; break; } - cdrom->playaudio(Scsi->BufferPosition, Scsi->SegmentData.Length, (Scsi->Cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0); - ScsiStatus = SCSI_STATUS_OK; + cdrom->playaudio(pos, len, (Scsi->Cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0); + + Scsi->PacketStatus = 3; + ScsiCallback[Id]=50*SCSI_TIME; + SCSISenseCodeOk(); - ScsiCallback[Id]=50*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_READ_SUBCHANNEL: Temp = Scsi->Cdb[2] & 0x40; if (Scsi->Cdb[3] != 1) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; break; } - Scsi->BufferPosition = 0; - Scsi->SegmentData.Address[Scsi->BufferPosition++] = 0; - Scsi->SegmentData.Address[Scsi->BufferPosition++] = 0; /*Audio status*/ - Scsi->SegmentData.Address[Scsi->BufferPosition++] = 0; Scsi->SegmentData.Address[Scsi->BufferPosition++] = 0; /*Subchannel length*/ - Scsi->SegmentData.Address[Scsi->BufferPosition++] = 1; /*Format code*/ + pos = 0; + Scsi->SegmentData.Address[pos++] = 0; + Scsi->SegmentData.Address[pos++] = 0; /*Audio status*/ + Scsi->SegmentData.Address[pos++] = 0; Scsi->SegmentData.Address[pos++] = 0; /*Subchannel length*/ + Scsi->SegmentData.Address[pos++] = 1; /*Format code*/ Scsi->SegmentData.Address[1] = cdrom->getcurrentsubchannel(&Scsi->SegmentData.Address[5], Msf); - Scsi->SegmentData.Length = 16; + len = 16; if (!Temp) - Scsi->SegmentData.Length = 4; + len = 4; + Scsi->BufferLength=len; + ScsiCallback[Id]=1000*SCSI_TIME; + Scsi->SegmentData.Length=len; + SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); SCSIReadTransfer(Scsi, Id); - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=1000*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_READ_DVD_STRUCTURE: + temp_command = Scsi->Cdb[0]; Media = Scsi->Cdb[1]; Format = Scsi->Cdb[7]; - Scsi->SegmentData.Length = (Scsi->Cdb[6]<<24)|(Scsi->Cdb[7]<<16)|(Scsi->Cdb[8]<<8)|Scsi->Cdb[9]; + len = (Scsi->Cdb[6]<<24)|(Scsi->Cdb[7]<<16)|(Scsi->Cdb[8]<<8)|Scsi->Cdb[9]; + alloc_length = len; if (Format < 0xff) { - if (Scsi->SegmentData.Length <= CD_MAX_SECTORS) + if (len <= CD_MAX_SECTORS) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INCOMPATIBLE_FORMAT, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; ScsiCallback[Id]=50*SCSI_TIME; break; } else { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; return; } } - memset(Scsi->SegmentData.Address, 0, Scsi->SegmentData.Length > 256 * 512 + 4 ? 256 * 512 + 4 : Scsi->SegmentData.Length); + memset(Scsi->SegmentData.Address, 0, alloc_length > 256 * 512 + 4 ? 256 * 512 + 4 : alloc_length); switch (Format) { @@ -972,19 +1429,17 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) if (DVDRet < 0) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, -DVDRet, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; ScsiCallback[Id]=50*SCSI_TIME; return; } else { - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); - - ScsiStatus = SCSI_STATUS_OK; + SCSICDROM_CommandInit(Scsi, temp_command, len, alloc_length); + SCSICDROM_CommandReady(Scsi, Id, len); SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; } break; } @@ -998,32 +1453,38 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) case 0x90: /* TODO: List of recognized format layers */ case 0xc0: /* TODO: Write protection status */ default: - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; - break; + return; } break; case GPCMD_START_STOP_UNIT: if (Scsi->Cdb[4]!=2 && Scsi->Cdb[4]!=3 && Scsi->Cdb[4]) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; ScsiCallback[Id]=50*SCSI_TIME; break; } if (!Scsi->Cdb[4]) cdrom->stop(); else if (Scsi->Cdb[4]==2) cdrom->eject(); else cdrom->load(); - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); ScsiCallback[Id]=50*SCSI_TIME; + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_INQUIRY: PageCode = Scsi->Cdb[2]; - Scsi->SegmentData.Length = Scsi->Cdb[4]; + max_len = Scsi->Cdb[4]; + alloc_length = max_len; + temp_command = Scsi->Cdb[0]; pclog("SCSI Inquiry Page %02X\n", Scsi->Cdb[1] & 1); if (Scsi->Cdb[1] & 1) @@ -1050,11 +1511,10 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) break; case 0x83: - if (Idx + 24 > Scsi->SegmentData.Length) + if (Idx + 24 > max_len) { - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0); - ScsiCallback[Id]=500*SCSI_TIME; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; return; } Scsi->SegmentData.Address[Idx++] = 0x02; @@ -1064,7 +1524,7 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) ScsiPadStr8(Scsi->SegmentData.Address + Idx, 20, "3097165"); /* Serial */ Idx += 20; - if (Idx + 72 > Scsi->SegmentData.Length) + if (Idx + 72 > max_len) { goto SCSIOut; } @@ -1081,9 +1541,8 @@ void SCSICDROM_RunCommand(SCSI *Scsi, uint8_t Id, uint8_t *Cdb) break; default: - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - ScsiCallback[Id]=500*SCSI_TIME; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; return; } } @@ -1111,95 +1570,95 @@ SCSIOut: Scsi->SegmentData.Address[SizeIndex] = Idx - PreambleLen; Scsi->SegmentData.Length=Idx; - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - SCSIReadTransfer(Scsi, Id); - - ScsiStatus = SCSI_STATUS_OK; + SCSICDROM_CommandInit(Scsi, temp_command, len, alloc_length); + + SCSICDROM_CommandReady(Scsi, Id, len); + SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_PREVENT_REMOVAL: - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); ScsiCallback[Id]=50*SCSI_TIME; + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_PAUSE_RESUME: if (Scsi->Cdb[8]&1) cdrom->resume(); else cdrom->pause(); - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); ScsiCallback[Id]=50*SCSI_TIME; + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; break; - case GPCMD_SEEK: - Scsi->BufferPosition = (Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; - cdrom->seek(Scsi->BufferPosition); - ScsiStatus = SCSI_STATUS_OK; + case GPCMD_SEEK: + pos = (Scsi->Cdb[3]<<16)|(Scsi->Cdb[4]<<8)|Scsi->Cdb[5]; + cdrom->seek(pos); + ScsiCallback[Id]=50*SCSI_TIME; SCSISenseCodeOk(); - ScsiCallback[Id]=50*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; - + case GPCMD_READ_CDROM_CAPACITY: + SCSICDROM_CommandInit(Scsi, temp_command, 8, 8); Size = cdrom->size(); - Scsi->SegmentData.Address[0] = (Size >> 24) & 0xFF; - Scsi->SegmentData.Address[1] = (Size >> 16) & 0xFF; - Scsi->SegmentData.Address[2] = (Size >> 8) & 0xFF; + Scsi->SegmentData.Address[0] = (Size >> 24); + Scsi->SegmentData.Address[1] = (Size >> 16); + Scsi->SegmentData.Address[2] = (Size >> 8); Scsi->SegmentData.Address[3] = Size & 0xFF; - Scsi->SegmentData.Address[4] = (2048 >> 24) & 0xFF; - Scsi->SegmentData.Address[5] = (2048 >> 16) & 0xFF; - Scsi->SegmentData.Address[6] = (2048 >> 8) & 0xFF; + Scsi->SegmentData.Address[4] = (2048 >> 24); + Scsi->SegmentData.Address[5] = (2048 >> 16); + Scsi->SegmentData.Address[6] = (2048 >> 8); Scsi->SegmentData.Address[7] = 2048 & 0xFF; Scsi->SegmentData.Length = 8; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); - - SCSIReadTransfer(Scsi, Id); - - ScsiStatus = SCSI_STATUS_OK; + len=8; + SCSICDROM_CommandReady(Scsi, Id, len); SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; break; case GPCMD_STOP_PLAY_SCAN: cdrom->stop(); - ScsiStatus = SCSI_STATUS_OK; - SCSISenseCodeOk(); ScsiCallback[Id]=50*SCSI_TIME; + SCSISenseCodeOk(); + ScsiStatus = SCSI_STATUS_OK; break; default: - ScsiStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - ScsiCallback[Id]=50*SCSI_TIME; + ScsiStatus = SCSI_STATUS_CHECK_CONDITION; + if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) + old_cdrom_drive = cdrom_drive; + ScsiCallback[Id]=50*SCSI_TIME; return; } } -void SCSICDROM_CallRead(SCSI *Scsi, uint8_t Id) + +void SCSICDROM_ReadCallback(SCSI *Scsi, uint8_t Id) { + int ret; + if (Scsi->SectorLen <= 0) { - pclog("All done - callback set\n"); - ScsiStatus = SCSI_STATUS_OK; SCSISenseCodeOk(); - ScsiCallback[Id]=20*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; return; } - pclog("Continue Read command! %i blocks left\n", Scsi->SectorLen); - - if (readcdmode) - cdrom->readsector_raw(Scsi->SegmentData.Address, Scsi->SectorLba, 0); - else - cdrom->readsector(Scsi->SegmentData.Address, Scsi->SectorLba); - - Scsi->SectorLba++; - Scsi->SectorLen--; - - SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, readcdmode ? 2352 : 2048); - ScsiStatus = SCSI_STATUS_OK; + ret = SCSICDROMReadData(Scsi, Scsi->SegmentData.Address); + pclog("SCSI Read: 0x%04X\n", Scsi->SegmentData.Address); + + Scsi->SectorLba++; + Scsi->SectorLen--; + + Scsi->BufferLength=cdrom_sector_size; + ScsiCallback[Id]=60*SCSI_TIME; + Scsi->SegmentData.Length=cdrom_sector_size; + + SegmentBufferCopyFromBuf(&Scsi->SegmentBuffer, Scsi->SegmentData.Address, Scsi->SegmentData.Length); + SCSISenseCodeOk(); - ScsiCallback[Id]=60*SCSI_TIME; + ScsiStatus = SCSI_STATUS_OK; } \ No newline at end of file diff --git a/src/serial.c b/src/serial.c index 9ea1b4f6b..3c386e035 100644 --- a/src/serial.c +++ b/src/serial.c @@ -18,14 +18,10 @@ enum SERIAL serial1, serial2; -int mousepos=-1; -int mousedelay; - void serial_reset() { serial1.iir = serial1.ier = serial1.lcr = 0; serial2.iir = serial2.ier = serial2.lcr = 0; - mousedelay = 0; serial1.fifo_read = serial1.fifo_write = 0; serial2.fifo_read = serial2.fifo_write = 0; } @@ -123,7 +119,7 @@ void serial_write(uint16_t addr, uint8_t val, void *p) if ((val & 2) && !(serial->mctrl & 2)) { if (serial->rcr_callback) - serial->rcr_callback(serial); + serial->rcr_callback(serial, serial->rcr_callback_p); // pclog("RCR raised! sending M\n"); } serial->mctrl = val; @@ -263,11 +259,17 @@ void serial1_set(uint16_t addr, int irq) serial1_remove(); io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); serial1.irq = irq; + // pclog("serial1_set(%04X, %02X)\n", addr, irq); } void serial1_remove() { + io_removehandler(0x208, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); + io_removehandler(0x228, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); + io_removehandler(0x238, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); + io_removehandler(0x2e0, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); + io_removehandler(0x338, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); } @@ -285,11 +287,17 @@ void serial2_set(uint16_t addr, int irq) serial2_remove(); io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); serial2.irq = irq; + // pclog("serial2_set(%04X, %02X)\n", addr, irq); } void serial2_remove() { - io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); - io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); - io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); - io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x208, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x228, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x238, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x2e0, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x2e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x338, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x3e8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); + io_removehandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); } diff --git a/src/serial.h b/src/serial.h index 185f8da0b..0e5995706 100644 --- a/src/serial.h +++ b/src/serial.h @@ -21,11 +21,12 @@ typedef struct int irq; - void (*rcr_callback)(void *p); + void (*rcr_callback)(struct SERIAL *serial, void *p); + void *rcr_callback_p; uint8_t fifo[256]; int fifo_read, fifo_write; - int64_t recieve_delay; + int recieve_delay; } SERIAL; extern SERIAL serial1, serial2; diff --git a/src/sio.c b/src/sio.c index f9ea10be5..a808aeb7b 100644 --- a/src/sio.c +++ b/src/sio.c @@ -37,6 +37,38 @@ void sio_write(int func, int addr, uint8_t val, void *priv) return; } card_sio[addr] = val; + if (addr == 0x40) + { + if (!((val ^ card_sio[addr]) & 0x40)) + { + return; + } + + if (val & 0x40) + { + dma_alias_remove(); + } + else + { + dma_alias_set(); + } + } + else if (addr == 0x4f) + { + if (!((val ^ card_sio[addr]) & 0x40)) + { + return; + } + + if (val & 0x40) + { + port_92_add(); + } + else + { + port_92_remove(); + } + } } } @@ -50,10 +82,10 @@ uint8_t sio_read(int func, int addr, void *priv) return card_sio[addr]; } -void sio_init(int card) +static int reset_reg = 0; + +void sio_reset() { - pci_add_specific(card, sio_read, sio_write, NULL); - memset(card_sio, 0, 256); card_sio[0x00] = 0x86; card_sio[0x01] = 0x80; /*Intel*/ card_sio[0x02] = 0x84; card_sio[0x03] = 0x04; /*82378ZB (SIO)*/ @@ -76,3 +108,45 @@ void sio_init(int card) card_sio[0xA0] = 0x08; card_sio[0xA8] = 0x0F; } + +static uint8_t rc_read(uint16_t port, void *priv) +{ + return reset_reg & 0xfb; +} + +static void rc_write(uint16_t port, uint8_t val, void *priv) +{ + if (!(reset_reg & 4) && (val & 4)) + { + if (reset_reg & 2) + { + // pclog("SIO: Hard reset\n"); + resetpchard(); + } + else + { + // pclog("SIO: Soft reset\n"); + sio_reset(); + resetide(); + softresetx86(); + } + } + reset_reg = val; +} + +void sio_init(int card) +{ + pci_add_specific(card, sio_read, sio_write, NULL); + + sio_reset(); + + reset_reg = 0; + + io_sethandler(0x0cf9, 0x0001, rc_read, NULL, NULL, rc_write, NULL, NULL, NULL); + + port_92_reset(); + + port_92_add(); + + dma_alias_set(); +} diff --git a/src/sis85c471.c b/src/sis85c471.c index ee123649c..cf8e24add 100644 --- a/src/sis85c471.c +++ b/src/sis85c471.c @@ -14,7 +14,6 @@ #include "fdd.h" #include "io.h" #include "lpt.h" -#include "mouse_serial.h" #include "serial.h" #include "sis85c471.h" @@ -63,7 +62,6 @@ process_value: { serial1_init(0x3f8, 4); serial2_init(0x2f8, 3); - mouse_serial_init(); } else { diff --git a/src/sound.h b/src/sound.h index 352d0cf41..8ef488ee1 100644 --- a/src/sound.h +++ b/src/sound.h @@ -2,8 +2,6 @@ void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p); -extern int sbtype; - extern int sound_card_current; int sound_card_available(int card); diff --git a/src/um8669f.c b/src/um8669f.c index d953bcb5f..63b7fffc4 100644 --- a/src/um8669f.c +++ b/src/um8669f.c @@ -45,7 +45,6 @@ COM2 : #include "fdc.h" #include "io.h" #include "lpt.h" -#include "mouse_serial.h" #include "serial.h" #include "um8669f.h" @@ -107,8 +106,6 @@ void um8669f_write(uint16_t port, uint8_t val, void *priv) } } - mouse_serial_init(); - lpt1_remove(); lpt2_remove(); temp = (um8669f_regs[0xc3] >> 4) & 3; diff --git a/src/vid_cga.c b/src/vid_cga.c index 2f2e47654..6b69e7aca 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -53,7 +53,7 @@ void cga_out(uint16_t addr, uint8_t val, void *p) if (((cga->cgamode ^ val) & 5) != 0) { cga->cgamode = val; - update_cga16_color(cga); + update_cga16_color(cga->cgamode); } cga->cgamode = val; return; @@ -303,7 +303,7 @@ void cga_poll(void *p) for (c = 0; c < x; c++) buffer32->line[cga->displine][c] = buffer->line[cga->displine][c] & 0xf; - Composite_Process(cga, 0, x >> 2, buffer32->line[cga->displine]); + Composite_Process(cga->cgamode, 0, x >> 2, buffer32->line[cga->displine]); } cga->sc = oldsc; @@ -455,7 +455,7 @@ void *cga_standalone_init() cga->vram = malloc(0x4000); - cga_comp_init(cga); + cga_comp_init(cga->revision); timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); diff --git a/src/vid_ega.c b/src/vid_ega.c index a60ad138d..6adee44a0 100644 --- a/src/vid_ega.c +++ b/src/vid_ega.c @@ -984,7 +984,6 @@ void *ega_standalone_init() mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); - vramp = ega->vram; io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); return ega; } @@ -1025,7 +1024,6 @@ void *cpqega_standalone_init() mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); - vramp = ega->vram; // io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); return ega; @@ -1067,7 +1065,6 @@ void *sega_standalone_init() mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, ega); timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); - vramp = ega->vram; // io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); return ega; diff --git a/src/vid_et4000w32.c b/src/vid_et4000w32.c index 42ca8eff8..d5e879443 100644 --- a/src/vid_et4000w32.c +++ b/src/vid_et4000w32.c @@ -1119,11 +1119,11 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: return 0x00; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return 0x03; + case 0x0b: return is_pentium ? 0x03 : 0x00; /* This has to be done in order to make this card work with the two 486 PCI machines. */ case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; - case 0x12: return (et4000->linearbase >> 16) & 0xff; + case 0x12: return 0x00; case 0x13: return (et4000->linearbase >> 24); case 0x30: return et4000->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ @@ -1157,9 +1157,10 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x13: - et4000->linearbase &= 0xffff0000; - et4000->linearbase = (et4000->pci_regs[0x12] << 16) | (et4000->pci_regs[0x13] << 24); - svga->crtc[0x30] = ((et4000->linearbase & 0x3fc00000) >> 22); + et4000->linearbase &= 0x00c00000; + et4000->linearbase = (et4000->pci_regs[0x13] << 24); + svga->crtc[0x30] &= 3; + svga->crtc[0x30] = ((et4000->linearbase & 0x3f000000) >> 22); et4000w32p_recalcmapping(et4000); break; diff --git a/src/vid_nv_riva128.c b/src/vid_nv_riva128.c index c1f3e7c4f..ed4ce3e42 100644 --- a/src/vid_nv_riva128.c +++ b/src/vid_nv_riva128.c @@ -106,7 +106,12 @@ typedef struct riva128_t struct { - uint32_t time; + uint32_t intr, intr_en; + + uint64_t time; + uint32_t alarm; + + uint16_t clock_mul, clock_div; } ptimer; struct @@ -177,7 +182,8 @@ typedef struct riva128_t uint8_t addr; //actually 7 bits } i2c; - int coretime; + int mtime, mfreq; + int nvtime, nvfreq; } riva128_t; @@ -302,6 +308,13 @@ static uint8_t riva128_pmc_read(uint32_t addr, void *p) case 0x000002: ret = 0x00; break; case 0x000003: ret = 0x00; break; } + else if(riva128->card_id == 0x05) switch(addr) + { + case 0x000000: ret = 0x00; break; + case 0x000001: ret = 0x40; break; + case 0x000002: ret = 0x10; break; + case 0x000003: ret = 0x00; break; + } switch(addr) { case 0x000100: ret = riva128->pmc.intr & 0xff; break; @@ -537,18 +550,80 @@ static uint8_t riva128_ptimer_read(uint32_t addr, void *p) switch(addr) { + case 0x009100: ret = riva128->ptimer.intr & 0xff; break; + case 0x009101: ret = (riva128->ptimer.intr >> 8) & 0xff; break; + case 0x009102: ret = (riva128->ptimer.intr >> 16) & 0xff; break; + case 0x009103: ret = (riva128->ptimer.intr >> 24) & 0xff; break; + case 0x009140: ret = riva128->ptimer.intr & 0xff; break; + case 0x009141: ret = (riva128->ptimer.intr_en >> 8) & 0xff; break; + case 0x009142: ret = (riva128->ptimer.intr_en >> 16) & 0xff; break; + case 0x009143: ret = (riva128->ptimer.intr_en >> 24) & 0xff; break; + case 0x009200: ret = riva128->ptimer.clock_div & 0xff; break; + case 0x009201: ret = (riva128->ptimer.clock_div >> 8) & 0xff; break; + case 0x009202: ret = (riva128->ptimer.clock_div >> 16) & 0xff; break; + case 0x009203: ret = (riva128->ptimer.clock_div >> 24) & 0xff; break; + case 0x009210: ret = riva128->ptimer.clock_mul & 0xff; break; + case 0x009211: ret = (riva128->ptimer.clock_mul >> 8) & 0xff; break; + case 0x009212: ret = (riva128->ptimer.clock_mul >> 16) & 0xff; break; + case 0x009213: ret = (riva128->ptimer.clock_mul >> 24) & 0xff; break; case 0x009400: ret = riva128->ptimer.time & 0xff; break; case 0x009401: ret = (riva128->ptimer.time >> 8) & 0xff; break; case 0x009402: ret = (riva128->ptimer.time >> 16) & 0xff; break; case 0x009403: ret = (riva128->ptimer.time >> 24) & 0xff; break; + case 0x009410: ret = (riva128->ptimer.time >> 32) & 0xff; break; + case 0x009411: ret = (riva128->ptimer.time >> 40) & 0xff; break; + case 0x009412: ret = (riva128->ptimer.time >> 48) & 0xff; break; + case 0x009413: ret = (riva128->ptimer.time >> 56) & 0xff; break; + case 0x009420: ret = riva128->ptimer.alarm & 0xff; break; + case 0x009421: ret = (riva128->ptimer.alarm >> 8) & 0xff; break; + case 0x009422: ret = (riva128->ptimer.alarm >> 16) & 0xff; break; + case 0x009423: ret = (riva128->ptimer.alarm >> 24) & 0xff; break; } - - //TODO: gross hack to make NT4 happy for the time being. - riva128->ptimer.time += 0x10000; + //TODO: NECESSARY SPEED HACK. DO NOT REMOVE THIS. + riva128->ptimer.time += 0x10000; + return ret; } +static void riva128_ptimer_write(uint32_t addr, uint32_t val, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t *svga = &riva128->svga; + pclog("RIVA 128 PTIMER write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + + switch(addr) + { + case 0x009100: + riva128->ptimer.intr &= ~val; + break; + case 0x009140: + riva128->ptimer.intr_en = val; + break; + case 0x009200: + if(!(val & 0xffff)) val = 1; + riva128->ptimer.clock_div = val & 0xffff; + break; + case 0x009210: + if((val & 0xffff) > riva128->ptimer.clock_div) val = riva128->ptimer.clock_div; + riva128->ptimer.clock_mul = val & 0xffff; + break; + case 0x009420: + riva128->ptimer.alarm = val & 0xffffffe0; + break; + } +} + +static void riva128_ptimer_interrupt(int num, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t *svga = &riva128->svga; + + riva128->ptimer.intr &= ~(1 << num); + + riva128_pmc_interrupt(20, riva128); +} + static uint8_t riva128_pfb_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -574,7 +649,7 @@ static uint8_t riva128_pfb_read(uint32_t addr, void *p) ret |= 0x04; break; } - case 0x04: + case 0x04: case 0x05: { switch(riva128->memory_size) { @@ -909,12 +984,14 @@ static void riva128_pramdac_write(uint32_t addr, uint32_t val, void *p) riva128->pramdac.nv_m = val & 0xff; riva128->pramdac.nv_n = (val >> 8) & 0xff; riva128->pramdac.nv_p = (val >> 16) & 7; + svga_recalctimings(svga); break; case 0x680504: riva128->pramdac.mpll = val; riva128->pramdac.m_m = val & 0xff; riva128->pramdac.m_n = (val >> 8) & 0xff; riva128->pramdac.m_p = (val >> 16) & 7; + svga_recalctimings(svga); break; case 0x680508: riva128->pramdac.vpll = val; @@ -1185,10 +1262,39 @@ static void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p) } } -static void riva128_poll(void *p) +static void riva128_ptimer_tick(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t *svga = &riva128->svga; + + uint64_t time = riva128->ptimer.clock_mul - riva128->ptimer.clock_div; + + time *= 1000; + + uint64_t tmp = riva128->ptimer.time; + riva128->ptimer.time += time << 5; + + if((tmp < riva128->ptimer.alarm) && (riva128->ptimer.time >= riva128->ptimer.alarm)) riva128_ptimer_interrupt(0, riva128); +} + +static void riva128_mclk_poll(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t *svga = &riva128->svga; + + if(riva128->card_id == 0x03) riva128_ptimer_tick(riva128); + + riva128->mtime += cpuclock / riva128->mfreq; +} + +static void riva128_nvclk_poll(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t *svga = &riva128->svga; + + if(riva128->card_id > 0x40 && riva128->card_id != 0x03) riva128_ptimer_tick(riva128); + + riva128->nvtime += cpuclock / riva128->nvfreq; } static uint8_t riva128_rma_in(uint16_t addr, void *p) @@ -1779,22 +1885,43 @@ static void riva128_recalctimings(svga_t *svga) } else svga_set_ramdac_type(svga, RAMDAC_6BIT);*/ + double freq; + if (((svga->miscout >> 2) & 2) == 2) { - double freq = 0; - - //if(riva128->pextdev.boot0 & 0x40) freq = 14318180.0; - freq = 13500000.0; + freq = 13500000.0; - if(riva128->pramdac.v_m == 0) freq = 0; + if(riva128->pramdac.v_m == 0) freq = 0; + else + { + freq = (freq * riva128->pramdac.v_n) / (1 << riva128->pramdac.v_p) / riva128->pramdac.v_m; + //pclog("RIVA 128 Pixel clock is %f Hz\n", freq); + } + + svga->clock = cpuclock / freq; + } + + freq = 13500.0; + + if(riva128->pramdac.nv_m == 0) freq = 0; else { - freq = (freq * riva128->pramdac.v_n) / (1 << riva128->pramdac.v_p) / riva128->pramdac.v_m; - //pclog("RIVA 128 Pixel clock is %f Hz\n", freq); + freq = (freq * riva128->pramdac.nv_n) / (1 << riva128->pramdac.nv_p) / riva128->pramdac.nv_m; + //pclog("RIVA 128 Core clock is %f Hz\n", freq); } - - svga->clock = cpuclock / freq; - } + + riva128->mfreq = freq; + + freq = 13500.0; + + if(riva128->pramdac.m_m == 0) freq = 0; + else + { + freq = (freq * riva128->pramdac.m_n) / (1 << riva128->pramdac.m_p) / riva128->pramdac.m_m; + //pclog("RIVA 128 Core clock is %f Hz\n", freq); + } + + riva128->nvfreq = freq; } static void *riva128_init() @@ -1878,6 +2005,18 @@ static void *riva128_init() pci_add(riva128_pci_read, riva128_pci_write, riva128); + //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. + riva128->pramdac.m_m = 0x03; + riva128->pramdac.m_n = 0xc2; + riva128->pramdac.m_p = 0x0d; + + riva128->pramdac.nv_m = 0x03; + riva128->pramdac.nv_n = 0xc2; + riva128->pramdac.nv_p = 0x0d; + + timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); + return riva128; } @@ -2067,6 +2206,18 @@ static void *rivatnt_init() pci_add(riva128_pci_read, rivatnt_pci_write, riva128); + //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. + riva128->pramdac.m_m = 0x03; + riva128->pramdac.m_n = 0xc2; + riva128->pramdac.m_p = 0x0d; + + riva128->pramdac.nv_m = 0x03; + riva128->pramdac.nv_n = 0xc2; + riva128->pramdac.nv_p = 0x0d; + + timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); + return riva128; } @@ -2152,3 +2303,201 @@ device_t rivatnt_device = rivatnt_config }; +static void *rivatnt2_init() +{ + riva128_t *riva128 = malloc(sizeof(riva128_t)); + memset(riva128, 0, sizeof(riva128_t)); + + riva128->card_id = 0x05; + riva128->is_nv3t = 0; + + int model = device_get_config_int("model"); + + riva128->vendor_id = 0x10de; + riva128->device_id = ((model > 1) ? 0x0029 : 0x0028); + + riva128->memory_size = device_get_config_int("memory"); + + svga_init(&riva128->svga, riva128, riva128->memory_size << 20, + riva128_recalctimings, + riva128_in, riva128_out, + NULL, NULL); + + switch(model) + { + case 0: rom_init(&riva128->bios_rom, "roms/NV5diamond.bin", 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); break; + case 1: rom_init(&riva128->bios_rom, "roms/inno3d64bit.BIN", 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); break; + case 2: rom_init(&riva128->bios_rom, "roms/creative.BIN", 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); break; + } + if (PCI) + mem_mapping_disable(&riva128->bios_rom.mapping); + + mem_mapping_add(&riva128->mmio_mapping, 0, 0, + riva128_mmio_read, + riva128_mmio_read_w, + riva128_mmio_read_l, + riva128_mmio_write, + riva128_mmio_write_w, + riva128_mmio_write_l, + NULL, + 0, + riva128); + mem_mapping_add(&riva128->linear_mapping, 0, 0, + svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + 0, + &riva128->svga); + + io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); + + // riva128->pci_regs[4] = 3; + riva128->pci_regs[4] = 7; + riva128->pci_regs[5] = 0; + riva128->pci_regs[6] = 0; + riva128->pci_regs[7] = 2; + + riva128->pci_regs[0x2c] = 0x02; + riva128->pci_regs[0x2d] = 0x11; + riva128->pci_regs[0x2e] = 0x16; + riva128->pci_regs[0x2f] = 0x10; + + riva128->pci_regs[0x30] = 0x00; + riva128->pci_regs[0x32] = 0x0c; + riva128->pci_regs[0x33] = 0x00; + + //riva128->pci_regs[0x3c] = 3; + + riva128->pmc.intr = 0; + riva128->pbus.intr = 0; + riva128->pfifo.intr = 0; + riva128->pgraph.intr = 0; + + pci_add(riva128_pci_read, rivatnt_pci_write, riva128); + + //Some bullshit default values so that the emulator won't shit itself trying to boot. These'll be overwritten by the video BIOS anyway. + riva128->pramdac.m_m = 0x03; + riva128->pramdac.m_n = 0xc2; + riva128->pramdac.m_p = 0x0d; + + riva128->pramdac.nv_m = 0x03; + riva128->pramdac.nv_n = 0xc2; + riva128->pramdac.nv_p = 0x0d; + + //timer_add(riva128_mclk_poll, &riva128->mtime, TIMER_ALWAYS_ENABLED, riva128); + //timer_add(riva128_nvclk_poll, &riva128->nvtime, TIMER_ALWAYS_ENABLED, riva128); + + return riva128; +} + +static void rivatnt2_close(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + FILE *f = fopen("vram.dmp", "wb"); + fwrite(riva128->svga.vram, 4 << 20, 1, f); + fclose(f); + + svga_close(&riva128->svga); + + free(riva128); +} + +static int rivatnt2_available() +{ + return rom_present("roms/NV5diamond.bin") || rom_present("roms/inno3d64bit.BIN") || rom_present("roms/creative.BIN"); +} + +static void rivatnt2_speed_changed(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + + svga_recalctimings(&riva128->svga); +} + +static void rivatnt2_force_redraw(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + + riva128->svga.fullchange = changeframecount; +} + +static void rivatnt2_add_status_info(char *s, int max_len, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + + svga_add_status_info(s, max_len, &riva128->svga); +} + +static device_config_t rivatnt2_config[] = +{ + { + .name = "model", + .description = "Card model", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "Vanilla TNT2", + .value = 0, + }, + { + .description = "TNT2 Pro", + .value = 1, + }, + { + .description = "TNT2 Ultra", + .value = 2, + }, + }, + .default_int = 0 + }, + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "16 MB", + .value = 16 + }, + { + .description = "32 MB", + .value = 32 + }, + { + .description = "" + } + }, + .default_int = 32 + }, + { + .type = -1 + } +}; + +device_t rivatnt2_device = +{ + "nVidia RIVA TNT2", + 0, + rivatnt2_init, + rivatnt2_close, + rivatnt2_available, + rivatnt2_speed_changed, + rivatnt2_force_redraw, + rivatnt2_add_status_info, + rivatnt2_config +}; + diff --git a/src/vid_nv_riva128.h b/src/vid_nv_riva128.h index 82e998f93..5f0f545e5 100644 --- a/src/vid_nv_riva128.h +++ b/src/vid_nv_riva128.h @@ -1,2 +1,3 @@ extern device_t riva128_device; extern device_t rivatnt_device; +extern device_t rivatnt2_device; diff --git a/src/vid_paradise.c b/src/vid_paradise.c index c7b1b3793..218f6683d 100644 --- a/src/vid_paradise.c +++ b/src/vid_paradise.c @@ -240,8 +240,6 @@ void paradise_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_highres; } -#define egacycles 1 -#define egacycles2 1 void paradise_write(uint32_t addr, uint8_t val, void *p) { paradise_t *paradise = (paradise_t *)p; diff --git a/src/vid_pcjr.c b/src/vid_pcjr.c index 38e1ff049..de5c1bc94 100644 --- a/src/vid_pcjr.c +++ b/src/vid_pcjr.c @@ -1,6 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include #include #include "ibm.h" @@ -11,7 +8,8 @@ #include "video.h" #include "vid_pcjr.h" -static int i_filt[8],q_filt[8]; +#define PCJR_RGB 0 +#define PCJR_COMPOSITE 1 typedef struct pcjr_t { @@ -36,9 +34,10 @@ typedef struct pcjr_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime; - int vidtime; + int dispontime, dispofftime, vidtime; int firstline, lastline; + + int composite; } pcjr_t; static uint8_t crtcmask[32] = @@ -82,6 +81,8 @@ void pcjr_out(uint16_t addr, uint8_t val, void *p) if (pcjr->array_index & 0x10) val &= 0x0f; pcjr->array[pcjr->array_index & 0x1f] = val; + if (!(pcjr->array_index & 0x1f)) + update_cga16_color(val); } pcjr->array_ff = !pcjr->array_ff; break; @@ -222,7 +223,7 @@ void pcjr_poll(void *p) if (pcjr->displine < pcjr->firstline) { - pcjr->firstline = pcjr->displine; + pcjr->firstline = pcjr->displine; video_wait_for_buffer(); } pcjr->lastline = pcjr->displine; @@ -431,59 +432,12 @@ void pcjr_poll(void *p) } if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16; else x = (pcjr->crtc[1] << 4) + 16; - if (cga_comp) + if (pcjr->composite) { - for (c = 0; c < x; c++) - { - y_buf[(c << 1) & 6] = ntsc_col[buffer->line[pcjr->displine][c] & 7][(c << 1) & 6] ? 0x6000 : 0; - y_buf[(c << 1) & 6] += (buffer->line[pcjr->displine][c] & 8) ? 0x3000 : 0; - i_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * i_filt[(c << 1) & 6]; - q_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * q_filt[(c << 1) & 6]; - y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7]; - i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7]; - q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7]; + for (c = 0; c < x; c++) + buffer32->line[pcjr->displine][c] = buffer->line[pcjr->displine][c] & 0xf; - y_val = y_tot >> 10; - if (y_val > 255) y_val = 255; - y_val <<= 16; - i_val = i_tot >> 12; - if (i_val > 39041) i_val = 39041; - if (i_val < -39041) i_val = -39041; - q_val = q_tot >> 12; - if (q_val > 34249) q_val = 34249; - if (q_val < -34249) q_val = -34249; - - r = (y_val + 249*i_val + 159*q_val) >> 16; - g = (y_val - 70*i_val - 166*q_val) >> 16; - b = (y_val - 283*i_val + 436*q_val) >> 16; - - y_buf[((c << 1) & 6) + 1] = ntsc_col[buffer->line[pcjr->displine][c] & 7][((c << 1) & 6) + 1] ? 0x6000 : 0; - y_buf[((c << 1) & 6) + 1] += (buffer->line[pcjr->displine][c] & 8) ? 0x3000 : 0; - i_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * i_filt[((c << 1) & 6) + 1]; - q_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * q_filt[((c << 1) & 6) + 1]; - y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7]; - i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7]; - q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7]; - - y_val = y_tot >> 10; - if (y_val > 255) y_val = 255; - y_val <<= 16; - i_val = i_tot >> 12; - if (i_val > 39041) i_val = 39041; - if (i_val < -39041) i_val = -39041; - q_val = q_tot >> 12; - if (q_val > 34249) q_val = 34249; - if (q_val < -34249) q_val = -34249; - - r = (y_val + 249*i_val + 159*q_val) >> 16; - g = (y_val - 70*i_val - 166*q_val) >> 16; - b = (y_val - 283*i_val + 436*q_val) >> 16; - if (r > 511) r = 511; - if (g > 511) g = 511; - if (b > 511) b = 511; - - ((uint32_t *)buffer32->line[pcjr->displine])[c] = makecol32(r / 2, g / 2, b / 2); - } + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[pcjr->displine]); } pcjr->sc = oldsc; if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) @@ -581,7 +535,7 @@ void pcjr_poll(void *p) // printf("Blit %i %i\n",firstline,lastline); //printf("Xsize is %i\n",xsize); - if (cga_comp) + if (pcjr->composite) video_blit_memtoscreen(0, pcjr->firstline-4, 0, (pcjr->lastline - pcjr->firstline) + 8, xsize, (pcjr->lastline - pcjr->firstline) + 8); else video_blit_memtoscreen_8(0, pcjr->firstline-4, xsize, (pcjr->lastline - pcjr->firstline) + 8); @@ -608,22 +562,18 @@ void pcjr_poll(void *p) static void *pcjr_video_init() { - int c; - int pcjr_tint = -2; + int display_type; pcjr_t *pcjr = malloc(sizeof(pcjr_t)); memset(pcjr, 0, sizeof(pcjr_t)); + display_type = model_get_config_int("display_type"); + pcjr->composite = (display_type != PCJR_RGB); + pcjr->memctrl = -1; - for (c = 0; c < 8; c++) - { - i_filt[c] = 512.0 * cos((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0); - q_filt[c] = 512.0 * sin((3.14 * (pcjr_tint + c * 4) / 16.0) - 33.0 / 180.0); - } timer_add(pcjr_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr); mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, pcjr_read, NULL, NULL, pcjr_write, NULL, NULL, NULL, 0, pcjr); io_sethandler(0x03d0, 0x0010, pcjr_in, NULL, NULL, pcjr_out, NULL, NULL, pcjr); - overscan_x = overscan_y = 16; return pcjr; } @@ -652,3 +602,45 @@ device_t pcjr_video_device = NULL, NULL }; + +static device_config_t pcjr_config[] = +{ + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "RGB", + .value = PCJR_RGB + }, + { + .description = "Composite", + .value = PCJR_COMPOSITE + }, + { + .description = "" + } + }, + .default_int = PCJR_RGB + }, + { + .type = -1 + } +}; + +/*This isn't really a device as such - more of a convenient way to hook in the + config information*/ +device_t pcjr_device = +{ + "IBM PCjr", + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcjr_config +}; diff --git a/src/vid_pcjr.h b/src/vid_pcjr.h index 786b6c889..6bb47bc07 100644 --- a/src/vid_pcjr.h +++ b/src/vid_pcjr.h @@ -1,4 +1,2 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ extern device_t pcjr_video_device; +extern device_t pcjr_device; diff --git a/src/vid_svga.c b/src/vid_svga.c index 0212dde34..d0090aa75 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -235,7 +235,7 @@ void svga_out(uint16_t addr, uint8_t val, void *p) if (svga->ramdac_type == RAMDAC_8BIT) svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b); else - svga->pallook[svga->dac_write] = makecol32((svga->vgapal[svga->dac_write].r & 0x3f) * 4, (svga->vgapal[svga->dac_write].g & 0x3f) * 4, (svga->vgapal[svga->dac_write].b & 0x3f) * 4); + svga->pallook[svga->dac_write] = makecol32(video_6to8[svga->vgapal[svga->dac_write].r], video_6to8[svga->vgapal[svga->dac_write].g], video_6to8[svga->vgapal[svga->dac_write].b]); svga->dac_pos = 0; svga->dac_write = (svga->dac_write + 1) & 255; break; @@ -408,7 +408,7 @@ void svga_set_ramdac_type(svga_t *svga, int type) if (svga->ramdac_type == RAMDAC_8BIT) svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); else - svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, (svga->vgapal[c].g & 0x3f) * 4, (svga->vgapal[c].b & 0x3f) * 4); + svga->pallook[c] = makecol32(video_6to8[svga->vgapal[c].r], video_6to8[svga->vgapal[c].g], video_6to8[svga->vgapal[c].b]); } } } @@ -919,7 +919,6 @@ int svga_init(svga_t *svga, void *p, int memsize, mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, 0, svga); timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); - vramp = svga->vram; svga_pri = svga; @@ -942,8 +941,6 @@ void svga_close(svga_t *svga) svga_pri = NULL; } -#define egacycles 1 -#define egacycles2 1 void svga_write(uint32_t addr, uint8_t val, void *p) { svga_t *svga = (svga_t *)p; diff --git a/src/vid_tandy.c b/src/vid_tandy.c index 6a438e672..0cc52235d 100644 --- a/src/vid_tandy.c +++ b/src/vid_tandy.c @@ -1,6 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ #include #include #include "ibm.h" @@ -10,8 +7,10 @@ #include "timer.h" #include "video.h" #include "vid_tandy.h" +#include "dosbox/vid_cga_comp.h" -static int i_filt[8],q_filt[8]; +#define TANDY_RGB 0 +#define TANDY_COMPOSITE 1 typedef struct tandy_t { @@ -38,9 +37,10 @@ typedef struct tandy_t int vsynctime, vadj; uint16_t ma, maback; - int dispontime, dispofftime; - int vidtime; + int dispontime, dispofftime, vidtime; int firstline, lastline; + + int composite; } tandy_t; static uint8_t crtcmask[32] = @@ -76,6 +76,7 @@ void tandy_out(uint16_t addr, uint8_t val, void *p) return; case 0x3d8: tandy->mode = val; + update_cga16_color(tandy->mode); return; case 0x3d9: tandy->col = val; @@ -471,60 +472,15 @@ void tandy_poll(void *p) } if (tandy->mode & 1) x = (tandy->crtc[1] << 3) + 16; else x = (tandy->crtc[1] << 4) + 16; - if (cga_comp) + + if (tandy->composite) { - for (c = 0; c < x; c++) - { - y_buf[(c << 1) & 6] = ntsc_col[buffer->line[tandy->displine][c] & 7][(c << 1) & 6] ? 0x6000 : 0; - y_buf[(c << 1) & 6] += (buffer->line[tandy->displine][c] & 8) ? 0x3000 : 0; - i_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * i_filt[(c << 1) & 6]; - q_buf[(c << 1) & 6] = y_buf[(c << 1) & 6] * q_filt[(c << 1) & 6]; - y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7]; - i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7]; - q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7]; + for (c = 0; c < x; c++) + buffer32->line[tandy->displine][c] = buffer->line[tandy->displine][c] & 0xf; - y_val = y_tot >> 10; - if (y_val > 255) y_val = 255; - y_val <<= 16; - i_val = i_tot >> 12; - if (i_val > 39041) i_val = 39041; - if (i_val < -39041) i_val = -39041; - q_val = q_tot >> 12; - if (q_val > 34249) q_val = 34249; - if (q_val < -34249) q_val = -34249; - - r = (y_val + 249*i_val + 159*q_val) >> 16; - g = (y_val - 70*i_val - 166*q_val) >> 16; - b = (y_val - 283*i_val + 436*q_val) >> 16; - - y_buf[((c << 1) & 6) + 1] = ntsc_col[buffer->line[tandy->displine][c] & 7][((c << 1) & 6) + 1] ? 0x6000 : 0; - y_buf[((c << 1) & 6) + 1] += (buffer->line[tandy->displine][c] & 8) ? 0x3000 : 0; - i_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * i_filt[((c << 1) & 6) + 1]; - q_buf[((c << 1) & 6) + 1] = y_buf[((c << 1) & 6) + 1] * q_filt[((c << 1) & 6) + 1]; - y_tot = y_buf[0] + y_buf[1] + y_buf[2] + y_buf[3] + y_buf[4] + y_buf[5] + y_buf[6] + y_buf[7]; - i_tot = i_buf[0] + i_buf[1] + i_buf[2] + i_buf[3] + i_buf[4] + i_buf[5] + i_buf[6] + i_buf[7]; - q_tot = q_buf[0] + q_buf[1] + q_buf[2] + q_buf[3] + q_buf[4] + q_buf[5] + q_buf[6] + q_buf[7]; - - y_val = y_tot >> 10; - if (y_val > 255) y_val = 255; - y_val <<= 16; - i_val = i_tot >> 12; - if (i_val > 39041) i_val = 39041; - if (i_val < -39041) i_val = -39041; - q_val = q_tot >> 12; - if (q_val > 34249) q_val = 34249; - if (q_val < -34249) q_val = -34249; - - r = (y_val + 249*i_val + 159*q_val) >> 16; - g = (y_val - 70*i_val - 166*q_val) >> 16; - b = (y_val - 283*i_val + 436*q_val) >> 16; - if (r > 511) r = 511; - if (g > 511) g = 511; - if (b > 511) b = 511; - - ((uint32_t *)buffer32->line[tandy->displine])[c] = makecol32(r / 2, g / 2, b / 2); - } + Composite_Process(tandy->mode, 0, x >> 2, buffer32->line[tandy->displine]); } + tandy->sc = oldsc; if (tandy->vc == tandy->crtc[7] && !tandy->sc) { @@ -619,7 +575,7 @@ void tandy_poll(void *p) // printf("Blit %i %i\n",firstline,lastline); //printf("Xsize is %i\n",xsize); - if (cga_comp) + if (tandy->composite) video_blit_memtoscreen(0, tandy->firstline-4, 0, (tandy->lastline - tandy->firstline) + 8, xsize, (tandy->lastline - tandy->firstline) + 8); else video_blit_memtoscreen_8(0, tandy->firstline-4, xsize, (tandy->lastline - tandy->firstline) + 8); @@ -677,19 +633,17 @@ void tandy_poll(void *p) void *tandy_init() { - int c; - int tandy_tint = -2; + int display_type; tandy_t *tandy = malloc(sizeof(tandy_t)); memset(tandy, 0, sizeof(tandy_t)); + display_type = model_get_config_int("display_type"); + tandy->composite = (display_type != TANDY_RGB); + + cga_comp_init(1); tandy->memctrl = -1; tandy->base = (mem_size - 128) * 1024; - for (c = 0; c < 8; c++) - { - i_filt[c] = 512.0 * cos((3.14 * (tandy_tint + c * 4) / 16.0) - 33.0 / 180.0); - q_filt[c] = 512.0 * sin((3.14 * (tandy_tint + c * 4) / 16.0) - 33.0 / 180.0); - } timer_add(tandy_poll, &tandy->vidtime, TIMER_ALWAYS_ENABLED, tandy); mem_mapping_add(&tandy->mapping, 0xb8000, 0x08000, tandy_read, NULL, NULL, tandy_write, NULL, NULL, NULL, 0, tandy); mem_mapping_add(&tandy->ram_mapping, 0x80000, 0x20000, tandy_ram_read, NULL, NULL, tandy_ram_write, NULL, NULL, NULL, 0, tandy); @@ -698,8 +652,6 @@ void *tandy_init() io_sethandler(0x03d0, 0x0010, tandy_in, NULL, NULL, tandy_out, NULL, NULL, tandy); io_sethandler(0x00a0, 0x0001, tandy_in, NULL, NULL, tandy_out, NULL, NULL, tandy); tandy->b8000_mask = 0x3fff; - - overscan_x = overscan_y = 16; return tandy; } @@ -729,3 +681,57 @@ device_t tandy_device = NULL, NULL }; + +static device_config_t tandy_config[] = +{ + { + .name = "display_type", + .description = "Display type", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "RGB", + .value = TANDY_RGB + }, + { + .description = "Composite", + .value = TANDY_COMPOSITE + }, + { + .description = "" + } + }, + .default_int = TANDY_RGB + }, + { + .type = -1 + } +}; + +/*These aren't really devices as such - more of a convenient way to hook in the + config information*/ +device_t tandy1000_device = +{ + "Tandy 1000", + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + tandy_config +}; +device_t tandy1000hx_device = +{ + "Tandy 1000HX", + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + tandy_config +}; diff --git a/src/vid_tandy.h b/src/vid_tandy.h index 3e5221af9..524ad023f 100644 --- a/src/vid_tandy.h +++ b/src/vid_tandy.h @@ -1,4 +1,4 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ extern device_t tandy_device; + +extern device_t tandy1000_device; +extern device_t tandy1000hx_device; diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index 5e8667420..d84de678d 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -11,6 +11,8 @@ #include "vid_voodoo.h" #include "vid_voodoo_dither.h" +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + #define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x))) #define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x))) @@ -300,7 +302,8 @@ typedef struct voodoo_t volatile int params_read_idx[2], params_write_idx; uint32_t cmdfifo_base, cmdfifo_end; - int cmdfifo_rp, cmdfifo_depth_rd, cmdfifo_depth_wr; + int cmdfifo_rp; + volatile int cmdfifo_depth_rd, cmdfifo_depth_wr; uint32_t cmdfifo_amin, cmdfifo_amax; uint32_t sSetupMode; @@ -318,6 +321,9 @@ typedef struct voodoo_t int flush; int scrfilter; + int scrfilterEnabled; + int scrfilterThreshold; + int scrfilterThresholdOld; uint32_t last_write_addr; @@ -368,9 +374,12 @@ typedef struct voodoo_t int buffer_cutoff; int read_time, write_time, burst_time; - - uint16_t thefilter[1024][1024]; // pixel filter, feeding from one or two - uint16_t thefilterg[1024][1024]; // for green + + int wake_timer; + + uint8_t thefilter[256][256]; // pixel filter, feeding from one or two + uint8_t thefilterg[256][256]; // for green + uint8_t thefilterb[256][256]; // for blue /* the voodoo adds purple lines for some reason */ uint16_t purpleline[1024]; @@ -548,6 +557,8 @@ enum SST_clutData = 0x228, SST_dacData = 0x22c, + SST_scrFilter = 0x230, + SST_hvRetrace = 0x240, SST_fbiInit5 = 0x244, SST_fbiInit6 = 0x248, @@ -831,7 +842,8 @@ enum CC_MSELECT_CLOCAL = 1, CC_MSELECT_AOTHER = 2, CC_MSELECT_ALOCAL = 3, - CC_MSELECT_TEX = 4 + CC_MSELECT_TEX = 4, + CC_MSELECT_TEXRGB = 5 }; enum @@ -961,6 +973,8 @@ enum #define TEXTUREMODE_LOCAL_MASK 0x00643000 #define TEXTUREMODE_LOCAL 0x00241000 +static void voodoo_threshold_check(voodoo_t *voodoo); + static void voodoo_update_ncc(voodoo_t *voodoo, int tmu) { int tbl; @@ -1841,18 +1855,20 @@ static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, v if (params->textureMode[tmu] & 1) { int64_t _w = 0; - if (state->tmu1_w) - _w = (int64_t)((1ULL << 48) / state->tmu1_w); if (tmu) { - state->tex_s = (int32_t)(((state->tmu1_s >> 14) * _w) >> 30); - state->tex_t = (int32_t)(((state->tmu1_t >> 14) * _w) >> 30); + if (state->tmu1_w) + _w = (int64_t)((1ULL << 48) / state->tmu1_w); + state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); } else { - state->tex_s = (int32_t)(((state->tmu0_s >> 14) * _w) >> 30); - state->tex_t = (int32_t)(((state->tmu0_t >> 14) * _w) >> 30); + if (state->tmu0_w) + _w = (int64_t)((1ULL << 48) / state->tmu0_w); + state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); } state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8)); @@ -2443,7 +2459,7 @@ static inline voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *para factor_a = state->lod_frac[0]; break; } - if (!a_reverse) + if (a_reverse) a = (a * ((factor_a ^ 0xff) + 1)) >> 8; else a = (a * (factor_a + 1)) >> 8; @@ -2953,6 +2969,11 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood msel_g = state->tex_a[0]; msel_b = state->tex_a[0]; break; + case CC_MSELECT_TEXRGB: + msel_r = state->tex_r[0]; + msel_g = state->tex_g[0]; + msel_b = state->tex_b[0]; + break; default: fatal("Bad cc_mselect %i\n", cc_mselect); @@ -3433,7 +3454,8 @@ enum SETUPMODE_STRIP_MODE = (1 << 16), SETUPMODE_CULLING_ENABLE = (1 << 17), - SETUPMODE_CULLING_SIGN = (1 << 18) + SETUPMODE_CULLING_SIGN = (1 << 18), + SETUPMODE_DISABLE_PINGPONG = (1 << 19) }; static void triangle_setup(voodoo_t *voodoo) @@ -3511,7 +3533,13 @@ static void triangle_setup(voodoo_t *voodoo) area = dxAB * dyBC - dxBC * dyAB; if (area == 0.0) + { + if ((voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) && + !(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG)) + voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN; + return; + } dxAB /= area; dxBC /= area; @@ -3520,14 +3548,18 @@ static void triangle_setup(voodoo_t *voodoo) if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) { + int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN; int sign = (area < 0.0); + if (!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG)) + voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN; + if (reverse_cull) sign = !sign; - if ((voodoo->sSetupMode & SETUPMODE_CULLING_SIGN) && sign) + if (cull_sign && sign) return; - if (!(voodoo->sSetupMode & SETUPMODE_CULLING_SIGN) && !sign) + if (!cull_sign && !sign) return; } @@ -3964,6 +3996,24 @@ enum CHIP_TREX2 = 0x8 }; +static void wait_for_swap_complete(voodoo_t *voodoo) +{ + while (voodoo->swap_pending) + { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + if ((voodoo->swap_pending && voodoo->flush) || FIFO_ENTRIES == 65536) + { + /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/ + memset(voodoo->dirty_line, 1, 1024); + voodoo->front_offset = voodoo->params.front_offset; + voodoo->swap_count--; + voodoo->swap_pending = 0; + break; + } + } +} + static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) { voodoo_t *voodoo = (voodoo_t *)p; @@ -4011,26 +4061,22 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) voodoo->front_offset = voodoo->params.front_offset; voodoo->swap_count--; } + else if (TRIPLE_BUFFER) + { + if (voodoo->swap_pending) + wait_for_swap_complete(voodoo); + + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->params.front_offset; + voodoo->swap_pending = 1; + } else { voodoo->swap_interval = (val >> 1) & 0xff; voodoo->swap_offset = voodoo->params.front_offset; voodoo->swap_pending = 1; - while (voodoo->swap_pending) - { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - if ((voodoo->swap_pending && voodoo->flush) || FIFO_ENTRIES == 65536) - { - /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/ - memset(voodoo->dirty_line, 1, 1024); - voodoo->front_offset = voodoo->params.front_offset; - voodoo->swap_count--; - voodoo->swap_pending = 0; - break; - } - } + wait_for_swap_complete(voodoo); } voodoo->cmd_read++; break; @@ -5169,6 +5215,10 @@ static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) alpha_data = colour_data.a; write_mask = LFB_WRITE_COLOUR; break; + case LFB_FORMAT_DEPTH: + depth_data = val; + write_mask = LFB_WRITE_DEPTH; + break; default: fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode); @@ -5446,8 +5496,32 @@ static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; } +#define WAKE_DELAY (TIMER_USEC * 100) static inline void wake_fifo_thread(voodoo_t *voodoo) { + if (!voodoo->wake_timer) + { + /*Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work.*/ + timer_process(); + voodoo->wake_timer = WAKE_DELAY; + timer_update_outstanding(); + } +} + +static inline void wake_fifo_thread_now(voodoo_t *voodoo) +{ + thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +static void voodoo_wake_timer(void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + + voodoo->wake_timer = 0; + thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } @@ -5487,7 +5561,7 @@ static uint16_t voodoo_readw(uint32_t addr, void *p) voodoo->flush = 1; while (!FIFO_EMPTY) { - wake_fifo_thread(voodoo); + wake_fifo_thread_now(voodoo); thread_wait_event(voodoo->fifo_not_full_event, 1); } wait_for_render_thread_idle(voodoo); @@ -5517,7 +5591,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) voodoo->flush = 1; while (!FIFO_EMPTY) { - wake_fifo_thread(voodoo); + wake_fifo_thread_now(voodoo); thread_wait_event(voodoo->fifo_not_full_event, 1); } wait_for_render_thread_idle(voodoo); @@ -5547,7 +5621,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) voodoo->flush = 1; while (!FIFO_EMPTY) { - wake_fifo_thread(voodoo); + wake_fifo_thread_now(voodoo); thread_wait_event(voodoo->fifo_not_full_event, 1); } wait_for_render_thread_idle(voodoo); @@ -5708,7 +5782,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) *(uint32_t *)&voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val; voodoo->cmdfifo_depth_wr++; if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20) - thread_set_event(voodoo->wake_fifo_thread); + wake_fifo_thread(voodoo); } else switch (addr & 0x3fc) { @@ -5877,6 +5951,19 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) } break; + case SST_scrFilter: + if (voodoo->initEnable & 0x01) + { + voodoo->scrfilterEnabled = 1; + voodoo->scrfilterThreshold = val; /* update the threshold values and generate a new lookup table if necessary */ + + if (val < 1) + voodoo->scrfilterEnabled = 0; + voodoo_threshold_check(voodoo); + pclog("Voodoo Filter: %06x\n", val); + } + break; + case SST_fbiInit5: if (voodoo->initEnable & 0x01) voodoo->fbiInit5 = val; @@ -6316,22 +6403,25 @@ static void voodoo_calc_clutData(voodoo_t *voodoo) } } -#define FILTCAP 64.0f /* Needs tuning to match DAC */ -#define FILTCAPG (FILTCAP / 2) + + +#define FILTDIV 256 + +static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */ static void voodoo_generate_filter(voodoo_t *voodoo) { - int g, h, i; - float difference, diffg; - float color; - float thiscol, thiscolg, lined; + int g, h; + float difference, diffg, diffb; + float thiscol, thiscolg, thiscolb, lined; - for (g=0;g<1024;g++) // pixel 1 + for (g=0;g FILTCAP) difference = FILTCAP; @@ -6343,30 +6433,67 @@ static void voodoo_generate_filter(voodoo_t *voodoo) if (diffg < -FILTCAPG) diffg = -FILTCAPG; - thiscol = g + (difference / 3); - thiscolg = g + (diffg / 3); + if (diffb > FILTCAPB) + diffb = FILTCAPB; + if (diffb < -FILTCAPB) + diffb = -FILTCAPB; + + thiscol = g + (difference / 2); + thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ + thiscolb = g + (diffb / 2); if (thiscol < 0) thiscol = 0; - if (thiscol > 1023) - thiscol = 1023; + if (thiscol > FILTDIV-1) + thiscol = FILTDIV-1; if (thiscolg < 0) thiscolg = 0; - if (thiscolg > 1023) - thiscolg = 1023; + if (thiscolg > FILTDIV-1) + thiscolg = FILTDIV-1; + + if (thiscolb < 0) + thiscolb = 0; + if (thiscolb > FILTDIV-1) + thiscolb = FILTDIV-1; voodoo->thefilter[g][h] = thiscol; voodoo->thefilterg[g][h] = thiscolg; + voodoo->thefilterb[g][h] = thiscolb; } - lined = g + 4; - if (lined > 1023) - lined = 1023; + lined = g + 3; + if (lined > 255) + lined = 255; voodoo->purpleline[g] = lined; } } +static void voodoo_threshold_check(voodoo_t *voodoo) +{ + int r, g, b; + + if (!voodoo->scrfilterEnabled) + return; /* considered disabled; don't check and generate */ + + /* Check for changes, to generate anew table */ + if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld) + { + r = (voodoo->scrfilterThreshold >> 16) & 0xFF; + g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF; + b = voodoo->scrfilterThreshold & 0xFF; + + FILTCAP = r; + FILTCAPG = g; + FILTCAPB = b; + + pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); + + voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; + voodoo_generate_filter(voodoo); + } +} + static void voodoo_filterline(voodoo_t *voodoo, uint16_t *fil, int column, uint16_t *src, int line) { int x; @@ -6374,41 +6501,42 @@ static void voodoo_filterline(voodoo_t *voodoo, uint16_t *fil, int column, uint1 /* 16 to 32-bit */ for (x=0; x> 5) & 63) << 4); - fil[x*3+2] = (((src[x] >> 11) & 31) << 5); + fil[x*3] = ((src[x] & 31) << 3); + fil[x*3+1] = (((src[x] >> 5) & 63) << 2); /* Shift to 32-bit */ + fil[x*3+2] = (((src[x] >> 11) & 31) << 3); } + fil[x*3] = 0; - fil[x*3+1] = 0; + fil[x*3+1] = 0; /* Keep the compiler happy */ fil[x*3+2] = 0; /* filtering time */ - for (x=1; xthefilter[fil[x*3]][fil[(x-1)*3]]; - fil[x*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[(x-1)*3+1]]; - fil[x*3+2] = voodoo->thefilter[fil[x*3+2]][fil[(x-1)*3+2]]; + fil[(x-1)*3] = voodoo->thefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil[(x-1)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil[(x-1)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; + } + for (x=0; xthefilterb[fil[x*3]][fil[ (x+1) *3]]; + fil[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x+1) *3+1]]; + fil[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x+1) *3+2]]; } for (x=1; xthefilter[fil[x*3]][fil[(x-1)*3]]; - fil[x*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[(x-1)*3+1]]; - fil[x*3+2] = voodoo->thefilter[fil[x*3+2]][fil[(x-1)*3+2]]; + fil[(x-1)*3] = voodoo->thefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil[(x-1)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil[(x-1)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; } - for (x=1; xthefilter[fil[x*3]][fil[(x-1)*3]]; - fil[x*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[(x-1)*3+1]]; - fil[x*3+2] = voodoo->thefilter[fil[x*3+2]][fil[(x-1)*3+2]]; + fil[(x-1)*3] = voodoo->thefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil[(x-1)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil[(x-1)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; } - for (x=0; xthefilter[fil[x*3]][fil[(x+1)*3]]) >> 2; - fil[x*3+1] = (voodoo->thefilterg[fil[x*3+1]][fil[(x+1)*3+1]]) >> 2; - fil[x*3+2] = (voodoo->thefilter[fil[x*3+2]][fil[(x+1)*3+2]]) >> 2; - } /* lines */ @@ -6448,7 +6576,7 @@ void voodoo_callback(void *p) if (voodoo->line > voodoo->dirty_line_high) voodoo->dirty_line_high = voodoo->line; - if (voodoo->scrfilter) + if (voodoo->scrfilter && voodoo->scrfilterEnabled) { int j, offset; uint16_t fil[(voodoo->h_disp + 1) * 3]; /* interleaved 24-bit RGB */ @@ -6493,7 +6621,7 @@ void voodoo_callback(void *p) if (voodoo->line == voodoo->v_disp) { if (voodoo->dirty_line_high > voodoo->dirty_line_low) - svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp, voodoo->svga); + svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); if (voodoo->clutData_dirty) { voodoo->clutData_dirty = 0; @@ -6643,6 +6771,8 @@ void *voodoo_init() voodoo->render_thread[0] = thread_create(render_thread_1, voodoo); if (voodoo->render_threads == 2) voodoo->render_thread[1] = thread_create(render_thread_2, voodoo); + + timer_add(voodoo_wake_timer, &voodoo->wake_timer, &voodoo->wake_timer, (void *)voodoo); for (c = 0; c < 0x100; c++) { diff --git a/src/vid_voodoo_codegen_x86-64.h b/src/vid_voodoo_codegen_x86-64.h index 14b9dd305..8d3cc7271 100644 --- a/src/vid_voodoo_codegen_x86-64.h +++ b/src/vid_voodoo_codegen_x86-64.h @@ -525,16 +525,6 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v addbyte(0xd5); addbyte(0x4e); addbyte(0x10); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0 | 0); - addbyte(8); - addbyte(0x66); /*PSRLW XMM1, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0 | 1); - addbyte(8); addbyte(0x66); /*PADDW XMM0, XMM1*/ addbyte(0x0f); addbyte(0xfd); @@ -552,6 +542,11 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v addbyte(0x0f); addbyte(0xfd); addbyte(0xc0 | 1 | (0 << 3)); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0 | 0); + addbyte(8); addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ addbyte(0x0f); addbyte(0x67); @@ -1542,7 +1537,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xfb); addbyte(0xc1); /*SHR EBX, 24*/ addbyte(0xeb); - addbyte(0x24); + addbyte(24); break; case TCA_MSELECT_AOTHER: addbyte(0x66); /*MOV EBX, XMM3*/ @@ -1551,7 +1546,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xdb); addbyte(0xc1); /*SHR EBX, 24*/ addbyte(0xeb); - addbyte(0x24); + addbyte(24); break; case TCA_MSELECT_ALOCAL: addbyte(0x66); /*MOV EBX, XMM7*/ @@ -1560,7 +1555,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xfb); addbyte(0xc1); /*SHR EBX, 24*/ addbyte(0xeb); - addbyte(0x24); + addbyte(24); break; case TCA_MSELECT_DETAIL: addbyte(0xbb); /*MOV EBX, params->detail_bias[1]*/ @@ -1647,9 +1642,20 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0x7e); addbyte(0xc1); } + if (cc_mselect == CC_MSELECT_TEXRGB) + { + addbyte(0xf3); /*MOVD XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + } if ((params->fbzMode & FBZ_CHROMAKEY)) { + addbyte(0x66); /*MOVD EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/ addbyte(0x9e); addlong(offsetof(voodoo_params_t, chromaKey)); @@ -2109,6 +2115,16 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addlong(offsetof(voodoo_state_t, tex_a)); addbyte(2); break; + case CC_MSELECT_TEXRGB: + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOVQ XMM3, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xdc); + break; default: addbyte(0x66); /*PXOR XMM3, XMM3*/ addbyte(0x0f); diff --git a/src/vid_voodoo_codegen_x86.h b/src/vid_voodoo_codegen_x86.h index 4e6756032..d10f3bbcc 100644 --- a/src/vid_voodoo_codegen_x86.h +++ b/src/vid_voodoo_codegen_x86.h @@ -503,16 +503,6 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v addbyte(0xd5); addbyte(0x4e); addbyte(0x10); - addbyte(0x66); /*PSRLW XMM0, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0 | 0); - addbyte(8); - addbyte(0x66); /*PSRLW XMM1, 8*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xd0 | 1); - addbyte(8); addbyte(0x66); /*PADDW XMM0, XMM1*/ addbyte(0x0f); addbyte(0xfd); @@ -530,6 +520,11 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v addbyte(0x0f); addbyte(0xfd); addbyte(0xc0 | 1 | (0 << 3)); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0 | 0); + addbyte(8); addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ addbyte(0x0f); addbyte(0x67); @@ -1523,7 +1518,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xfb); addbyte(0xc1); /*SHR EBX, 24*/ addbyte(0xeb); - addbyte(0x24); + addbyte(24); break; case TCA_MSELECT_AOTHER: addbyte(0x66); /*MOV EBX, XMM3*/ @@ -1532,7 +1527,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xdb); addbyte(0xc1); /*SHR EBX, 24*/ addbyte(0xeb); - addbyte(0x24); + addbyte(24); break; case TCA_MSELECT_ALOCAL: addbyte(0x66); /*MOV EBX, XMM7*/ @@ -1541,7 +1536,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xfb); addbyte(0xc1); /*SHR EBX, 24*/ addbyte(0xeb); - addbyte(0x24); + addbyte(24); break; case TCA_MSELECT_DETAIL: addbyte(0xbb); /*MOV EBX, params->detail_bias[1]*/ @@ -1628,6 +1623,13 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0x7e); addbyte(0xc1); } + if (cc_mselect == CC_MSELECT_TEXRGB) + { + addbyte(0xf3); /*MOVD XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + } if ((params->fbzMode & FBZ_CHROMAKEY)) { @@ -2095,6 +2097,16 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addlong(offsetof(voodoo_state_t, tex_a)); addbyte(2); break; + case CC_MSELECT_TEXRGB: + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOVQ XMM3, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xdc); + break; default: addbyte(0x66); /*PXOR XMM3, XMM3*/ addbyte(0x0f); diff --git a/src/vid_wy700.c b/src/vid_wy700.c new file mode 100644 index 000000000..41bb73ffb --- /dev/null +++ b/src/vid_wy700.c @@ -0,0 +1,994 @@ +/* Wyse-700 emulation*/ +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "timer.h" +#include "video.h" +#include "vid_wy700.h" + +#define WY700_XSIZE 1280 +#define WY700_YSIZE 800 + +void updatewindowsize(int x, int y); +void loadfont(char *s, int format); + + +/* The Wyse 700 is an unusual video card. Though it has an MC6845 CRTC, this + * is not exposed directly to the host PC. Instead, the CRTC is controlled by + * an MC68705P3 microcontroller. + * + * Rather than emulate the real CRTC, I'm writing this as more or less a + * fixed-frequency card with a 1280x800 display, and scaling its selection + * of modes to that window. + * + * By default, the card responds to both the CGA and MDA I/O and memory + * ranges. Either range can be disabled by means of jumpers; this allows + * the Wy700 to coexist with a CGA or MDA. + * + * wy700->wy700_mode indicates which of the supported video modes is in use: + * + * 0x00: 40x 25 text (CGA compatible) [32x32 character cell] + * 0x02: 80x 25 text (CGA / MDA compatible) [16x32 character cell] + * 0x04: 320x200x4 graphics (CGA compatible) + * 0x06: 640x200x2 graphics (CGA compatible) + * 0x80: 640x400x2 graphics + * 0x90: 320x400x4 graphics + * 0xA0: 1280x400x2 graphics + * 0xB0: 640x400x4 graphics + * 0xC0: 1280x800x2 graphics (interleaved) + * 0xD0: 640x800x4 graphics (interleaved) + * In hi-res graphics modes, bit 3 of the mode byte is the enable flag. + * + */ + +/* What works (or appears to) : + * MDA/CGA 80x25 text mode + * CGA 40x25 text mode + * CGA 640x200 graphics mode + * CGA 320x200 graphics mode + * Hi-res graphics modes + * Font selection + * Display enable / disable + * -- via Wy700 mode register (in hi-res modes) + * -- via Wy700 command register (in text & CGA modes) + * -- via CGA/MDA control register (in text & CGA modes) + * + * What doesn't work, is untested or not well understood: + * - Cursor detach (commands 4 and 5) + */ + + +/* The microcontroller sets up the real CRTC with one of five fixed mode + * definitions. As written, this is a fairly simplistic emulation that + * doesn't attempt to closely follow the actual working of the CRTC; but I've + * included the definitions here for information. */ + +static uint8_t mode_1280x800[] = +{ + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x29, /* Horizontal sync position */ + 0x06, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x03, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ +}; + +static uint8_t mode_1280x400[] = +{ + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x29, /* Horizontal sync position */ + 0x06, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ +}; + +static uint8_t mode_640x400[] = +{ + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x14, /* Horizontal sync position */ + 0x03, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ +}; + +static uint8_t mode_640x200[] = +{ + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x14, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x37, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x32, /* Vertical displayed */ + 0x34, /* Vsync position */ + 0x03, /* Interlace and skew */ + 0x07, /* Maximum raster address */ +}; + +static uint8_t mode_80x24[] = +{ + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x2A, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ +}; + +static uint8_t mode_40x24[] = +{ + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x15, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f, /* Maximum raster address */ +}; + + +/* Font ROM: Two fonts, each containing 256 characters, 16x16 pixels */ +extern uint8_t fontdatw[512][32]; + +typedef struct wy700_t +{ + mem_mapping_t mapping; + + /* The microcontroller works by watching four ports: + * 0x3D8 / 0x3B8 (mode control register) + * 0x3DD (top scanline address) + * 0x3DF (Wy700 control register) + * CRTC reg 14 (cursor location high) + * + * It will do nothing until one of these registers is touched. When + * one is, it then reconfigures the internal 6845 based on what it + * sees. + */ + uint8_t last_03D8; /* Copies of values written to the listed */ + uint8_t last_03DD; /* I/O ports */ + uint8_t last_03DF; + uint8_t last_crtc_0E; + + uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ + uint8_t real_crtc[32]; /* The internal CRTC as the microcontroller */ + /* sees it */ + int cga_crtcreg; /* Current CRTC register */ + uint16_t wy700_base; /* Framebuffer base address (native modes) */ + uint8_t wy700_control; /* Native control / command register */ + uint8_t wy700_mode; /* Current mode (see list at top of file) */ + uint8_t cga_ctrl; /* Emulated MDA/CGA control register */ + uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ + + uint8_t mda_stat; /* MDA status (IN 0x3BA) */ + uint8_t cga_stat; /* CGA status (IN 0x3DA) */ + + int font; /* Current font, 0 or 1 */ + int enabled; /* Display enabled, 0 or 1 */ + int detach; /* Detach cursor, 0 or 1 */ + + int dispontime, dispofftime; + int vidtime; + + int linepos, displine; + int vc; + int dispon, blink; + int vsynctime; + + uint8_t *vram; +} wy700_t; + +/* Mapping of attributes to colours, in CGA emulation... */ +static int cgacols[256][2][2]; +/* ... and MDA emulation. */ +static int mdacols[256][2][2]; + +void wy700_recalctimings(wy700_t *wy700); +void wy700_write(uint32_t addr, uint8_t val, void *p); +uint8_t wy700_read(uint32_t addr, void *p); +void wy700_checkchanges(wy700_t *wy700); + + +void wy700_out(uint16_t addr, uint8_t val, void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + switch (addr) + { + /* These three registers are only mapped in the 3Dx range, + * not the 3Bx range. */ + case 0x3DD: /* Base address (low) */ + wy700->wy700_base &= 0xFF00; + wy700->wy700_base |= val; + wy700_checkchanges(wy700); + break; + + case 0x3DE: /* Base address (high) */ + wy700->wy700_base &= 0xFF; + wy700->wy700_base |= ((uint16_t)val) << 8; + wy700_checkchanges(wy700); + break; + + case 0x3DF: /* Command / control register */ + wy700->wy700_control = val; + wy700_checkchanges(wy700); + break; + + /* Emulated CRTC, register select */ + case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: + case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: + wy700->cga_crtcreg = val & 31; + break; + + /* Emulated CRTC, value */ + case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + wy700->cga_crtc[wy700->cga_crtcreg] = val; + + wy700_checkchanges(wy700); + wy700_recalctimings(wy700); + return; + + /* Emulated MDA / CGA control register */ + case 0x3b8: case 0x3D8: + wy700->cga_ctrl = val; + wy700_checkchanges(wy700); + return; + /* Emulated CGA colour register */ + case 0x3D9: + wy700->cga_colour = val; + return; + } +} + +uint8_t wy700_in(uint16_t addr, void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + switch (addr) + { + case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: + case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: + return wy700->cga_crtcreg; + case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + return wy700->cga_crtc[wy700->cga_crtcreg]; + case 0x3b8: case 0x3d8: + return wy700->cga_ctrl; + case 0x3d9: + return wy700->cga_colour; + case 0x3ba: + return wy700->mda_stat; + case 0x3da: + return wy700->cga_stat; + } + return 0xff; +} + + +/* Check if any of the four key registers has changed. If so, check for a + * mode change or cursor size change */ +void wy700_checkchanges(wy700_t *wy700) +{ + uint8_t curstart, curend; + + if (wy700->last_03D8 == wy700->cga_ctrl && + wy700->last_03DD == (wy700->wy700_base & 0xFF) && + wy700->last_03DF == wy700->wy700_control && + wy700->last_crtc_0E == wy700->cga_crtc[0x0E]) + { + return; /* Nothing changed */ + } + /* Check for control register changes */ + if (wy700->last_03DF != wy700->wy700_control) + { + wy700->last_03DF = wy700->wy700_control; + + /* Values 1-7 are commands. */ + switch (wy700->wy700_control) + { + case 1: /* Reset */ + wy700->font = 0; + wy700->enabled = 1; + wy700->detach = 0; + break; + + case 2: /* Font 1 */ + wy700->font = 0; + break; + + case 3: /* Font 2 */ + wy700->font = 1; + break; + +/* Even with the microprogram from an original card, I can't really work out + * what commands 4 and 5 (which I've called 'cursor detach' / 'cursor attach') + * do. Command 4 sets a flag in microcontroller RAM, and command 5 clears + * it. When the flag is set, the real cursor doesn't track the cursor in the + * emulated CRTC, and its blink rate increases. Possibly it's a self-test + * function of some kind. + * + * The card documentation doesn't cover these commands. + */ + + case 4: /* Detach cursor */ + wy700->detach = 1; + break; + + case 5: /* Attach cursor */ + wy700->detach = 0; + break; + + case 6: /* Disable display */ + wy700->enabled = 0; + break; + + case 7: /* Enable display */ + wy700->enabled = 1; + break; + } + /* A control write with the top bit set selects graphics mode */ + if (wy700->wy700_control & 0x80) + { + /* Select hi-res graphics mode; map framebuffer at A0000 */ + mem_mapping_set_addr(&wy700->mapping, 0xa0000, 0x20000); + wy700->wy700_mode = wy700->wy700_control; + + /* Select appropriate preset timings */ + if (wy700->wy700_mode & 0x40) + { + memcpy(wy700->real_crtc, mode_1280x800, + sizeof(mode_1280x800)); + } + else if (wy700->wy700_mode & 0x20) + { + memcpy(wy700->real_crtc, mode_1280x400, + sizeof(mode_1280x400)); + } + else + { + memcpy(wy700->real_crtc, mode_640x400, + sizeof(mode_640x400)); + } + } + } + /* An attempt to program the CGA / MDA selects low-res mode */ + else if (wy700->last_03D8 != wy700->cga_ctrl) + { + wy700->last_03D8 = wy700->cga_ctrl; + /* Set lo-res text or graphics mode. + * (Strictly speaking, when not in hi-res mode the card + * should be mapped at B0000-B3FFF and B8000-BBFFF, leaving + * a 16k hole between the two ranges) */ + mem_mapping_set_addr(&wy700->mapping, 0xb0000, 0x0C000); + if (wy700->cga_ctrl & 2) /* Graphics mode */ + { + wy700->wy700_mode = (wy700->cga_ctrl & 0x10) ? 6 : 4; + memcpy(wy700->real_crtc, mode_640x200, + sizeof(mode_640x200)); + } + else if (wy700->cga_ctrl & 1) /* Text mode 80x24 */ + { + wy700->wy700_mode = 2; + memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); + } + else /* Text mode 40x24 */ + { + wy700->wy700_mode = 0; + memcpy(wy700->real_crtc, mode_40x24, sizeof(mode_40x24)); + } + } + /* Convert the cursor sizes from the ones used by the CGA or MDA + * to native */ + + if (wy700->cga_crtc[9] == 13) /* MDA scaling */ + { + curstart = wy700->cga_crtc[10] & 0x1F; + wy700->real_crtc[10] = ((curstart + 5) >> 3) + curstart; + if (wy700->real_crtc[10] > 31) wy700->real_crtc[10] = 31; + /* And bring 'cursor disabled' flag across */ + if ((wy700->cga_crtc[10] & 0x60) == 0x20) + { + wy700->real_crtc[10] |= 0x20; + } + curend = wy700->cga_crtc[11] & 0x1F; + wy700->real_crtc[11] = ((curend + 5) >> 3) + curend; + if (wy700->real_crtc[11] > 31) wy700->real_crtc[11] = 31; + } + else /* CGA scaling */ + { + curstart = wy700->cga_crtc[10] & 0x1F; + wy700->real_crtc[10] = curstart << 1; + if (wy700->real_crtc[10] > 31) wy700->real_crtc[10] = 31; + /* And bring 'cursor disabled' flag across */ + if ((wy700->cga_crtc[10] & 0x60) == 0x20) + { + wy700->real_crtc[10] |= 0x20; + } + curend = wy700->cga_crtc[11] & 0x1F; + wy700->real_crtc[11] = curend << 1; + if (wy700->real_crtc[11] > 31) wy700->real_crtc[11] = 31; + } +} + + +void wy700_write(uint32_t addr, uint8_t val, void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + egawrites++; + + if (wy700->wy700_mode & 0x80) /* High-res mode. */ + { + addr &= 0xFFFF; +/* In 800-line modes, bit 1 of the control register sets the high bit of the + * write address. */ + if ((wy700->wy700_mode & 0x42) == 0x42) + { + addr |= 0x10000; + } + wy700->vram[addr] = val; + } + else + { + wy700->vram[addr & 0x3fff] = val; + } +} + + + +uint8_t wy700_read(uint32_t addr, void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + egareads++; + if (wy700->wy700_mode & 0x80) /* High-res mode. */ + { + addr &= 0xFFFF; +/* In 800-line modes, bit 0 of the control register sets the high bit of the + * read address. */ + if ((wy700->wy700_mode & 0x41) == 0x41) + { + addr |= 0x10000; + } + return wy700->vram[addr]; + } + else + { + return wy700->vram[addr & 0x3fff]; + } +} + + + +void wy700_recalctimings(wy700_t *wy700) +{ + double disptime; + double _dispontime, _dispofftime; + + disptime = wy700->real_crtc[0] + 1; + _dispontime = wy700->real_crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + wy700->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + wy700->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +/* Draw a single line of the screen in either text mode */ +void wy700_textline(wy700_t *wy700) +{ + int x; + int w = (wy700->wy700_mode == 0) ? 40 : 80; + int cw = (wy700->wy700_mode == 0) ? 32 : 16; + uint8_t chr, attr, fg, bg; + uint8_t bitmap[2]; + uint8_t *fontbase = &fontdatw[0][0]; + int blink, c; + int drawcursor, cursorline; + int mda = 0; + uint16_t addr; + uint8_t sc; + uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; + uint16_t ca = (wy700->cga_crtc[15] | (wy700->cga_crtc[14] << 8)) & 0x3fff; + + +/* The fake CRTC character height register selects whether MDA or CGA + * attributes are used */ + if (wy700->cga_crtc[9] == 0 || wy700->cga_crtc[9] == 13) + { + mda = 1; + } + + if (wy700->font) + { + fontbase += 256*32; + } + addr = ((ma & ~1) + (wy700->displine >> 5) * w) * 2; + sc = (wy700->displine >> 1) & 15; + + ma += ((wy700->displine >> 5) * w); + + if ((wy700->real_crtc[10] & 0x60) == 0x20) + { + cursorline = 0; + } + else + { + cursorline = ((wy700->real_crtc[10] & 0x1F) <= sc) && + ((wy700->real_crtc[11] & 0x1F) >= sc); + } + + for (x = 0; x < w; x++) + { + chr = wy700->vram[(addr + 2 * x) & 0x3FFF]; + attr = wy700->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && wy700->enabled && + (wy700->cga_ctrl & 8) && (wy700->blink & 16)); + blink = ((wy700->blink & 16) && + (wy700->cga_ctrl & 0x20) && + (attr & 0x80) && !drawcursor); + + if (wy700->cga_ctrl & 0x20) attr &= 0x7F; + /* MDA underline */ + if (sc == 14 && mda && ((attr & 7) == 1)) + { + for (c = 0; c < cw; c++) + buffer->line[wy700->displine][(x * cw) + c] = + mdacols[attr][blink][1]; + } + else /* Draw 16 pixels of character */ + { + bitmap[0] = fontbase[chr * 32 + 2 * sc]; + bitmap[1] = fontbase[chr * 32 + 2 * sc + 1]; + for (c = 0; c < 16; c++) + { + int col; + if (c < 8) + col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; + else col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; + if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) + col = mdacols[0][0][0]; + if (w == 40) + { + buffer->line[wy700->displine][(x * cw) + 2*c] = col; + buffer->line[wy700->displine][(x * cw) + 2*c + 1] = col; + } + else buffer->line[wy700->displine][(x * cw) + c] = col; + } + + if (drawcursor) + { + for (c = 0; c < cw; c++) + buffer->line[wy700->displine][(x * cw) + c] ^= (mda ? mdacols : cgacols)[attr][0][1]; + } + ++ma; + } + } +} + + +/* Draw a line in either of the CGA graphics modes (320x200 or 640x200) */ +void wy700_cgaline(wy700_t *wy700) +{ + int x, c; + uint32_t dat; + uint8_t bitmap, ink; + uint16_t addr; + + uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; + addr = ((wy700->displine >> 2) & 1) * 0x2000 + + (wy700->displine >> 3) * 80 + + ((ma & ~1) << 1); + + /* The fixed mode setting here programs the real CRTC with a screen + * width to 20, so draw in 20 fixed chunks of 4 bytes each */ + for (x = 0; x < 20; x++) + { + dat = ((wy700->vram[addr & 0x3FFF] << 24) | + (wy700->vram[(addr+1) & 0x3FFF] << 16) | + (wy700->vram[(addr+2) & 0x3FFF] << 8) | + (wy700->vram[(addr+3) & 0x3FFF])); + addr += 4; + + if (wy700->wy700_mode == 6) + { + for (c = 0; c < 32; c++) + { + ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; + if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) + ink = 16; + buffer->line[wy700->displine][x*64 + 2*c] = + buffer->line[wy700->displine][x*64 + 2*c+1] = + ink; + dat = dat << 1; + } + } + else + { + for (c = 0; c < 16; c++) + { + switch ((dat >> 30) & 3) + { + case 0: ink = 16 + 0; break; + case 1: ink = 16 + 8; break; + case 2: ink = 16 + 7; break; + case 3: ink = 16 + 15; break; + } + if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) + ink = 16; + buffer->line[wy700->displine][x*64 + 4*c] = + buffer->line[wy700->displine][x*64 + 4*c+1] = + buffer->line[wy700->displine][x*64 + 4*c+2] = + buffer->line[wy700->displine][x*64 + 4*c+3] = + ink; + dat = dat << 2; + } + } + } +} + +/* Draw a line in the medium-resolution graphics modes (640x400 or 320x400) */ +void wy700_medresline(wy700_t *wy700) +{ + int x, c; + uint32_t dat; + uint8_t bitmap, ink; + uint32_t addr; + + addr = (wy700->displine >> 1) * 80 + 4 * wy700->wy700_base; + + for (x = 0; x < 20; x++) + { + dat = ((wy700->vram[addr & 0x1FFFF] << 24) | + (wy700->vram[(addr+1) & 0x1FFFF] << 16) | + (wy700->vram[(addr+2) & 0x1FFFF] << 8) | + (wy700->vram[(addr+3) & 0x1FFFF])); + addr += 4; + + if (wy700->wy700_mode & 0x10) + { + for (c = 0; c < 16; c++) + { + switch ((dat >> 30) & 3) + { + case 0: ink = 16 + 0; break; + case 1: ink = 16 + 8; break; + case 2: ink = 16 + 7; break; + case 3: ink = 16 + 15; break; + } + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) ink = 16; + buffer->line[wy700->displine][x*64 + 4*c] = + buffer->line[wy700->displine][x*64 + 4*c+1] = + buffer->line[wy700->displine][x*64 + 4*c+2] = + buffer->line[wy700->displine][x*64 + 4*c+3] = + ink; + dat = dat << 2; + } + } + else + { + for (c = 0; c < 32; c++) + { + ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) ink = 16; + buffer->line[wy700->displine][x*64 + 2*c] = + buffer->line[wy700->displine][x*64 + 2*c+1] = + ink; + dat = dat << 1; + } + } + } +} + + + + +/* Draw a line in one of the high-resolution modes */ +void wy700_hiresline(wy700_t *wy700) +{ + int x, c; + uint32_t dat; + uint8_t bitmap, ink; + uint32_t addr; + + addr = (wy700->displine >> 1) * 160 + 4 * wy700->wy700_base; + + if (wy700->wy700_mode & 0x40) /* 800-line interleaved modes */ + { + if (wy700->displine & 1) addr += 0x10000; + } + for (x = 0; x < 40; x++) + { + dat = ((wy700->vram[addr & 0x1FFFF] << 24) | + (wy700->vram[(addr+1) & 0x1FFFF] << 16) | + (wy700->vram[(addr+2) & 0x1FFFF] << 8) | + (wy700->vram[(addr+3) & 0x1FFFF])); + addr += 4; + + if (wy700->wy700_mode & 0x10) + { + for (c = 0; c < 16; c++) + { + switch ((dat >> 30) & 3) + { + case 0: ink = 16 + 0; break; + case 1: ink = 16 + 8; break; + case 2: ink = 16 + 7; break; + case 3: ink = 16 + 15; break; + } + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) ink = 16; + buffer->line[wy700->displine][x*32 + 2*c] = + buffer->line[wy700->displine][x*32 + 2*c+1] = + ink; + dat = dat << 2; + } + } + else + { + for (c = 0; c < 32; c++) + { + ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; + /* Display disabled? */ + if (!(wy700->wy700_mode & 8)) ink = 16; + buffer->line[wy700->displine][x*32 + c] = ink; + dat = dat << 1; + } + } + } +} + + + + +void wy700_poll(void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + int x, c; + int oldvc; + uint8_t chr, attr; + uint16_t dat; + int mode; + + if (!wy700->linepos) + { + wy700->vidtime += wy700->dispofftime; + wy700->cga_stat |= 1; + wy700->mda_stat |= 1; + wy700->linepos = 1; + if (wy700->dispon) + { + if (wy700->displine == 0) + { + video_wait_for_buffer(); + } + + if (wy700->wy700_mode & 0x80) + mode = wy700->wy700_mode & 0xF0; + else mode = wy700->wy700_mode & 0x0F; + + switch (mode) + { + default: + case 0x00: + case 0x02: + wy700_textline(wy700); + break; + case 0x04: + case 0x06: + wy700_cgaline(wy700); + break; + case 0x80: + case 0x90: + wy700_medresline(wy700); + break; + case 0xA0: + case 0xB0: + case 0xC0: + case 0xD0: + case 0xE0: + case 0xF0: + wy700_hiresline(wy700); + break; + } + } + wy700->displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (wy700->displine == 800) /* Start of VSYNC */ + { + wy700->cga_stat |= 8; + wy700->dispon = 0; + } + if (wy700->displine == 832) /* End of VSYNC */ + { + wy700->displine = 0; + wy700->cga_stat &= ~8; + wy700->dispon = 1; + } + } + else + { + if (wy700->dispon) + { + wy700->cga_stat &= ~1; + wy700->mda_stat &= ~1; + } + wy700->vidtime += wy700->dispontime; + wy700->linepos = 0; + + if (wy700->displine == 800) + { +/* Hardcode 1280x800 window size */ + if (WY700_XSIZE != xsize || WY700_YSIZE != ysize) + { + xsize = WY700_XSIZE; + ysize = WY700_YSIZE; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + updatewindowsize(xsize, ysize); + } + video_blit_memtoscreen_8(0, 0, xsize, ysize); + + frames++; + /* Fixed 1280x800 resolution */ + video_res_x = WY700_XSIZE; + video_res_y = WY700_YSIZE; + if (wy700->wy700_mode & 0x80) + mode = wy700->wy700_mode & 0xF0; + else mode = wy700->wy700_mode & 0x0F; + switch(mode) + { + case 0x00: + case 0x02: video_bpp = 0; break; + case 0x04: + case 0x90: + case 0xB0: + case 0xD0: + case 0xF0: video_bpp = 2; break; + default: video_bpp = 1; break; + } + wy700->blink++; + } + } +} + +void *wy700_init() +{ + int c; + wy700_t *wy700 = malloc(sizeof(wy700_t)); + memset(wy700, 0, sizeof(wy700_t)); + + /* 128k video RAM */ + wy700->vram = malloc(0x20000); + + timer_add(wy700_poll, &wy700->vidtime, TIMER_ALWAYS_ENABLED, wy700); + + /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in + * high-resolution modes) */ + mem_mapping_add(&wy700->mapping, 0xb0000, 0x10000, wy700_read, NULL, NULL, wy700_write, NULL, NULL, NULL, 0, wy700); + /* Respond to both MDA and CGA I/O ports */ + io_sethandler(0x03b0, 0x000C, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); + io_sethandler(0x03d0, 0x0010, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); + + /* Set up the emulated attributes. + * CGA is done in four groups: 00-0F, 10-7F, 80-8F, 90-FF */ + for (c = 0; c < 0x10; c++) + { + cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16; + if (c & 8) cgacols[c][0][1] = 15 + 16; + else cgacols[c][0][1] = 7 + 16; + } + for (c = 0x10; c < 0x80; c++) + { + cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16 + 7; + if (c & 8) cgacols[c][0][1] = 15 + 16; + else cgacols[c][0][1] = 0 + 16; + + if ((c & 0x0F) == 8) cgacols[c][0][1] = 8 + 16; + } + /* With special cases for 00, 11, 22, ... 77 */ + cgacols[0x00][0][1] = cgacols[0x00][1][1] = 16; + for (c = 0x11; c <= 0x77; c += 0x11) + { + cgacols[c][0][1] = cgacols[c][1][1] = 16 + 7; + } + for (c = 0x80; c < 0x90; c++) + { + cgacols[c][0][0] = 16 + 8; + if (c & 8) cgacols[c][0][1] = 15 + 16; + else cgacols[c][0][1] = 7 + 16; + cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c-0x80][0][0]; + } + for (c = 0x90; c < 0x100; c++) + { + cgacols[c][0][0] = 16 + 15; + if (c & 8) cgacols[c][0][1] = 8 + 16; + else cgacols[c][0][1] = 7 + 16; + if ((c & 0x0F) == 0) cgacols[c][0][1] = 16; + cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c-0x80][0][0]; + } + /* Also special cases for 99, AA, ..., FF */ + for (c = 0x99; c <= 0xFF; c += 0x11) + { + cgacols[c][0][1] = 16 + 15; + } + /* Special cases for 08, 80 and 88 */ + cgacols[0x08][0][1] = 16 + 8; + cgacols[0x80][0][1] = 16; + cgacols[0x88][0][1] = 16 + 8; + + /* MDA attributes */ + for (c = 0; c < 256; c++) + { + mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; + if (c & 8) mdacols[c][0][1] = 15 + 16; + else mdacols[c][0][1] = 7 + 16; + } + mdacols[0x70][0][1] = 16; + mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; + mdacols[0xF0][0][1] = 16; + mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; + mdacols[0x78][0][1] = 16 + 7; + mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; + mdacols[0xF8][0][1] = 16 + 7; + mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; + mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; + mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; + mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; + mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + +/* Start off in 80x25 text mode */ + wy700->cga_stat = 0xF4; + wy700->wy700_mode = 2; + wy700->enabled = 1; + memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); + return wy700; +} + +void wy700_close(void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + + free(wy700->vram); + free(wy700); +} + +void wy700_speed_changed(void *p) +{ + wy700_t *wy700 = (wy700_t *)p; + + wy700_recalctimings(wy700); +} + +device_t wy700_device = +{ + "Wyse 700", + 0, + wy700_init, + wy700_close, + NULL, + wy700_speed_changed, + NULL, + NULL +}; diff --git a/src/vid_wy700.h b/src/vid_wy700.h new file mode 100644 index 000000000..71d5063e4 --- /dev/null +++ b/src/vid_wy700.h @@ -0,0 +1 @@ +extern device_t wy700_device; diff --git a/src/video.c b/src/video.c index d42359140..674894ec0 100644 --- a/src/video.c +++ b/src/video.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include 1 #include "ibm.h" #include "config.h" #include "device.h" @@ -47,6 +47,7 @@ #include "vid_tgui9440.h" #include "vid_tvga.h" #include "vid_vga.h" +#include "vid_wy700.h" typedef struct { @@ -79,6 +80,8 @@ static VIDEO_CARD video_cards[] = {"Number Nine 9FX (S3 Trio64)", &s3_9fx_device, GFX_N9_9FX}, {"nVidia RIVA 128 (Experimental)", &riva128_device, GFX_RIVA128}, {"nVidia RIVA TNT (Experimental)", &rivatnt_device, GFX_RIVATNT}, + {"nVidia TNT2 (Experimental)", &rivatnt2_device, GFX_RIVATNT2}, + {"OAK OTI-067", &oti067_device, GFX_OTI067}, {"OAK OTI-077", &oti077_device, GFX_OTI077}, {"Paradise Bahamas 64 (S3 Vision864)", &s3_bahamas64_device, GFX_BAHAMAS64}, @@ -92,6 +95,7 @@ static VIDEO_CARD video_cards[] = {"Tseng ET4000AX", &et4000_device, GFX_ET4000}, {"Trident TGUI9440", &tgui9440_device, GFX_TGUI9440}, {"VGA", &vga_device, GFX_VGA}, + {"Wyse 700", &wy700_device, GFX_WY700}, {"", NULL, 0} }; @@ -152,7 +156,7 @@ int video_new_to_old(int card) } int video_fullscreen = 0, video_fullscreen_scale, video_fullscreen_first; -uint32_t *video_15to32, *video_16to32; +uint32_t *video_6to8, *video_15to32, *video_16to32; int egareads=0,egawrites=0; int changeframecount=2; @@ -312,6 +316,7 @@ BITMAP *buffer, *buffer32; uint8_t fontdat[256][8]; uint8_t fontdatm[256][16]; +uint8_t fontdatw[512][32]; /* Wyse700 font */ int xsize=1,ysize=1; @@ -322,10 +327,12 @@ void loadfont(char *s, int format) FILE *f=romfopen(s,"rb"); int c,d; if (!f) - return; - - if (!format) + { + return; + } + switch (format) { + case 0: /* MDA */ for (c=0;c<256;c++) { for (d=0;d<8;d++) @@ -348,9 +355,8 @@ void loadfont(char *s, int format) fontdat[c][d]=getc(f); } } - } - else if (format == 1) - { + break; + case 1: /* PC200 */ for (c=0;c<256;c++) { for (d=0;d<8;d++) @@ -360,7 +366,7 @@ void loadfont(char *s, int format) } for (c=0;c<256;c++) { - for (d=0;d<8;d++) + for (d=0;d<8;d++) { fontdatm[c][d+8]=getc(f); } @@ -374,16 +380,26 @@ void loadfont(char *s, int format) } for (d=0;d<8;d++) getc(f); } - } - else - { + break; + default: + case 2: /* CGA */ for (c=0;c<256;c++) { - for (d=0;d<8;d++) + for (d=0;d<8;d++) { fontdat[c][d]=getc(f); } } + break; + case 3: /* Wyse 700 */ + for (c=0;c<512;c++) + { + for (d=0;d<32;d++) + { + fontdatw[c][d]=getc(f); + } + } + break; } fclose(f); } @@ -402,6 +418,25 @@ static struct static void blit_thread(void *param); +int calc_6to8(int c) +{ + int ic, i8; + double dc, d8; + ic = c; + if (ic == 64) + { + ic = 63; + } + else + { + ic &= 0x3f; + } + dc = (double) ic; + d8 = (ic / 63.0) * 255.0; + i8 = (int) d8; + return i8 & 0xff; +} + int calc_15to32(int c) { int b, g, r; @@ -480,6 +515,10 @@ void initvideo() } } + video_6to8 = malloc(4 * 256); + for (c = 0; c < 256; c++) + video_6to8[c] = calc_6to8(c); + video_15to32 = malloc(4 * 65536); #if 0 for (c = 0; c < 65536; c++) @@ -509,7 +548,8 @@ void closevideo() thread_destroy_event(blit_data.blit_complete); thread_destroy_event(blit_data.wake_blit_thread); - free(video_15to32); + free(video_6to8); + free(video_15to32); free(video_16to32); destroy_bitmap(buffer); destroy_bitmap(buffer32); diff --git a/src/video.h b/src/video.h index d4800b58f..dc9f24eba 100644 --- a/src/video.h +++ b/src/video.h @@ -58,7 +58,7 @@ extern int changeframecount; extern uint8_t fontdat[256][8]; extern uint8_t fontdatm[256][16]; -extern uint32_t *video_15to32, *video_16to32; +extern uint32_t *video_6to8, *video_15to32, *video_16to32; extern int xsize,ysize; diff --git a/src/w83877f.c b/src/w83877f.c index 7f8f959a2..ef595040f 100644 --- a/src/w83877f.c +++ b/src/w83877f.c @@ -8,12 +8,11 @@ #include "ibm.h" +#include "disc.h" #include "fdc.h" #include "fdd.h" -#include "disc.h" #include "io.h" #include "lpt.h" -// #include "mouse_serial.h" #include "serial.h" #include "w83877f.h" @@ -364,7 +363,6 @@ process_value: if (!(w83877f_regs[4] & 0x20)) { serial1_set(make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8); - // mouse_serial_init(); } } if (valxor & 0x80) @@ -384,6 +382,8 @@ process_value: // pclog("W83877F Write [Reg. %02X]: %02X\n", w83877f_curreg, val); if (valxor & 3) fdc_update_rwc(0, FDDA_TYPE); if (valxor & 0xC) fdc_update_rwc(1, FDDB_TYPE); + if (valxor & 0x30) fdc_update_rwc(2, FDDC_TYPE); + if (valxor & 0xC0) fdc_update_rwc(3, FDDD_TYPE); break; case 8: // pclog("W83877F Write [Reg. %02X]: %02X\n", w83877f_curreg, val); @@ -426,7 +426,6 @@ process_value: if (!(w83877f_regs[4] & 0x20)) { serial1_set(make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8); - // mouse_serial_init(); } } break; @@ -448,7 +447,6 @@ process_value: if (!(w83877f_regs[4] & 0x20)) { serial1_set(make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8); - // mouse_serial_init(); } } break; diff --git a/src/win-config.c b/src/win-config.c index ed3e5c17e..6926bc4c5 100644 --- a/src/win-config.c +++ b/src/win-config.c @@ -16,6 +16,7 @@ #include "fdd.h" #include "gameport.h" #include "model.h" +#include "mouse.h" #include "nvr.h" #include "resources.h" #include "sound.h" @@ -26,8 +27,20 @@ extern int is486; static int romstolist[ROM_MAX], listtomodel[ROM_MAX], romstomodel[ROM_MAX], modeltolist[ROM_MAX]; static int settings_sound_to_list[20], settings_list_to_sound[20]; +static int settings_mouse_to_list[20], settings_list_to_mouse[20]; static int settings_network_to_list[20], settings_list_to_network[20]; +static int mouse_valid(int type, int model) +{ + if (type == MOUSE_TYPE_PS2 && !(models[model].flags & MODEL_PS2)) + return 0; + if (type == MOUSE_TYPE_AMSTRAD && !(models[model].flags & MODEL_AMSTRAD)) + return 0; + if (type == MOUSE_TYPE_OLIM24 && !(models[model].flags & MODEL_OLIM24)) + return 0; + return 1; +} + static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { char temp_str[256]; @@ -38,12 +51,12 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR int temp_GAMEBLASTER, temp_GUS, temp_SSI2001, temp_voodoo, temp_sound_card_current; int temp_dynarec; int cpu_flags; - int temp_fda_type, temp_fdb_type; + int temp_fd1_type, temp_fd2_type, temp_fd3_type, temp_fd4_type; int temp_network_card_current; int temp_network_interface_current; - int temp_always_serial; int temp_joystick_type; - int temp_aha154x; + int cpu_type; + int temp_mouse_type; UDACCEL accel; // pclog("Dialog msg %i %08X\n",message,message); @@ -170,33 +183,12 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h=GetDlgItem(hdlg, IDC_CHECKSSI); SendMessage(h, BM_SETCHECK, SSI2001, 0); - h=GetDlgItem(hdlg, IDC_CHECK2); - SendMessage(h, BM_SETCHECK, slowega, 0); - - h=GetDlgItem(hdlg, IDC_CHECK4); - SendMessage(h, BM_SETCHECK, cga_comp, 0); - - h=GetDlgItem(hdlg, IDC_CHECKFORCE43); - SendMessage(h, BM_SETCHECK, force_43, 0); - - h=GetDlgItem(hdlg, IDC_CHECKOVERSCAN); - SendMessage(h, BM_SETCHECK, enable_overscan, 0); - - h=GetDlgItem(hdlg, IDC_CHECKFLASH); - SendMessage(h, BM_SETCHECK, enable_flash, 0); - h=GetDlgItem(hdlg, IDC_CHECKSYNC); SendMessage(h, BM_SETCHECK, enable_sync, 0); - h=GetDlgItem(hdlg, IDC_CHECKSERIAL); - SendMessage(h, BM_SETCHECK, mouse_always_serial, 0); - h=GetDlgItem(hdlg, IDC_CHECKVOODOO); SendMessage(h, BM_SETCHECK, voodoo_enabled, 0); - h=GetDlgItem(hdlg, IDC_CHECK_AHA154X); - SendMessage(h, BM_SETCHECK, aha154x_enabled, 0); - cpu_flags = models[romstomodel[romset]].cpu[cpu_manufacturer].cpus[cpu].cpu_flags; h=GetDlgItem(hdlg, IDC_CHECKDYNAREC); if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || (cpu_flags & CPU_REQUIRES_DYNAREC)) @@ -205,14 +197,6 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR EnableWindow(h, TRUE); SendMessage(h, BM_SETCHECK, ((cpu_flags & CPU_SUPPORTS_DYNAREC) && cpu_use_dynarec) || (cpu_flags & CPU_REQUIRES_DYNAREC), 0); - h = GetDlgItem(hdlg, IDC_COMBOCHC); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"A little"); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"A bit"); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"Some"); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"A lot"); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"Infinite"); - SendMessage(h, CB_SETCURSEL, cache, 0); - h = GetDlgItem(hdlg, IDC_COMBOSPD); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"8-bit"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"Slow 16-bit"); @@ -225,7 +209,7 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h = GetDlgItem(hdlg, IDC_MEMSPIN); SendMessage(h, UDM_SETBUDDY, (WPARAM)GetDlgItem(hdlg, IDC_MEMTEXT), 0); SendMessage(h, UDM_SETRANGE, 0, (models[romstomodel[romset]].min_ram << 16) | models[romstomodel[romset]].max_ram); - if (!models[model].is_at) + if (!models[model].flags & MODEL_AT) SendMessage(h, UDM_SETPOS, 0, mem_size); else SendMessage(h, UDM_SETPOS, 0, mem_size / 1024); @@ -233,6 +217,12 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR accel.nInc = models[model].ram_granularity; SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); + h = GetDlgItem(hdlg, IDC_CONFIGUREMOD); + if (model_getdevice(model)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGUREVID); if (video_card_has_config(video_old_to_new(gfxcard))) EnableWindow(h, TRUE); @@ -251,29 +241,57 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR else EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBODRA); + h = GetDlgItem(hdlg, IDC_COMBODR1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M Dual RPM"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 720k"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M PS/2"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.25M PC-98"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M 3-Mode"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 2.88M"); SendMessage(h, CB_SETCURSEL, fdd_get_type(0), 0); - h = GetDlgItem(hdlg, IDC_COMBODRB); + h = GetDlgItem(hdlg, IDC_COMBODR2); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M Dual RPM"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 720k"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M PS/2"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.25M PC-98"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M 3-Mode"); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 2.88M"); SendMessage(h, CB_SETCURSEL, fdd_get_type(1), 0); + h = GetDlgItem(hdlg, IDC_COMBODR3); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M Dual RPM"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 720k"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M PS/2"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.25M PC-98"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M 3-Mode"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 2.88M"); + SendMessage(h, CB_SETCURSEL, fdd_get_type(2), 0); + h = GetDlgItem(hdlg, IDC_COMBODR4); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M Dual RPM"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 720k"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M PS/2"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.25M PC-98"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M 3-Mode"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 2.88M"); + SendMessage(h, CB_SETCURSEL, fdd_get_type(3), 0); h = GetDlgItem(hdlg, IDC_TEXT_MB); - if (models[model].is_at) + if (models[model].flags & MODEL_AT) SendMessage(h, WM_SETTEXT, 0, (LPARAM)(LPCSTR)"MB"); else SendMessage(h, WM_SETTEXT, 0, (LPARAM)(LPCSTR)"KB"); @@ -296,6 +314,48 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR EnableWindow(h, (joystick_get_max_joysticks(joystick_type) >= 3) ? TRUE : FALSE); h = GetDlgItem(hdlg, IDC_JOY4); EnableWindow(h, (joystick_get_max_joysticks(joystick_type) >= 4) ? TRUE : FALSE); + + h = GetDlgItem(hdlg, IDC_COMBOWS); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"System default"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"0 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"1 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"2 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"4 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"6 W/S"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"7 W/S"); + SendMessage(h, CB_SETCURSEL, cpu_waitstates, 0); + cpu_type = models[romstomodel[romset]].cpu[cpu_manufacturer].cpus[cpu].cpu_type; + if (cpu_type >= CPU_286 && cpu_type <= CPU_386DX) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_COMBOMOUSE); + c = d = 0; + while (1) + { + char *s = mouse_get_name(c); + int type; + + if (!s) + break; + + type = mouse_get_type(c); + settings_mouse_to_list[c] = d; + + if (mouse_valid(type, model)) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + + settings_list_to_mouse[d] = c; + d++; + } + c++; + } + + SendMessage(h, CB_SETCURSEL, settings_mouse_to_list[mouse_type], 0); return TRUE; case WM_COMMAND: @@ -313,7 +373,7 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR mem = models[temp_model].min_ram; else if (mem > models[temp_model].max_ram) mem = models[temp_model].max_ram; - if (models[temp_model].is_at) + if (models[temp_model].flags & MODEL_AT) mem *= 1024; h = GetDlgItem(hdlg, IDC_COMBOVID); @@ -335,27 +395,12 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h = GetDlgItem(hdlg, IDC_CHECKSSI); temp_SSI2001 = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECKFORCE43); - force_43 = SendMessage(h, BM_GETCHECK, 0, 0); - - h = GetDlgItem(hdlg, IDC_CHECKOVERSCAN); - enable_overscan = SendMessage(h, BM_GETCHECK, 0, 0); - - h = GetDlgItem(hdlg, IDC_CHECKFLASH); - enable_flash=SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECKSYNC); enable_sync = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECKSERIAL); - temp_always_serial = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECKVOODOO); temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECK_AHA154X); - temp_aha154x = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_COMBOSND); temp_sound_card_current = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; @@ -365,19 +410,25 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h = GetDlgItem(hdlg, IDC_COMBONET); temp_network_card_current = settings_list_to_network[SendMessage(h, CB_GETCURSEL, 0, 0)]; - h = GetDlgItem(hdlg, IDC_COMBODRA); - temp_fda_type = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_COMBODRB); - temp_fdb_type = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_COMBODR1); + temp_fd1_type = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_COMBODR2); + temp_fd2_type = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_COMBODR3); + temp_fd3_type = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_COMBODR4); + temp_fd4_type = SendMessage(h, CB_GETCURSEL, 0, 0); h = GetDlgItem(hdlg, IDC_COMBOJOY); temp_joystick_type = SendMessage(h, CB_GETCURSEL, 0, 0); - + h = GetDlgItem(hdlg, IDC_COMBOMOUSE); + temp_mouse_type = settings_list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; + if (temp_model != model || gfx != gfxcard || mem != mem_size || temp_cpu != cpu || temp_cpu_m != cpu_manufacturer || fpu != hasfpu || temp_GAMEBLASTER != GAMEBLASTER || temp_GUS != GUS || temp_SSI2001 != SSI2001 || temp_sound_card_current != sound_card_current || - temp_voodoo != voodoo_enabled || temp_dynarec != cpu_use_dynarec || temp_always_serial != mouse_always_serial || - temp_fda_type != fdd_get_type(0) || temp_fdb_type != fdd_get_type(1) || temp_network_card_current != network_card_current || temp_aha154x != aha154x_enabled) + temp_voodoo != voodoo_enabled || temp_dynarec != cpu_use_dynarec || temp_mouse_type != mouse_type || + temp_fd1_type != fdd_get_type(0) || temp_fd2_type != fdd_get_type(1) || temp_fd3_type != fdd_get_type(2) || temp_fd4_type != fdd_get_type(3) || temp_network_card_current != network_card_current) { if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL)==IDOK) { @@ -393,14 +444,14 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR SSI2001 = temp_SSI2001; sound_card_current = temp_sound_card_current; voodoo_enabled = temp_voodoo; - aha154x_enabled = temp_aha154x; cpu_use_dynarec = temp_dynarec; - fdd_set_type(0, temp_fda_type); - fdd_set_type(1, temp_fdb_type); + fdd_set_type(0, temp_fd1_type); + fdd_set_type(1, temp_fd2_type); + fdd_set_type(2, temp_fd3_type); + fdd_set_type(3, temp_fd4_type); network_card_current = temp_network_card_current; - mouse_always_serial = temp_always_serial; mem_resize(); loadbios(); @@ -417,16 +468,13 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h = GetDlgItem(hdlg, IDC_COMBOSPD); video_speed = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECK4); - cga_comp=SendMessage(h, BM_GETCHECK, 0, 0); - cpu_manufacturer = temp_cpu_m; cpu = temp_cpu; cpu_set(); - h = GetDlgItem(hdlg, IDC_COMBOCHC); - cache=SendMessage(h, CB_GETCURSEL, 0, 0); - mem_updatecache(); + h = GetDlgItem(hdlg, IDC_COMBOWS); + cpu_waitstates = SendMessage(h, CB_GETCURSEL, 0, 0); + cpu_update_waitstates(); saveconfig(); @@ -506,7 +554,7 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR SendMessage(h, BM_SETCHECK, ((cpu_flags & CPU_SUPPORTS_DYNAREC) && temp_dynarec) || (cpu_flags & CPU_REQUIRES_DYNAREC), 0); h = GetDlgItem(hdlg, IDC_TEXT_MB); - if (models[temp_model].is_at) + if (models[temp_model].flags & MODEL_AT) SendMessage(h, WM_SETTEXT, 0, (LPARAM)(LPCSTR)"MB"); else SendMessage(h, WM_SETTEXT, 0, (LPARAM)(LPCSTR)"KB"); @@ -526,6 +574,49 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR accel.nSec = 0; accel.nInc = models[temp_model].ram_granularity; SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); + + h = GetDlgItem(hdlg, IDC_COMBOWS); + cpu_type = models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + if (cpu_type >= CPU_286 && cpu_type <= CPU_386DX) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_CONFIGUREMOD); + if (model_getdevice(temp_model)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_COMBOMOUSE); + temp_mouse_type = settings_list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; + SendMessage(h, CB_RESETCONTENT, 0, 0); + c = d = 0; + while (1) + { + char *s = mouse_get_name(c); + int type; + + if (!s) + break; + + type = mouse_get_type(c); + settings_mouse_to_list[c] = d; + + if (mouse_valid(type, temp_model)) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + + settings_list_to_mouse[d] = c; + d++; + } + + c++; + } + if (mouse_valid(temp_mouse_type, temp_model)) + SendMessage(h, CB_SETCURSEL, settings_mouse_to_list[temp_mouse_type], 0); + else + SendMessage(h, CB_SETCURSEL, 0, 0); } break; case IDC_COMBOCPUM: @@ -559,6 +650,14 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR else EnableWindow(h, TRUE); SendMessage(h, BM_SETCHECK, ((cpu_flags & CPU_SUPPORTS_DYNAREC) && temp_dynarec) || (cpu_flags & CPU_REQUIRES_DYNAREC), 0); + + h = GetDlgItem(hdlg, IDC_COMBOWS); + cpu_type = models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + if (cpu_type >= CPU_286 && cpu_type <= CPU_386DX) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + } break; case IDC_COMBO3: @@ -581,9 +680,23 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR else EnableWindow(h, TRUE); SendMessage(h, BM_SETCHECK, ((cpu_flags & CPU_SUPPORTS_DYNAREC) && temp_dynarec) || (cpu_flags & CPU_REQUIRES_DYNAREC), 0); + + h = GetDlgItem(hdlg, IDC_COMBOWS); + cpu_type = models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + if (cpu_type >= CPU_286 && cpu_type <= CPU_386DX) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); } break; + case IDC_CONFIGUREMOD: + h = GetDlgItem(hdlg, IDC_COMBO1); + temp_model = listtomodel[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + deviceconfig_open(hdlg, (void *)model_getdevice(temp_model)); + break; + case IDC_CONFIGUREVID: h = GetDlgItem(hdlg, IDC_COMBOVID); SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp_str); diff --git a/src/win-hdconf.c b/src/win-hdconf.c index 7ee127a88..bf762a552 100644 --- a/src/win-hdconf.c +++ b/src/win-hdconf.c @@ -39,8 +39,12 @@ static void update_hdd_cdrom(HWND hdlg) SendMessage(h, BM_SETCHECK, (new_cdrom_channel == 3) ? 0 : 1, 0); h = GetDlgItem(hdlg, IDC_FCDROM); SendMessage(h, BM_SETCHECK, (new_cdrom_channel == 3) ? 1 : 0, 0); + h = GetDlgItem(hdlg, IDC_GHDD); + SendMessage(h, BM_SETCHECK, (new_cdrom_channel == 4) ? 0 : 1, 0); h = GetDlgItem(hdlg, IDC_GCDROM); SendMessage(h, BM_SETCHECK, (new_cdrom_channel == 4) ? 1 : 0, 0); + h = GetDlgItem(hdlg, IDC_HHDD); + SendMessage(h, BM_SETCHECK, (new_cdrom_channel == 5) ? 0 : 1, 0); h = GetDlgItem(hdlg, IDC_HCDROM); SendMessage(h, BM_SETCHECK, (new_cdrom_channel == 5) ? 1 : 0, 0); } @@ -408,7 +412,7 @@ BOOL CALLBACK hdsize_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPar static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND h; - hard_disk_t hd[4]; + hard_disk_t hd[6]; FILE *f; off64_t sz; int ret; @@ -422,6 +426,8 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR hd[1] = hdc[1]; hd[2] = hdc[2]; hd[3] = hdc[3]; + hd[4] = hdc[4]; + hd[5] = hdc[5]; hd_changed = 0; h = GetDlgItem(hdlg, IDC_EDIT_C_SPT); @@ -472,6 +478,30 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h= GetDlgItem(hdlg, IDC_EDIT_F_FN); SendMessage(h, WM_SETTEXT, 0, (LPARAM)ide_fn[3]); + h = GetDlgItem(hdlg, IDC_EDIT_G_SPT); + sprintf(s, "%" PRIu64, hdc[4].spt); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_HPC); + sprintf(s, "%" PRIu64, hdc[4].hpc); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_CYL); + sprintf(s, "%" PRIu64, hdc[4].tracks); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h= GetDlgItem(hdlg, IDC_EDIT_G_FN); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)ide_fn[4]); + + h = GetDlgItem(hdlg, IDC_EDIT_H_SPT); + sprintf(s, "%" PRIu64, hdc[5].spt); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_HPC); + sprintf(s, "%" PRIu64, hdc[5].hpc); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_CYL); + sprintf(s, "%" PRIu64, hdc[5].tracks); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h= GetDlgItem(hdlg, IDC_EDIT_H_FN); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)ide_fn[5]); + h = GetDlgItem(hdlg, IDC_TEXT_C_SIZE); sprintf(s, "Size: %" PRIu64 " MB", (hd[0].tracks*hd[0].hpc*hd[0].spt) >> 11); SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); @@ -488,6 +518,14 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR sprintf(s, "Size: %" PRIu64 " MB", (hd[3].tracks*hd[3].hpc*hd[3].spt) >> 11); SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_TEXT_G_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd[4].tracks*hd[4].hpc*hd[4].spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + + h = GetDlgItem(hdlg, IDC_TEXT_H_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd[5].tracks*hd[5].hpc*hd[5].spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + new_cdrom_channel = atapi_cdrom_channel; update_hdd_cdrom(hdlg); @@ -549,10 +587,36 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR h = GetDlgItem(hdlg, IDC_EDIT_F_FN); SendMessage(h, WM_GETTEXT, 511, (LPARAM)ide_fn[3]); + h = GetDlgItem(hdlg, IDC_EDIT_G_SPT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[4].spt); + h = GetDlgItem(hdlg, IDC_EDIT_G_HPC); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[4].hpc); + h = GetDlgItem(hdlg, IDC_EDIT_G_CYL); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[4].tracks); + h = GetDlgItem(hdlg, IDC_EDIT_G_FN); + SendMessage(h, WM_GETTEXT, 511, (LPARAM)ide_fn[4]); + + h = GetDlgItem(hdlg, IDC_EDIT_H_SPT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[5].spt); + h = GetDlgItem(hdlg, IDC_EDIT_H_HPC); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[5].hpc); + h = GetDlgItem(hdlg, IDC_EDIT_H_CYL); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[5].tracks); + h = GetDlgItem(hdlg, IDC_EDIT_H_FN); + SendMessage(h, WM_GETTEXT, 511, (LPARAM)ide_fn[5]); + hdc[0] = hd[0]; hdc[1] = hd[1]; hdc[2] = hd[2]; hdc[3] = hd[3]; + hdc[4] = hd[4]; + hdc[5] = hd[5]; atapi_cdrom_channel = new_cdrom_channel; @@ -610,6 +674,28 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR SetDlgItemText(hdlg, IDC_EDIT_F_FN, ""); hd_changed = 1; return TRUE; + case IDC_EJECTG: + hd[4].spt = 0; + hd[4].hpc = 0; + hd[4].tracks = 0; + ide_fn[4][0] = 0; + SetDlgItemText(hdlg, IDC_EDIT_G_SPT, "0"); + SetDlgItemText(hdlg, IDC_EDIT_G_HPC, "0"); + SetDlgItemText(hdlg, IDC_EDIT_G_CYL, "0"); + SetDlgItemText(hdlg, IDC_EDIT_G_FN, ""); + hd_changed = 1; + return TRUE; + case IDC_EJECTH: + hd[5].spt = 0; + hd[5].hpc = 0; + hd[5].tracks = 0; + ide_fn[5][0] = 0; + SetDlgItemText(hdlg, IDC_EDIT_H_SPT, "0"); + SetDlgItemText(hdlg, IDC_EDIT_H_HPC, "0"); + SetDlgItemText(hdlg, IDC_EDIT_H_CYL, "0"); + SetDlgItemText(hdlg, IDC_EDIT_H_FN, ""); + hd_changed = 1; + return TRUE; case IDC_CNEW: if (DialogBox(hinstance, TEXT("HdNewDlg"), hdlg, hdnew_dlgproc) == 1) @@ -943,6 +1029,172 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR } return TRUE; + case IDC_GNEW: + if (DialogBox(hinstance, TEXT("HdNewDlg"), hdlg, hdnew_dlgproc) == 1) + { + h = GetDlgItem(hdlg, IDC_EDIT_G_SPT); + sprintf(s, "%" PRIu64, hd_new_spt); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_HPC); + sprintf(s, "%" PRIu64, hd_new_hpc); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_CYL); + sprintf(s, "%" PRIu64, hd_new_cyl); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_FN); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)hd_new_name); + + h= GetDlgItem(hdlg, IDC_TEXT_G_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd_new_cyl*hd_new_hpc*hd_new_spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + + hd_changed = 1; + } + return TRUE; + + case IDC_GFILE: + if (!getfile(hdlg, "Hard disc image (*.HDI;*.IMA;*.IMG;*.VHD)\0*.HDI;*.IMA;*.IMG;*.VHD\0All files (*.*)\0*.*\0", "")) + { + f = fopen64(openfilestring, "rb"); + if (!f) + { + MessageBox(ghwnd,"Can't open file for read","86Box error",MB_OK); + return TRUE; + } + + if (image_is_hdi(openfilestring)) + { + fseeko64(f, 0x10, SEEK_END); + fread(§or_size, 1, 4, f); + if (sector_size != 512) + { + MessageBox(ghwnd,"HDI image with a sector size that is not 512","86Box error",MB_OK); + fclose(f); + return TRUE; + } + fread(&hd_new_spt, 1, 4, f); + fread(&hd_new_hpc, 1, 4, f); + fread(&hd_new_cyl, 1, 4, f); + + ret = 1; + } + else + { + fseeko64(f, -1, SEEK_END); + sz = ftello64(f) + 1; + fclose(f); + hd_new_spt = 63; + hd_new_hpc = 16; + hd_new_cyl = ((sz / 512) / 16) / 63; + + ret = DialogBox(hinstance, TEXT("HdSizeDlg"), hdlg, hdsize_dlgproc); + } + if (ret == 1) + { + h = GetDlgItem(hdlg, IDC_EDIT_G_SPT); + sprintf(s, "%" PRIu64, hd_new_spt); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_HPC); + sprintf(s, "%" PRIu64, hd_new_hpc); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_CYL); + sprintf(s, "%" PRIu64, hd_new_cyl); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_G_FN); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring); + + h = GetDlgItem(hdlg, IDC_TEXT_G_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd_new_cyl*hd_new_hpc*hd_new_spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + + hd_changed = 1; + } + } + return TRUE; + + case IDC_HNEW: + if (DialogBox(hinstance, TEXT("HdNewDlg"), hdlg, hdnew_dlgproc) == 1) + { + h = GetDlgItem(hdlg, IDC_EDIT_H_SPT); + sprintf(s, "%" PRIu64, hd_new_spt); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_HPC); + sprintf(s, "%" PRIu64, hd_new_hpc); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_CYL); + sprintf(s, "%" PRIu64, hd_new_cyl); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_FN); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)hd_new_name); + + h= GetDlgItem(hdlg, IDC_TEXT_H_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd_new_cyl*hd_new_hpc*hd_new_spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + + hd_changed = 1; + } + return TRUE; + + case IDC_HFILE: + if (!getfile(hdlg, "Hard disc image (*.HDI;*.IMA;*.IMG;*.VHD)\0*.HDI;*.IMA;*.IMG;*.VHD\0All files (*.*)\0*.*\0", "")) + { + f = fopen64(openfilestring, "rb"); + if (!f) + { + MessageBox(ghwnd,"Can't open file for read","86Box error",MB_OK); + return TRUE; + } + + if (image_is_hdi(openfilestring)) + { + fseeko64(f, 0x10, SEEK_END); + fread(§or_size, 1, 4, f); + if (sector_size != 512) + { + MessageBox(ghwnd,"HDI image with a sector size that is not 512","86Box error",MB_OK); + fclose(f); + return TRUE; + } + fread(&hd_new_spt, 1, 4, f); + fread(&hd_new_hpc, 1, 4, f); + fread(&hd_new_cyl, 1, 4, f); + + ret = 1; + } + else + { + fseeko64(f, -1, SEEK_END); + sz = ftello64(f) + 1; + fclose(f); + hd_new_spt = 63; + hd_new_hpc = 16; + hd_new_cyl = ((sz / 512) / 16) / 63; + + ret = DialogBox(hinstance, TEXT("HdSizeDlg"), hdlg, hdsize_dlgproc); + } + if (ret == 1) + { + h = GetDlgItem(hdlg, IDC_EDIT_H_SPT); + sprintf(s, "%" PRIu64, hd_new_spt); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_HPC); + sprintf(s, "%" PRIu64, hd_new_hpc); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_CYL); + sprintf(s, "%" PRIu64, hd_new_cyl); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + h = GetDlgItem(hdlg, IDC_EDIT_H_FN); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring); + + h = GetDlgItem(hdlg, IDC_TEXT_H_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd_new_cyl*hd_new_hpc*hd_new_spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + + hd_changed = 1; + } + } + return TRUE; + case IDC_EDIT_C_SPT: case IDC_EDIT_C_HPC: case IDC_EDIT_C_CYL: h = GetDlgItem(hdlg, IDC_EDIT_C_SPT); SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); @@ -1007,6 +1259,38 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); return TRUE; + case IDC_EDIT_G_SPT: case IDC_EDIT_G_HPC: case IDC_EDIT_G_CYL: + h = GetDlgItem(hdlg, IDC_EDIT_G_SPT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[4].spt); + h = GetDlgItem(hdlg, IDC_EDIT_G_HPC); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[4].hpc); + h = GetDlgItem(hdlg, IDC_EDIT_G_CYL); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[4].tracks); + + h = GetDlgItem(hdlg, IDC_TEXT_G_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd[4].tracks*hd[4].hpc*hd[4].spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + return TRUE; + + case IDC_EDIT_H_SPT: case IDC_EDIT_H_HPC: case IDC_EDIT_H_CYL: + h = GetDlgItem(hdlg, IDC_EDIT_H_SPT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[5].spt); + h = GetDlgItem(hdlg, IDC_EDIT_H_HPC); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[5].hpc); + h = GetDlgItem(hdlg, IDC_EDIT_H_CYL); + SendMessage(h, WM_GETTEXT, 255, (LPARAM)s); + sscanf(s, "%" PRIu64, &hd[5].tracks); + + h = GetDlgItem(hdlg, IDC_TEXT_H_SIZE); + sprintf(s, "Size: %" PRIu64 " MB", (hd[5].tracks*hd[5].hpc*hd[5].spt) >> 11); + SendMessage(h, WM_SETTEXT, 0, (LPARAM)s); + return TRUE; + case IDC_CHDD: if (new_cdrom_channel == 0) new_cdrom_channel = -1; @@ -1027,6 +1311,16 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR new_cdrom_channel = -1; update_hdd_cdrom(hdlg); return TRUE; + case IDC_GHDD: + if (new_cdrom_channel == 4) + new_cdrom_channel = -1; + update_hdd_cdrom(hdlg); + return TRUE; + case IDC_HHDD: + if (new_cdrom_channel == 5) + new_cdrom_channel = -1; + update_hdd_cdrom(hdlg); + return TRUE; case IDC_CCDROM: new_cdrom_channel = 0; diff --git a/src/win-mouse.cc b/src/win-mouse.cc index 0b0824cc7..0eacdee78 100644 --- a/src/win-mouse.cc +++ b/src/win-mouse.cc @@ -14,12 +14,12 @@ extern "C" void pclog(const char *format, ...); extern "C" void mouse_init(); extern "C" void mouse_close(); extern "C" void mouse_poll_host(); -extern "C" void mouse_get_mickeys(int *x, int *y); +extern "C" void mouse_get_mickeys(int *x, int *y, int *z); static LPDIRECTINPUT8 lpdi; static LPDIRECTINPUTDEVICE8 lpdi_mouse = NULL; static DIMOUSESTATE mousestate; -static int mouse_x = 0, mouse_y = 0; +static int mouse_x = 0, mouse_y = 0, mouse_z = 0; int mouse_buttons = 0; void mouse_init() @@ -61,13 +61,15 @@ void mouse_poll_host() mouse_buttons |= 4; mouse_x += mousestate.lX; mouse_y += mousestate.lY; + mouse_z += mousestate.lZ/120; if (!mousecapture && !video_fullscreen) mouse_x = mouse_y = mouse_buttons = 0; } -void mouse_get_mickeys(int *x, int *y) +void mouse_get_mickeys(int *x, int *y, int *z) { *x = mouse_x; *y = mouse_y; - mouse_x = mouse_y = 0; + *z = mouse_z; + mouse_x = mouse_y = mouse_z = 0; } diff --git a/src/win-status.c b/src/win-status.c index 58d97e12e..345f9e2e5 100644 --- a/src/win-status.c +++ b/src/win-status.c @@ -59,7 +59,7 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR #endif*/ segareads, segawrites, - clockrate - (sreadlnum*memwaitstate) - (swritelnum*memwaitstate) - scycles_lost, + clockrate - scycles_lost, pit_timer0_freq(), ((double)main_time * 100.0) / status_diff, ((double)main_time * 100.0) / timer_freq diff --git a/src/win.c b/src/win.c index 0de086a83..64f82a996 100644 --- a/src/win.c +++ b/src/win.c @@ -27,6 +27,7 @@ #include "cpu.h" #include "cdrom.h" #include "model.h" +#include "mouse.h" #include "nethandler.h" #include "nvr.h" #include "sound.h" @@ -322,7 +323,7 @@ static void initmenu(void) HMENU m; char s[32]; m=GetSubMenu(menu,1); /*Disc*/ - m=GetSubMenu(m,9); /*CD-ROM*/ + m=GetSubMenu(m,17); /*CD-ROM*/ /* Loop through each Windows drive letter and test to see if it's a CDROM */ @@ -722,9 +723,17 @@ int WINAPI WinMain (HINSTANCE hThisInstance, } if (cdrom_drive == 200) + { CheckMenuItem(menu, IDM_CDROM_ISO, MF_CHECKED); + } else + { CheckMenuItem(menu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED); + } + + CheckMenuItem(menu, IDM_VID_FORCE43, force_43 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menu, IDM_VID_OVERSCAN, enable_overscan ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(menu, IDM_VID_FLASH, enable_flash ? MF_CHECKED : MF_UNCHECKED); // pclog("Checking video resize menu item...\n"); if (vid_resize) CheckMenuItem(menu, IDM_VID_RESIZE, MF_CHECKED); @@ -1127,6 +1136,13 @@ int scsi_set_dma(HMENU hmenu, int dma, int id) return 1; } +void video_toggle_option(HMENU hmenu, int *val, int id) +{ + *val ^= 1; + CheckMenuItem(hmenu, id, *val ? MF_CHECKED : MF_UNCHECKED); + saveconfig(); +} + LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hmenu; @@ -1176,34 +1192,62 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM case IDM_FILE_EXIT: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; - case IDM_DISC_A: - case IDM_DISC_A_WP: + case IDM_DISC_1: + case IDM_DISC_1_WP: if (!getfile(hwnd, floppy_image_extensions, discfns[0])) { disc_close(0); - ui_writeprot[0] = (LOWORD(wParam) == IDM_DISC_A_WP) ? 1 : 0; + ui_writeprot[0] = (LOWORD(wParam) == IDM_DISC_1_WP) ? 1 : 0; disc_load(0, openfilestring); saveconfig(); } break; - case IDM_DISC_B: - case IDM_DISC_B_WP: + case IDM_DISC_2: + case IDM_DISC_2_WP: if (!getfile(hwnd, floppy_image_extensions, discfns[1])) { disc_close(1); - ui_writeprot[1] = (LOWORD(wParam) == IDM_DISC_B_WP) ? 1 : 0; + ui_writeprot[1] = (LOWORD(wParam) == IDM_DISC_2_WP) ? 1 : 0; disc_load(1, openfilestring); saveconfig(); } break; - case IDM_EJECT_A: + case IDM_DISC_3: + case IDM_DISC_3_WP: + if (!getfile(hwnd, floppy_image_extensions, discfns[2])) + { + disc_close(2); + ui_writeprot[2] = (LOWORD(wParam) == IDM_DISC_3_WP) ? 1 : 0; + disc_load(2, openfilestring); + saveconfig(); + } + break; + case IDM_DISC_4: + case IDM_DISC_4_WP: + if (!getfile(hwnd, floppy_image_extensions, discfns[3])) + { + disc_close(3); + ui_writeprot[3] = (LOWORD(wParam) == IDM_DISC_4_WP) ? 1 : 0; + disc_load(3, openfilestring); + saveconfig(); + } + break; + case IDM_EJECT_1: disc_close(0); saveconfig(); break; - case IDM_EJECT_B: + case IDM_EJECT_2: disc_close(1); saveconfig(); break; + case IDM_EJECT_3: + disc_close(2); + saveconfig(); + break; + case IDM_EJECT_4: + disc_close(3); + saveconfig(); + break; case IDM_HDCONF: hdconf_open(hwnd); break; @@ -1279,6 +1323,18 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM saveconfig(); break; + case IDM_VID_FORCE43: + video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); + break; + + case IDM_VID_OVERSCAN: + video_toggle_option(hmenu, &enable_overscan, IDM_VID_OVERSCAN); + break; + + case IDM_VID_FLASH: + video_toggle_option(hmenu, &enable_flash, IDM_VID_FLASH); + break; + case IDM_VID_SCREENSHOT: take_screenshot(); break; @@ -1723,7 +1779,8 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM break; case WM_MBUTTONUP: - releasemouse(); + if (!(mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON)) + releasemouse(); break; case WM_ENTERMENULOOP: diff --git a/src/x86_ops_arith.h b/src/x86_ops_arith.h index dd05e5688..3a9f96953 100644 --- a/src/x86_ops_arith.h +++ b/src/x86_ops_arith.h @@ -10,6 +10,7 @@ setflags ## 8 flagops; \ setr8(cpu_rm, operation); \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \ } \ else \ { \ @@ -18,6 +19,7 @@ seteab(operation); if (cpu_state.abrt) return 1; \ setflags ## 8 flagops; \ CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 0); \ } \ return 0; \ } \ @@ -32,6 +34,7 @@ setflags ## 8 flagops; \ setr8(cpu_rm, operation); \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \ } \ else \ { \ @@ -40,6 +43,7 @@ seteab(operation); if (cpu_state.abrt) return 1; \ setflags ## 8 flagops; \ CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 1); \ } \ return 0; \ } \ @@ -55,6 +59,7 @@ setflags ## 16 flagops; \ cpu_state.regs[cpu_rm].w = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \ } \ else \ { \ @@ -63,6 +68,7 @@ seteaw(operation); if (cpu_state.abrt) return 1; \ setflags ## 16 flagops; \ CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 0); \ } \ return 0; \ } \ @@ -77,6 +83,7 @@ setflags ## 16 flagops; \ cpu_state.regs[cpu_rm].w = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \ } \ else \ { \ @@ -85,6 +92,7 @@ seteaw(operation); if (cpu_state.abrt) return 1; \ setflags ## 16 flagops; \ CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 1); \ } \ return 0; \ } \ @@ -100,6 +108,7 @@ setflags ## 32 flagops; \ cpu_state.regs[cpu_rm].l = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \ } \ else \ { \ @@ -107,7 +116,8 @@ uint32_t src = cpu_state.regs[cpu_reg].l; \ seteal(operation); if (cpu_state.abrt) return 1; \ setflags ## 32 flagops; \ - CLOCK_CYCLES(timing_mrl); \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 0); \ } \ return 0; \ } \ @@ -122,6 +132,7 @@ setflags ## 32 flagops; \ cpu_state.regs[cpu_rm].l = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \ } \ else \ { \ @@ -129,7 +140,8 @@ uint32_t src = cpu_state.regs[cpu_reg].l; \ seteal(operation); if (cpu_state.abrt) return 1; \ setflags ## 32 flagops; \ - CLOCK_CYCLES(timing_mrl); \ + CLOCK_CYCLES(timing_mr); \ + PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 1); \ } \ return 0; \ } \ @@ -144,6 +156,7 @@ setflags ## 8 flagops; \ setr8(cpu_reg, operation); \ CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \ return 0; \ } \ static int op ## name ## _b_rm_a32(uint32_t fetchdat) \ @@ -156,6 +169,7 @@ setflags ## 8 flagops; \ setr8(cpu_reg, operation); \ CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \ return 0; \ } \ \ @@ -169,6 +183,7 @@ setflags ## 16 flagops; \ cpu_state.regs[cpu_reg].w = operation; \ CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \ return 0; \ } \ static int op ## name ## _w_rm_a32(uint32_t fetchdat) \ @@ -181,6 +196,7 @@ setflags ## 16 flagops; \ cpu_state.regs[cpu_reg].w = operation; \ CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \ return 0; \ } \ \ @@ -194,6 +210,7 @@ setflags ## 32 flagops; \ cpu_state.regs[cpu_reg].l = operation; \ CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); \ return 0; \ } \ static int op ## name ## _l_rm_a32(uint32_t fetchdat) \ @@ -206,6 +223,7 @@ setflags ## 32 flagops; \ cpu_state.regs[cpu_reg].l = operation; \ CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \ + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); \ return 0; \ } \ \ @@ -217,6 +235,7 @@ setflags ## 8 flagops; \ AL = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); \ return 0; \ } \ \ @@ -228,6 +247,7 @@ setflags ## 16 flagops; \ AX = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); \ return 0; \ } \ \ @@ -239,6 +259,7 @@ setflags ## 32 flagops; \ EAX = operation; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); \ return 0; \ } @@ -258,6 +279,7 @@ static int opCMP_b_rmw_a16(uint32_t fetchdat) setsub8(dst, getr8(cpu_reg)); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); return 0; } static int opCMP_b_rmw_a32(uint32_t fetchdat) @@ -268,6 +290,7 @@ static int opCMP_b_rmw_a32(uint32_t fetchdat) setsub8(dst, getr8(cpu_reg)); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); return 0; } @@ -279,6 +302,7 @@ static int opCMP_w_rmw_a16(uint32_t fetchdat) setsub16(dst, cpu_state.regs[cpu_reg].w); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); return 0; } static int opCMP_w_rmw_a32(uint32_t fetchdat) @@ -289,6 +313,7 @@ static int opCMP_w_rmw_a32(uint32_t fetchdat) setsub16(dst, cpu_state.regs[cpu_reg].w); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); return 0; } @@ -300,6 +325,7 @@ static int opCMP_l_rmw_a16(uint32_t fetchdat) setsub32(dst, cpu_state.regs[cpu_reg].l); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); return 0; } static int opCMP_l_rmw_a32(uint32_t fetchdat) @@ -310,6 +336,7 @@ static int opCMP_l_rmw_a32(uint32_t fetchdat) setsub32(dst, cpu_state.regs[cpu_reg].l); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); return 0; } @@ -320,6 +347,7 @@ static int opCMP_b_rm_a16(uint32_t fetchdat) src = geteab(); if (cpu_state.abrt) return 1; setsub8(getr8(cpu_reg), src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); return 0; } static int opCMP_b_rm_a32(uint32_t fetchdat) @@ -329,6 +357,7 @@ static int opCMP_b_rm_a32(uint32_t fetchdat) src = geteab(); if (cpu_state.abrt) return 1; setsub8(getr8(cpu_reg), src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); return 0; } @@ -339,6 +368,7 @@ static int opCMP_w_rm_a16(uint32_t fetchdat) src = geteaw(); if (cpu_state.abrt) return 1; setsub16(cpu_state.regs[cpu_reg].w, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); return 0; } static int opCMP_w_rm_a32(uint32_t fetchdat) @@ -348,6 +378,7 @@ static int opCMP_w_rm_a32(uint32_t fetchdat) src = geteaw(); if (cpu_state.abrt) return 1; setsub16(cpu_state.regs[cpu_reg].w, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); return 0; } @@ -358,6 +389,7 @@ static int opCMP_l_rm_a16(uint32_t fetchdat) src = geteal(); if (cpu_state.abrt) return 1; setsub32(cpu_state.regs[cpu_reg].l, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); return 0; } static int opCMP_l_rm_a32(uint32_t fetchdat) @@ -367,6 +399,7 @@ static int opCMP_l_rm_a32(uint32_t fetchdat) src = geteal(); if (cpu_state.abrt) return 1; setsub32(cpu_state.regs[cpu_reg].l, src); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); return 0; } @@ -375,6 +408,7 @@ static int opCMP_AL_imm(uint32_t fetchdat) uint8_t src = getbytef(); setsub8(AL, src); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } @@ -383,6 +417,7 @@ static int opCMP_AX_imm(uint32_t fetchdat) uint16_t src = getwordf(); setsub16(AX, src); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } @@ -391,6 +426,7 @@ static int opCMP_EAX_imm(uint32_t fetchdat) uint32_t src = getlong(); if (cpu_state.abrt) return 1; setsub32(EAX, src); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } @@ -403,6 +439,7 @@ static int opTEST_b_a16(uint32_t fetchdat) setznp8(temp & temp2); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); return 0; } static int opTEST_b_a32(uint32_t fetchdat) @@ -414,6 +451,7 @@ static int opTEST_b_a32(uint32_t fetchdat) setznp8(temp & temp2); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); return 0; } @@ -426,6 +464,7 @@ static int opTEST_w_a16(uint32_t fetchdat) setznp16(temp & temp2); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); return 0; } static int opTEST_w_a32(uint32_t fetchdat) @@ -437,6 +476,7 @@ static int opTEST_w_a32(uint32_t fetchdat) setznp16(temp & temp2); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); return 0; } @@ -449,6 +489,7 @@ static int opTEST_l_a16(uint32_t fetchdat) setznp32(temp & temp2); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 0); return 0; } static int opTEST_l_a32(uint32_t fetchdat) @@ -460,6 +501,7 @@ static int opTEST_l_a32(uint32_t fetchdat) setznp32(temp & temp2); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 1); return 0; } @@ -468,6 +510,7 @@ static int opTEST_AL(uint32_t fetchdat) uint8_t temp = getbytef(); setznp8(AL & temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opTEST_AX(uint32_t fetchdat) @@ -475,6 +518,7 @@ static int opTEST_AX(uint32_t fetchdat) uint16_t temp = getwordf(); setznp16(AX & temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opTEST_EAX(uint32_t fetchdat) @@ -482,6 +526,7 @@ static int opTEST_EAX(uint32_t fetchdat) uint32_t temp = getlong(); if (cpu_state.abrt) return 1; setznp32(EAX & temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } @@ -545,6 +590,10 @@ static int op80_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); src = getbyte(); if (cpu_state.abrt) return 1; ARITH_MULTI(b, 8); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } @@ -555,6 +604,10 @@ static int op80_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); src = getbyte(); if (cpu_state.abrt) return 1; ARITH_MULTI(b, 8); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); return 0; } @@ -565,6 +618,10 @@ static int op81_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); src = getword(); if (cpu_state.abrt) return 1; ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } @@ -575,6 +632,10 @@ static int op81_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); src = getword(); if (cpu_state.abrt) return 1; ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); return 0; } @@ -585,6 +646,10 @@ static int op81_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); src = getlong(); if (cpu_state.abrt) return 1; ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); return 0; } @@ -595,6 +660,10 @@ static int op81_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); src = getlong(); if (cpu_state.abrt) return 1; ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); return 0; } @@ -607,6 +676,10 @@ static int op83_w_a16(uint32_t fetchdat) src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xff00; ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } @@ -618,6 +691,10 @@ static int op83_w_a32(uint32_t fetchdat) src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xff00; ARITH_MULTI(w, 16); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); return 0; } @@ -630,6 +707,10 @@ static int op83_l_a16(uint32_t fetchdat) src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xffffff00; ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); return 0; } @@ -641,6 +722,10 @@ static int op83_l_a32(uint32_t fetchdat) src = getbyte(); if (cpu_state.abrt) return 1; if (src & 0x80) src |= 0xffffff00; ARITH_MULTI(l, 32); + if ((rmdat & 0x38) == 0x38) + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); + else + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); return 0; } diff --git a/src/x86_ops_bcd.h b/src/x86_ops_bcd.h index 826c6505b..241216b14 100644 --- a/src/x86_ops_bcd.h +++ b/src/x86_ops_bcd.h @@ -1,6 +1,3 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ static int opAAA(uint32_t fetchdat) { flags_rebuild(); @@ -14,6 +11,7 @@ static int opAAA(uint32_t fetchdat) flags &= ~(A_FLAG | C_FLAG); AL &= 0xF; CLOCK_CYCLES(is486 ? 3 : 4); + PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); return 0; } @@ -25,6 +23,7 @@ static int opAAD(uint32_t fetchdat) AH = 0; setznp16(AX); CLOCK_CYCLES((is486) ? 14 : 19); + PREFETCH_RUN(is486 ? 14 : 19, 2, -1, 0,0,0,0, 0); return 0; } @@ -36,6 +35,7 @@ static int opAAM(uint32_t fetchdat) AL %= base; setznp16(AX); CLOCK_CYCLES((is486) ? 15 : 17); + PREFETCH_RUN(is486 ? 15 : 17, 2, -1, 0,0,0,0, 0); return 0; } @@ -52,6 +52,7 @@ static int opAAS(uint32_t fetchdat) flags &= ~(A_FLAG | C_FLAG); AL &= 0xF; CLOCK_CYCLES(is486 ? 3 : 4); + PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); return 0; } @@ -78,6 +79,7 @@ static int opDAA(uint32_t fetchdat) flags_rebuild(); flags |= tempw; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); return 0; } @@ -105,6 +107,7 @@ static int opDAS(uint32_t fetchdat) flags_rebuild(); flags |= tempw; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); return 0; } diff --git a/src/x86_ops_bit.h b/src/x86_ops_bit.h index de4c8604b..dc10b4f6c 100644 --- a/src/x86_ops_bit.h +++ b/src/x86_ops_bit.h @@ -10,6 +10,7 @@ static int opBT_w_r_a16(uint32_t fetchdat) else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 0); return 0; } static int opBT_w_r_a32(uint32_t fetchdat) @@ -24,6 +25,7 @@ static int opBT_w_r_a32(uint32_t fetchdat) else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 1); return 0; } static int opBT_l_r_a16(uint32_t fetchdat) @@ -38,6 +40,7 @@ static int opBT_l_r_a16(uint32_t fetchdat) else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 0); return 0; } static int opBT_l_r_a32(uint32_t fetchdat) @@ -52,6 +55,7 @@ static int opBT_l_r_a32(uint32_t fetchdat) else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 1); return 0; } @@ -72,6 +76,7 @@ static int opBT_l_r_a32(uint32_t fetchdat) else flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 0); \ return 0; \ } \ static int opBT ## name ## _w_r_a32(uint32_t fetchdat) \ @@ -90,6 +95,7 @@ static int opBT_l_r_a32(uint32_t fetchdat) else flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 1); \ return 0; \ } \ static int opBT ## name ## _l_r_a16(uint32_t fetchdat) \ @@ -108,6 +114,7 @@ static int opBT_l_r_a32(uint32_t fetchdat) else flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 0); \ return 0; \ } \ static int opBT ## name ## _l_r_a32(uint32_t fetchdat) \ @@ -126,6 +133,7 @@ static int opBT_l_r_a32(uint32_t fetchdat) else flags &= ~C_FLAG; \ \ CLOCK_CYCLES(6); \ + PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 1); \ return 0; \ } @@ -150,6 +158,7 @@ static int opBA_w_a16(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; case 0x28: /*BTS w,imm*/ temp |= (1 << count); @@ -171,6 +180,7 @@ static int opBA_w_a16(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } static int opBA_w_a32(uint32_t fetchdat) @@ -190,6 +200,7 @@ static int opBA_w_a32(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; case 0x28: /*BTS w,imm*/ temp |= (1 << count); @@ -211,6 +222,7 @@ static int opBA_w_a32(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } @@ -231,6 +243,7 @@ static int opBA_l_a16(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return 0; case 0x28: /*BTS w,imm*/ temp |= (1 << count); @@ -252,6 +265,7 @@ static int opBA_l_a16(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); return 0; } static int opBA_l_a32(uint32_t fetchdat) @@ -271,6 +285,7 @@ static int opBA_l_a32(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return 0; case 0x28: /*BTS w,imm*/ temp |= (1 << count); @@ -292,5 +307,6 @@ static int opBA_l_a32(uint32_t fetchdat) if (tempc) flags |= C_FLAG; else flags &= ~C_FLAG; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); return 0; } diff --git a/src/x86_ops_bitscan.h b/src/x86_ops_bitscan.h index edd3fde33..834211128 100644 --- a/src/x86_ops_bitscan.h +++ b/src/x86_ops_bitscan.h @@ -7,6 +7,7 @@ for (c = start; c != end; c += dir) \ { \ CLOCK_CYCLES(time); \ + instr_cycles += time; \ if (temp & (1 << c)) \ { \ dest = c; \ @@ -20,6 +21,7 @@ static int opBSF_w_a16(uint32_t fetchdat) { uint16_t temp; + int instr_cycles; fetch_ea_16(fetchdat); temp = geteaw(); if (cpu_state.abrt) return 1; @@ -27,11 +29,14 @@ static int opBSF_w_a16(uint32_t fetchdat) BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opBSF_w_a32(uint32_t fetchdat) { uint16_t temp; + int instr_cycles; fetch_ea_32(fetchdat); temp = geteaw(); if (cpu_state.abrt) return 1; @@ -39,11 +44,14 @@ static int opBSF_w_a32(uint32_t fetchdat) BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opBSF_l_a16(uint32_t fetchdat) { uint32_t temp; + int instr_cycles; fetch_ea_16(fetchdat); temp = geteal(); if (cpu_state.abrt) return 1; @@ -51,24 +59,30 @@ static int opBSF_l_a16(uint32_t fetchdat) BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return 0; } static int opBSF_l_a32(uint32_t fetchdat) { uint32_t temp; - + int instr_cycles; + fetch_ea_32(fetchdat); temp = geteal(); if (cpu_state.abrt) return 1; BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return 0; } static int opBSR_w_a16(uint32_t fetchdat) { uint16_t temp; + int instr_cycles; fetch_ea_16(fetchdat); temp = geteaw(); if (cpu_state.abrt) return 1; @@ -76,11 +90,14 @@ static int opBSR_w_a16(uint32_t fetchdat) BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opBSR_w_a32(uint32_t fetchdat) { uint16_t temp; + int instr_cycles; fetch_ea_32(fetchdat); temp = geteaw(); if (cpu_state.abrt) return 1; @@ -88,11 +105,14 @@ static int opBSR_w_a32(uint32_t fetchdat) BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opBSR_l_a16(uint32_t fetchdat) { uint32_t temp; + int instr_cycles; fetch_ea_16(fetchdat); temp = geteal(); if (cpu_state.abrt) return 1; @@ -100,11 +120,14 @@ static int opBSR_l_a16(uint32_t fetchdat) BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return 0; } static int opBSR_l_a32(uint32_t fetchdat) { uint32_t temp; + int instr_cycles; fetch_ea_32(fetchdat); temp = geteal(); if (cpu_state.abrt) return 1; @@ -112,6 +135,8 @@ static int opBSR_l_a32(uint32_t fetchdat) BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); CLOCK_CYCLES((is486) ? 6 : 10); + instr_cycles += ((is486) ? 6 : 10); + PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return 0; } diff --git a/src/x86_ops_call.h b/src/x86_ops_call.h index b6c72e06f..40d90a09e 100644 --- a/src/x86_ops_call.h +++ b/src/x86_ops_call.h @@ -61,26 +61,32 @@ static int opCALL_far_w(uint32_t fetchdat) { uint32_t old_cs, old_pc; uint16_t new_cs, new_pc; + int cycles_old = cycles; new_pc = getwordf(); new_cs = getword(); if (cpu_state.abrt) return 1; CALL_FAR_w(new_cs, new_pc); CPU_BLOCK_END(); - + PREFETCH_RUN(cycles_old-cycles, 5, -1, 0,0,cgate16 ? 2:0,cgate16 ? 0:2, 0); + PREFETCH_FLUSH(); + return 0; } static int opCALL_far_l(uint32_t fetchdat) { uint32_t old_cs, old_pc; uint32_t new_cs, new_pc; - + int cycles_old = cycles; + new_pc = getlong(); new_cs = getword(); if (cpu_state.abrt) return 1; CALL_FAR_l(new_cs, new_pc); CPU_BLOCK_END(); - + PREFETCH_RUN(cycles_old-cycles, 7, -1, 0,0,cgate16 ? 2:0,cgate16 ? 0:2, 0); + PREFETCH_FLUSH(); + return 0; } @@ -89,6 +95,7 @@ static int opFF_w_a16(uint32_t fetchdat) { uint16_t old_cs, new_cs; uint32_t old_pc, new_pc; + int cycles_old = cycles; uint16_t temp; @@ -101,12 +108,14 @@ static int opFF_w_a16(uint32_t fetchdat) seteaw(temp + 1); if (cpu_state.abrt) return 1; setadd16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x08: /*DEC w*/ temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp - 1); if (cpu_state.abrt) return 1; setsub16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x10: /*CALL*/ new_pc = geteaw(); if (cpu_state.abrt) return 1; @@ -115,6 +124,8 @@ static int opFF_w_a16(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 0); + PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ new_pc = readmemw(easeg, cpu_state.eaaddr); @@ -122,6 +133,8 @@ static int opFF_w_a16(uint32_t fetchdat) CALL_FAR_w(new_cs, new_pc); CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,cgate16 ? 2:0,cgate16 ? 0:2, 0); + PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ new_pc = geteaw(); if (cpu_state.abrt) return 1; @@ -129,6 +142,8 @@ static int opFF_w_a16(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ oxpc = cpu_state.pc; @@ -137,11 +152,14 @@ static int opFF_w_a16(uint32_t fetchdat) cpu_state.pc = new_pc; loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 0); + PREFETCH_FLUSH(); break; case 0x30: /*PUSH w*/ temp = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 0); break; default: @@ -154,6 +172,7 @@ static int opFF_w_a32(uint32_t fetchdat) { uint16_t old_cs, new_cs; uint32_t old_pc, new_pc; + int cycles_old = cycles; uint16_t temp; @@ -166,12 +185,14 @@ static int opFF_w_a32(uint32_t fetchdat) seteaw(temp + 1); if (cpu_state.abrt) return 1; setadd16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x08: /*DEC w*/ temp = geteaw(); if (cpu_state.abrt) return 1; seteaw(temp - 1); if (cpu_state.abrt) return 1; setsub16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x10: /*CALL*/ new_pc = geteaw(); if (cpu_state.abrt) return 1; @@ -180,6 +201,8 @@ static int opFF_w_a32(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 1); + PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ new_pc = readmemw(easeg, cpu_state.eaaddr); @@ -187,6 +210,8 @@ static int opFF_w_a32(uint32_t fetchdat) CALL_FAR_w(new_cs, new_pc); CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,cgate16 ? 2:0,cgate16 ? 0:2, 1); + PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ new_pc = geteaw(); if (cpu_state.abrt) return 1; @@ -194,6 +219,8 @@ static int opFF_w_a32(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,0,0,0, 1); + PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ oxpc = cpu_state.pc; @@ -202,11 +229,14 @@ static int opFF_w_a32(uint32_t fetchdat) cpu_state.pc = new_pc; loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 1); + PREFETCH_FLUSH(); break; case 0x30: /*PUSH w*/ temp = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 1); break; default: @@ -220,7 +250,8 @@ static int opFF_l_a16(uint32_t fetchdat) { uint16_t old_cs, new_cs; uint32_t old_pc, new_pc; - + int cycles_old = cycles; + uint32_t temp; fetch_ea_16(fetchdat); @@ -232,12 +263,14 @@ static int opFF_l_a16(uint32_t fetchdat) seteal(temp + 1); if (cpu_state.abrt) return 1; setadd32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x08: /*DEC l*/ temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp - 1); if (cpu_state.abrt) return 1; setsub32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x10: /*CALL*/ new_pc = geteal(); if (cpu_state.abrt) return 1; @@ -246,6 +279,8 @@ static int opFF_l_a16(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 0); + PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ new_pc = readmeml(easeg, cpu_state.eaaddr); @@ -253,6 +288,8 @@ static int opFF_l_a16(uint32_t fetchdat) CALL_FAR_l(new_cs, new_pc); CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,cgate16 ? 2:0,cgate16 ? 0:2, 0); + PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ new_pc = geteal(); if (cpu_state.abrt) return 1; @@ -260,6 +297,8 @@ static int opFF_l_a16(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 0,1,0,0, 0); + PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ oxpc = cpu_state.pc; @@ -268,11 +307,14 @@ static int opFF_l_a16(uint32_t fetchdat) cpu_state.pc = new_pc; loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 0); + PREFETCH_FLUSH(); break; case 0x30: /*PUSH l*/ temp = geteal(); if (cpu_state.abrt) return 1; PUSH_L(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 0); break; default: @@ -285,7 +327,8 @@ static int opFF_l_a32(uint32_t fetchdat) { uint16_t old_cs, new_cs; uint32_t old_pc, new_pc; - + int cycles_old = cycles; + uint32_t temp; fetch_ea_32(fetchdat); @@ -297,12 +340,14 @@ static int opFF_l_a32(uint32_t fetchdat) seteal(temp + 1); if (cpu_state.abrt) return 1; setadd32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x08: /*DEC l*/ temp = geteal(); if (cpu_state.abrt) return 1; seteal(temp - 1); if (cpu_state.abrt) return 1; setsub32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x10: /*CALL*/ new_pc = geteal(); if (cpu_state.abrt) return 1; @@ -311,6 +356,8 @@ static int opFF_l_a32(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1); + PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ new_pc = readmeml(easeg, cpu_state.eaaddr); @@ -318,6 +365,8 @@ static int opFF_l_a32(uint32_t fetchdat) CALL_FAR_l(new_cs, new_pc); CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,cgate16 ? 2:0,cgate16 ? 0:2, 1); + PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ new_pc = geteal(); if (cpu_state.abrt) return 1; @@ -325,6 +374,8 @@ static int opFF_l_a32(uint32_t fetchdat) CPU_BLOCK_END(); if (is486) CLOCK_CYCLES(5); else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1); + PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ oxpc = cpu_state.pc; @@ -333,11 +384,13 @@ static int opFF_l_a32(uint32_t fetchdat) cpu_state.pc = new_pc; loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1; CPU_BLOCK_END(); + PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1); + PREFETCH_FLUSH(); break; case 0x30: /*PUSH l*/ temp = geteal(); if (cpu_state.abrt) return 1; PUSH_L(temp); - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1); break; default: diff --git a/src/x86_ops_flag.h b/src/x86_ops_flag.h index 5b259f3b0..9f70330f9 100644 --- a/src/x86_ops_flag.h +++ b/src/x86_ops_flag.h @@ -3,6 +3,7 @@ static int opCMC(uint32_t fetchdat) flags_rebuild(); flags ^= C_FLAG; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } @@ -12,12 +13,14 @@ static int opCLC(uint32_t fetchdat) flags_rebuild(); flags &= ~C_FLAG; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opCLD(uint32_t fetchdat) { flags &= ~D_FLAG; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opCLI(uint32_t fetchdat) @@ -30,9 +33,8 @@ static int opCLI(uint32_t fetchdat) else flags &= ~I_FLAG; - CPU_BLOCK_END(); - CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } @@ -41,12 +43,14 @@ static int opSTC(uint32_t fetchdat) flags_rebuild(); flags |= C_FLAG; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opSTD(uint32_t fetchdat) { flags |= D_FLAG; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opSTI(uint32_t fetchdat) @@ -62,6 +66,7 @@ static int opSTI(uint32_t fetchdat) CPU_BLOCK_END(); CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } @@ -70,7 +75,8 @@ static int opSAHF(uint32_t fetchdat) flags_rebuild(); flags = (flags & 0xff00) | (AH & 0xd5) | 2; CLOCK_CYCLES(3); - + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); + codegen_flags_changed = 0; return 0; @@ -80,6 +86,7 @@ static int opLAHF(uint32_t fetchdat) flags_rebuild(); AH = flags & 0xff; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } @@ -93,6 +100,7 @@ static int opPUSHF(uint32_t fetchdat) flags_rebuild(); PUSH_W(flags); CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); return cpu_state.abrt; } static int opPUSHFD(uint32_t fetchdat) @@ -108,6 +116,7 @@ static int opPUSHFD(uint32_t fetchdat) flags_rebuild(); PUSH_L(flags | (tempw << 16)); CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); return cpu_state.abrt; } @@ -130,7 +139,8 @@ static int opPOPF_286(uint32_t fetchdat) flags_extract(); CLOCK_CYCLES(5); - + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); + codegen_flags_changed = 0; return 0; @@ -153,7 +163,8 @@ static int opPOPF(uint32_t fetchdat) flags_extract(); CLOCK_CYCLES(5); - + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); + codegen_flags_changed = 0; return 0; @@ -183,7 +194,8 @@ static int opPOPFD(uint32_t fetchdat) flags_extract(); CLOCK_CYCLES(5); - + PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); + codegen_flags_changed = 0; return 0; diff --git a/src/x86_ops_inc_dec.h b/src/x86_ops_inc_dec.h index 3e636639d..56293c7bf 100644 --- a/src/x86_ops_inc_dec.h +++ b/src/x86_ops_inc_dec.h @@ -4,6 +4,7 @@ setflags(reg, 1); \ reg += inc; \ CLOCK_CYCLES(timing_rr); \ + PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); \ return 0; \ } @@ -62,6 +63,7 @@ static int opINCDEC_b_a16(uint32_t fetchdat) setadd8nc(temp, 1); } CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } static int opINCDEC_b_a32(uint32_t fetchdat) @@ -82,5 +84,6 @@ static int opINCDEC_b_a32(uint32_t fetchdat) setadd8nc(temp, 1); } CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); return 0; } diff --git a/src/x86_ops_int.h b/src/x86_ops_int.h index ffba7e65d..139389160 100644 --- a/src/x86_ops_int.h +++ b/src/x86_ops_int.h @@ -1,5 +1,6 @@ static int opINT3(uint32_t fetchdat) { + int cycles_old = cycles; if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); @@ -7,11 +8,13 @@ static int opINT3(uint32_t fetchdat) } x86_int_sw(3); CLOCK_CYCLES((is486) ? 44 : 59); + PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); return 1; } static int opINT(uint32_t fetchdat) { + int cycles_old = cycles; uint8_t temp; /*if (msw&1) pclog("INT %i %i %i\n",cr0&1,eflags&VM_FLAG,IOPL);*/ @@ -55,11 +58,14 @@ static int opINT(uint32_t fetchdat) }*/ x86_int_sw(temp); + PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0); return 1; } static int opINTO(uint32_t fetchdat) { + int cycles_old = cycles; + if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); @@ -69,9 +75,11 @@ static int opINTO(uint32_t fetchdat) { cpu_state.oldpc = cpu_state.pc; x86_int_sw(4); + PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); return 1; } CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } diff --git a/src/x86_ops_io.h b/src/x86_ops_io.h index 8e106e4e1..8f190cea0 100644 --- a/src/x86_ops_io.h +++ b/src/x86_ops_io.h @@ -1,12 +1,10 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ static int opIN_AL_imm(uint32_t fetchdat) { uint16_t port = (uint16_t)getbytef(); check_io_perm(port); AL = inb(port); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); return 0; } static int opIN_AX_imm(uint32_t fetchdat) @@ -16,6 +14,7 @@ static int opIN_AX_imm(uint32_t fetchdat) check_io_perm(port + 1); AX = inw(port); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); return 0; } static int opIN_EAX_imm(uint32_t fetchdat) @@ -27,6 +26,7 @@ static int opIN_EAX_imm(uint32_t fetchdat) check_io_perm(port + 3); EAX = inl(port); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0); return 0; } @@ -36,6 +36,7 @@ static int opOUT_AL_imm(uint32_t fetchdat) check_io_perm(port); outb(port, AL); CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); if (port == 0x64) return x86_was_reset; return 0; @@ -47,6 +48,7 @@ static int opOUT_AX_imm(uint32_t fetchdat) check_io_perm(port + 1); outw(port, AX); CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); return 0; } static int opOUT_EAX_imm(uint32_t fetchdat) @@ -58,6 +60,7 @@ static int opOUT_EAX_imm(uint32_t fetchdat) check_io_perm(port + 3); outl(port, EAX); CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0); return 0; } @@ -66,6 +69,7 @@ static int opIN_AL_DX(uint32_t fetchdat) check_io_perm(DX); AL = inb(DX); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); return 0; } static int opIN_AX_DX(uint32_t fetchdat) @@ -74,6 +78,7 @@ static int opIN_AX_DX(uint32_t fetchdat) check_io_perm(DX + 1); AX = inw(DX); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); return 0; } static int opIN_EAX_DX(uint32_t fetchdat) @@ -84,6 +89,7 @@ static int opIN_EAX_DX(uint32_t fetchdat) check_io_perm(DX + 3); EAX = inl(DX); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0); return 0; } @@ -92,6 +98,7 @@ static int opOUT_AL_DX(uint32_t fetchdat) check_io_perm(DX); outb(DX, AL); CLOCK_CYCLES(11); + PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); return x86_was_reset; } static int opOUT_AX_DX(uint32_t fetchdat) @@ -101,6 +108,7 @@ static int opOUT_AX_DX(uint32_t fetchdat) check_io_perm(DX + 1); outw(DX, AX); CLOCK_CYCLES(11); + PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); return 0; } static int opOUT_EAX_DX(uint32_t fetchdat) @@ -110,6 +118,6 @@ static int opOUT_EAX_DX(uint32_t fetchdat) check_io_perm(DX + 2); check_io_perm(DX + 3); outl(DX, EAX); - CLOCK_CYCLES(11); + PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0); return 0; } diff --git a/src/x86_ops_jump.h b/src/x86_ops_jump.h index 8514c4bdb..93987633e 100644 --- a/src/x86_ops_jump.h +++ b/src/x86_ops_jump.h @@ -25,8 +25,11 @@ cpu_state.pc += offset; \ CLOCK_CYCLES_ALWAYS(timing_bt); \ CPU_BLOCK_END(); \ + PREFETCH_RUN(timing_bt+timing_bnt, 2, -1, 0,0,0,0, 0); \ + PREFETCH_FLUSH(); \ return 1; \ } \ + PREFETCH_RUN(timing_bnt, 2, -1, 0,0,0,0, 0); \ return 0; \ } \ \ @@ -39,8 +42,11 @@ cpu_state.pc += offset; \ CLOCK_CYCLES_ALWAYS(timing_bt); \ CPU_BLOCK_END(); \ + PREFETCH_RUN(timing_bt+timing_bnt, 3, -1, 0,0,0,0, 0); \ + PREFETCH_FLUSH(); \ return 1; \ } \ + PREFETCH_RUN(timing_bnt, 3, -1, 0,0,0,0, 0); \ return 0; \ } \ \ @@ -53,8 +59,11 @@ cpu_state.pc += offset; \ CLOCK_CYCLES_ALWAYS(timing_bt); \ CPU_BLOCK_END(); \ + PREFETCH_RUN(timing_bt+timing_bnt, 5, -1, 0,0,0,0, 0); \ + PREFETCH_FLUSH(); \ return 1; \ } \ + PREFETCH_RUN(timing_bnt, 5, -1, 0,0,0,0, 0); \ return 0; \ } \ @@ -82,10 +91,12 @@ static int opLOOPNE_w(uint32_t fetchdat) int8_t offset = (int8_t)getbytef(); CX--; CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); if (CX && !ZF_SET()) { cpu_state.pc += offset; CPU_BLOCK_END(); + PREFETCH_FLUSH(); return 1; } return 0; @@ -95,10 +106,12 @@ static int opLOOPNE_l(uint32_t fetchdat) int8_t offset = (int8_t)getbytef(); ECX--; CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); if (ECX && !ZF_SET()) { cpu_state.pc += offset; CPU_BLOCK_END(); + PREFETCH_FLUSH(); return 1; } return 0; @@ -109,10 +122,12 @@ static int opLOOPE_w(uint32_t fetchdat) int8_t offset = (int8_t)getbytef(); CX--; CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); if (CX && ZF_SET()) { cpu_state.pc += offset; CPU_BLOCK_END(); + PREFETCH_FLUSH(); return 1; } return 0; @@ -122,10 +137,12 @@ static int opLOOPE_l(uint32_t fetchdat) int8_t offset = (int8_t)getbytef(); ECX--; CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); if (ECX && ZF_SET()) { cpu_state.pc += offset; CPU_BLOCK_END(); + PREFETCH_FLUSH(); return 1; } return 0; @@ -136,10 +153,12 @@ static int opLOOP_w(uint32_t fetchdat) int8_t offset = (int8_t)getbytef(); CX--; CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); if (CX) { cpu_state.pc += offset; CPU_BLOCK_END(); + PREFETCH_FLUSH(); return 1; } return 0; @@ -149,10 +168,12 @@ static int opLOOP_l(uint32_t fetchdat) int8_t offset = (int8_t)getbytef(); ECX--; CLOCK_CYCLES((is486) ? 7 : 11); + PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0); if (ECX) { cpu_state.pc += offset; CPU_BLOCK_END(); + PREFETCH_FLUSH(); return 1; } return 0; @@ -167,8 +188,11 @@ static int opJCXZ(uint32_t fetchdat) cpu_state.pc += offset; CLOCK_CYCLES(4); CPU_BLOCK_END(); + PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 1; } + PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0); return 0; } static int opJECXZ(uint32_t fetchdat) @@ -180,8 +204,11 @@ static int opJECXZ(uint32_t fetchdat) cpu_state.pc += offset; CLOCK_CYCLES(4); CPU_BLOCK_END(); + PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 1; } + PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0); return 0; } @@ -192,6 +219,8 @@ static int opJMP_r8(uint32_t fetchdat) cpu_state.pc += offset; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 2, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opJMP_r16(uint32_t fetchdat) @@ -200,6 +229,8 @@ static int opJMP_r16(uint32_t fetchdat) cpu_state.pc += offset; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 3, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opJMP_r32(uint32_t fetchdat) @@ -208,6 +239,8 @@ static int opJMP_r32(uint32_t fetchdat) cpu_state.pc += offset; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 5, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } @@ -219,6 +252,8 @@ static int opJMP_far_a16(uint32_t fetchdat) cpu_state.pc = addr; loadcsjmp(seg, oxpc); CPU_BLOCK_END(); + PREFETCH_RUN(11, 5, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opJMP_far_a32(uint32_t fetchdat) @@ -229,6 +264,8 @@ static int opJMP_far_a32(uint32_t fetchdat) cpu_state.pc = addr; loadcsjmp(seg, oxpc); CPU_BLOCK_END(); + PREFETCH_RUN(11, 7, -1, 0,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } @@ -239,6 +276,8 @@ static int opCALL_r16(uint32_t fetchdat) cpu_state.pc += addr; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 3, -1, 0,0,1,0, 0); + PREFETCH_FLUSH(); return 0; } static int opCALL_r32(uint32_t fetchdat) @@ -248,6 +287,8 @@ static int opCALL_r32(uint32_t fetchdat) cpu_state.pc += addr; CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 3 : 7); + PREFETCH_RUN(7, 5, -1, 0,0,0,1, 0); + PREFETCH_FLUSH(); return 0; } @@ -260,6 +301,8 @@ static int opRET_w(uint32_t fetchdat) CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 1, -1, 1,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opRET_l(uint32_t fetchdat) @@ -271,6 +314,8 @@ static int opRET_l(uint32_t fetchdat) CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 1, -1, 0,1,0,0, 0); + PREFETCH_FLUSH(); return 0; } @@ -286,6 +331,8 @@ static int opRET_w_imm(uint32_t fetchdat) CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 5, -1, 1,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opRET_l_imm(uint32_t fetchdat) @@ -300,6 +347,8 @@ static int opRET_l_imm(uint32_t fetchdat) CPU_BLOCK_END(); CLOCK_CYCLES((is486) ? 5 : 10); + PREFETCH_RUN(10, 5, -1, 0,1,0,0, 0); + PREFETCH_FLUSH(); return 0; } diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index 6fbab66bf..ddf727f32 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -2,30 +2,35 @@ static int opCBW(uint32_t fetchdat) { AH = (AL & 0x80) ? 0xff : 0; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opCWDE(uint32_t fetchdat) { EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opCWD(uint32_t fetchdat) { DX = (AX & 0x8000) ? 0xFFFF : 0; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opCDQ(uint32_t fetchdat) { EDX = (EAX & 0x80000000) ? 0xffffffff : 0; CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } static int opNOP(uint32_t fetchdat) { CLOCK_CYCLES((is486) ? 1 : 3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } @@ -33,6 +38,7 @@ static int opSETALC(uint32_t fetchdat) { AL = (CF_SET()) ? 0xff : 0; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); return 0; } @@ -54,15 +60,18 @@ static int opF6_a16(uint32_t fetchdat) setznp8(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x10: /*NOT b*/ seteab(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x18: /*NEG b*/ seteab(0 - dst); if (cpu_state.abrt) return 1; setsub8(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x20: /*MUL AL,b*/ AX = AL * dst; @@ -70,6 +79,7 @@ static int opF6_a16(uint32_t fetchdat) if (AH) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(13); + PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x28: /*IMUL AL,b*/ tempws = (int)((int8_t)AL) * (int)((int8_t)dst); @@ -78,6 +88,7 @@ static int opF6_a16(uint32_t fetchdat) if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x30: /*DIV AL,b*/ src16 = AX; @@ -98,6 +109,7 @@ static int opF6_a16(uint32_t fetchdat) return 1; } CLOCK_CYCLES(is486 ? 16 : 14); + PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x38: /*IDIV AL,b*/ tempws = (int)(int16_t)AX; @@ -120,6 +132,7 @@ static int opF6_a16(uint32_t fetchdat) return 1; } CLOCK_CYCLES(19); + PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; default: @@ -144,15 +157,18 @@ static int opF6_a32(uint32_t fetchdat) setznp8(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x10: /*NOT b*/ seteab(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x18: /*NEG b*/ seteab(0 - dst); if (cpu_state.abrt) return 1; setsub8(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x20: /*MUL AL,b*/ AX = AL * dst; @@ -160,6 +176,7 @@ static int opF6_a32(uint32_t fetchdat) if (AH) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(13); + PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x28: /*IMUL AL,b*/ tempws = (int)((int8_t)AL) * (int)((int8_t)dst); @@ -168,6 +185,7 @@ static int opF6_a32(uint32_t fetchdat) if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x30: /*DIV AL,b*/ src16 = AX; @@ -188,6 +206,7 @@ static int opF6_a32(uint32_t fetchdat) return 1; } CLOCK_CYCLES(is486 ? 16 : 14); + PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x38: /*IDIV AL,b*/ tempws = (int)(int16_t)AX; @@ -210,6 +229,7 @@ static int opF6_a32(uint32_t fetchdat) return 1; } CLOCK_CYCLES(19); + PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; default: @@ -237,15 +257,18 @@ static int opF7_w_a16(uint32_t fetchdat) setznp16(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x10: /*NOT w*/ seteaw(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x18: /*NEG w*/ seteaw(0 - dst); if (cpu_state.abrt) return 1; setsub16(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x20: /*MUL AX,w*/ templ = AX * dst; @@ -255,6 +278,7 @@ static int opF7_w_a16(uint32_t fetchdat) if (DX) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x28: /*IMUL AX,w*/ templ = (int)((int16_t)AX) * (int)((int16_t)dst); @@ -264,6 +288,7 @@ static int opF7_w_a16(uint32_t fetchdat) if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(22); + PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x30: /*DIV AX,w*/ templ = (DX << 16) | AX; @@ -281,6 +306,7 @@ static int opF7_w_a16(uint32_t fetchdat) return 1; } CLOCK_CYCLES(is486 ? 24 : 22); + PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x38: /*IDIV AX,w*/ tempws = (int)((DX << 16)|AX); @@ -299,6 +325,7 @@ static int opF7_w_a16(uint32_t fetchdat) return 1; } CLOCK_CYCLES(27); + PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; default: @@ -323,15 +350,18 @@ static int opF7_w_a32(uint32_t fetchdat) setznp16(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x10: /*NOT w*/ seteaw(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x18: /*NEG w*/ seteaw(0 - dst); if (cpu_state.abrt) return 1; setsub16(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x20: /*MUL AX,w*/ templ = AX * dst; @@ -341,6 +371,7 @@ static int opF7_w_a32(uint32_t fetchdat) if (DX) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x28: /*IMUL AX,w*/ templ = (int)((int16_t)AX) * (int)((int16_t)dst); @@ -350,6 +381,7 @@ static int opF7_w_a32(uint32_t fetchdat) if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(22); + PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x30: /*DIV AX,w*/ templ = (DX << 16) | AX; @@ -367,6 +399,7 @@ static int opF7_w_a32(uint32_t fetchdat) return 1; } CLOCK_CYCLES(is486 ? 24 : 22); + PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x38: /*IDIV AX,w*/ tempws = (int)((DX << 16)|AX); @@ -385,6 +418,7 @@ static int opF7_w_a32(uint32_t fetchdat) return 1; } CLOCK_CYCLES(27); + PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; default: @@ -409,15 +443,18 @@ static int opF7_l_a16(uint32_t fetchdat) setznp32(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; case 0x10: /*NOT l*/ seteal(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x18: /*NEG l*/ seteal(0 - dst); if (cpu_state.abrt) return 1; setsub32(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x20: /*MUL EAX,l*/ temp64 = (uint64_t)EAX * (uint64_t)dst; @@ -427,6 +464,7 @@ static int opF7_l_a16(uint32_t fetchdat) if (EDX) flags |= (C_FLAG|V_FLAG); else flags &= ~(C_FLAG|V_FLAG); CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; case 0x28: /*IMUL EAX,l*/ temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst; @@ -436,18 +474,21 @@ static int opF7_l_a16(uint32_t fetchdat) if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(38); + PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; case 0x30: /*DIV EAX,l*/ if (divl(dst)) return 1; if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES((is486) ? 40 : 38); + PREFETCH_RUN(is486 ? 40:38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; case 0x38: /*IDIV EAX,l*/ if (idivl((int32_t)dst)) return 1; if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES(43); + PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); break; default: @@ -471,15 +512,18 @@ static int opF7_l_a32(uint32_t fetchdat) setznp32(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; case 0x10: /*NOT l*/ seteal(~dst); if (cpu_state.abrt) return 1; CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x18: /*NEG l*/ seteal(0 - dst); if (cpu_state.abrt) return 1; setsub32(0, dst); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); + PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x20: /*MUL EAX,l*/ temp64 = (uint64_t)EAX * (uint64_t)dst; @@ -489,6 +533,7 @@ static int opF7_l_a32(uint32_t fetchdat) if (EDX) flags |= (C_FLAG|V_FLAG); else flags &= ~(C_FLAG|V_FLAG); CLOCK_CYCLES(21); + PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; case 0x28: /*IMUL EAX,l*/ temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst; @@ -498,18 +543,21 @@ static int opF7_l_a32(uint32_t fetchdat) if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(38); + PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; case 0x30: /*DIV EAX,l*/ if (divl(dst)) return 1; if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES((is486) ? 40 : 38); + PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; case 0x38: /*IDIV EAX,l*/ if (idivl((int32_t)dst)) return 1; if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES(43); + PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); break; default: @@ -536,7 +584,8 @@ static int opHLT(uint32_t fetchdat) CLOCK_CYCLES(5); CPU_BLOCK_END(); - + PREFETCH_RUN(100, 1, -1, 0,0,0,0, 0); + return 0; } @@ -547,7 +596,10 @@ static int opLOCK(uint32_t fetchdat) if (cpu_state.abrt) return 0; cpu_state.pc++; + ILLEGAL_ON((fetchdat & 0xff) == 0x90); + CLOCK_CYCLES(4); + PREFETCH_PREFIX(); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } @@ -569,6 +621,7 @@ static int opBOUND_w_a16(uint32_t fetchdat) } CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 0); return 0; } static int opBOUND_w_a32(uint32_t fetchdat) @@ -587,6 +640,7 @@ static int opBOUND_w_a32(uint32_t fetchdat) } CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 1); return 0; } @@ -606,6 +660,7 @@ static int opBOUND_l_a16(uint32_t fetchdat) } CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 0); return 0; } static int opBOUND_l_a32(uint32_t fetchdat) @@ -624,6 +679,7 @@ static int opBOUND_l_a32(uint32_t fetchdat) } CLOCK_CYCLES(is486 ? 7 : 10); + PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 1); return 0; } @@ -638,6 +694,7 @@ static int opCLTS(uint32_t fetchdat) } cr0 &= ~8; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0,0,0,0, 0); return 0; } diff --git a/src/x86_ops_mov.h b/src/x86_ops_mov.h index 2884a3944..a9ba431c2 100644 --- a/src/x86_ops_mov.h +++ b/src/x86_ops_mov.h @@ -2,48 +2,56 @@ static int opMOV_AL_imm(uint32_t fetchdat) { AL = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_AH_imm(uint32_t fetchdat) { AH = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_BL_imm(uint32_t fetchdat) { BL = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_BH_imm(uint32_t fetchdat) { BH = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_CL_imm(uint32_t fetchdat) { CL = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_CH_imm(uint32_t fetchdat) { CH = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_DL_imm(uint32_t fetchdat) { DL = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } static int opMOV_DH_imm(uint32_t fetchdat) { DH = getbytef(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); return 0; } @@ -51,48 +59,56 @@ static int opMOV_AX_imm(uint32_t fetchdat) { AX = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_BX_imm(uint32_t fetchdat) { BX = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_CX_imm(uint32_t fetchdat) { CX = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_DX_imm(uint32_t fetchdat) { DX = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_SI_imm(uint32_t fetchdat) { SI = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_DI_imm(uint32_t fetchdat) { DI = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_BP_imm(uint32_t fetchdat) { BP = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } static int opMOV_SP_imm(uint32_t fetchdat) { SP = getwordf(); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); return 0; } @@ -101,6 +117,7 @@ static int opMOV_EAX_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; EAX = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_EBX_imm(uint32_t fetchdat) @@ -108,6 +125,7 @@ static int opMOV_EBX_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; EBX = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_ECX_imm(uint32_t fetchdat) @@ -115,6 +133,7 @@ static int opMOV_ECX_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; ECX = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_EDX_imm(uint32_t fetchdat) @@ -122,6 +141,7 @@ static int opMOV_EDX_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; EDX = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_ESI_imm(uint32_t fetchdat) @@ -129,6 +149,7 @@ static int opMOV_ESI_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; ESI = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_EDI_imm(uint32_t fetchdat) @@ -136,6 +157,7 @@ static int opMOV_EDI_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; EDI = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_EBP_imm(uint32_t fetchdat) @@ -143,6 +165,7 @@ static int opMOV_EBP_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; EBP = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } static int opMOV_ESP_imm(uint32_t fetchdat) @@ -150,6 +173,7 @@ static int opMOV_ESP_imm(uint32_t fetchdat) uint32_t templ = getlong(); if (cpu_state.abrt) return 1; ESP = templ; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); return 0; } @@ -161,6 +185,7 @@ static int opMOV_b_imm_a16(uint32_t fetchdat) CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); seteab(temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0); return cpu_state.abrt; } static int opMOV_b_imm_a32(uint32_t fetchdat) @@ -170,6 +195,7 @@ static int opMOV_b_imm_a32(uint32_t fetchdat) temp = getbyte(); if (cpu_state.abrt) return 1; seteab(temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1); return cpu_state.abrt; } @@ -180,6 +206,7 @@ static int opMOV_w_imm_a16(uint32_t fetchdat) temp = getword(); if (cpu_state.abrt) return 1; seteaw(temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0); return cpu_state.abrt; } static int opMOV_w_imm_a32(uint32_t fetchdat) @@ -189,6 +216,7 @@ static int opMOV_w_imm_a32(uint32_t fetchdat) temp = getword(); if (cpu_state.abrt) return 1; seteaw(temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1); return cpu_state.abrt; } static int opMOV_l_imm_a16(uint32_t fetchdat) @@ -198,6 +226,7 @@ static int opMOV_l_imm_a16(uint32_t fetchdat) temp = getlong(); if (cpu_state.abrt) return 1; seteal(temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 0); return cpu_state.abrt; } static int opMOV_l_imm_a32(uint32_t fetchdat) @@ -207,6 +236,7 @@ static int opMOV_l_imm_a32(uint32_t fetchdat) temp = getlong(); if (cpu_state.abrt) return 1; seteal(temp); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 1); return cpu_state.abrt; } @@ -217,6 +247,7 @@ static int opMOV_AL_a16(uint32_t fetchdat) uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AL = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0); return 0; } static int opMOV_AL_a32(uint32_t fetchdat) @@ -225,6 +256,7 @@ static int opMOV_AL_a32(uint32_t fetchdat) uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AL = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1); return 0; } static int opMOV_AX_a16(uint32_t fetchdat) @@ -233,6 +265,7 @@ static int opMOV_AX_a16(uint32_t fetchdat) uint16_t temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AX = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0); return 0; } static int opMOV_AX_a32(uint32_t fetchdat) @@ -241,6 +274,7 @@ static int opMOV_AX_a32(uint32_t fetchdat) uint16_t temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; AX = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1); return 0; } static int opMOV_EAX_a16(uint32_t fetchdat) @@ -249,6 +283,7 @@ static int opMOV_EAX_a16(uint32_t fetchdat) uint32_t temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; EAX = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 3, -1, 0,1,0,0, 0); return 0; } static int opMOV_EAX_a32(uint32_t fetchdat) @@ -257,6 +292,7 @@ static int opMOV_EAX_a32(uint32_t fetchdat) uint32_t temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; EAX = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 5, -1, 0,1,0,0, 1); return 0; } @@ -265,6 +301,7 @@ static int opMOV_a16_AL(uint32_t fetchdat) uint16_t addr = getwordf(); writememb(cpu_state.ea_seg->base, addr, AL); CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); return cpu_state.abrt; } static int opMOV_a32_AL(uint32_t fetchdat) @@ -272,6 +309,7 @@ static int opMOV_a32_AL(uint32_t fetchdat) uint32_t addr = getlong(); writememb(cpu_state.ea_seg->base, addr, AL); CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); return cpu_state.abrt; } static int opMOV_a16_AX(uint32_t fetchdat) @@ -279,6 +317,7 @@ static int opMOV_a16_AX(uint32_t fetchdat) uint16_t addr = getwordf(); writememw(cpu_state.ea_seg->base, addr, AX); CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); return cpu_state.abrt; } static int opMOV_a32_AX(uint32_t fetchdat) @@ -286,6 +325,7 @@ static int opMOV_a32_AX(uint32_t fetchdat) uint32_t addr = getlong(); if (cpu_state.abrt) return 1; writememw(cpu_state.ea_seg->base, addr, AX); CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); return cpu_state.abrt; } static int opMOV_a16_EAX(uint32_t fetchdat) @@ -293,6 +333,7 @@ static int opMOV_a16_EAX(uint32_t fetchdat) uint16_t addr = getwordf(); writememl(cpu_state.ea_seg->base, addr, EAX); CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0); return cpu_state.abrt; } static int opMOV_a32_EAX(uint32_t fetchdat) @@ -300,6 +341,7 @@ static int opMOV_a32_EAX(uint32_t fetchdat) uint32_t addr = getlong(); if (cpu_state.abrt) return 1; writememl(cpu_state.ea_seg->base, addr, EAX); CLOCK_CYCLES((is486) ? 1 : 2); + PREFETCH_RUN(2, 5, -1, 0,0,0,1, 1); return cpu_state.abrt; } @@ -307,34 +349,38 @@ static int opMOV_a32_EAX(uint32_t fetchdat) static int opLEA_w_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + // ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].w = (cpu_mod == 3) ? (cpu_state.last_ea & 0xffff) : cpu_state.eaaddr; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); return 0; } static int opLEA_w_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + // ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].w = (cpu_mod == 3) ? (cpu_state.last_ea & 0xffff) : cpu_state.eaaddr; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); return 0; } static int opLEA_l_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].l = cpu_state.eaaddr & 0xffff; + // ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].l = ((cpu_mod == 3) ? cpu_state.last_ea : cpu_state.eaaddr) & 0xffff; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); return 0; } static int opLEA_l_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].l = cpu_state.eaaddr; + // ILLEGAL_ON(cpu_mod == 3); + cpu_state.regs[cpu_reg].l = (cpu_mod == 3) ? cpu_state.last_ea : cpu_state.eaaddr; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); return 0; } @@ -343,17 +389,25 @@ static int opLEA_l_a32(uint32_t fetchdat) static int opXLAT_a16(uint32_t fetchdat) { uint32_t addr = (BX + AL)&0xFFFF; - uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; + uint8_t temp; + cpu_state.last_ea = addr; + temp = readmemb(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) return 1; AL = temp; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); return 0; } static int opXLAT_a32(uint32_t fetchdat) { uint32_t addr = EBX + AL; - uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; + uint8_t temp; + cpu_state.last_ea = addr; + temp = readmemb(cpu_state.ea_seg->base, addr); + if (cpu_state.abrt) return 1; AL = temp; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); return 0; } @@ -364,12 +418,14 @@ static int opMOV_b_r_a16(uint32_t fetchdat) { setr8(cpu_rm, getr8(cpu_reg)); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); } else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); seteab(getr8(cpu_reg)); CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0); } return cpu_state.abrt; } @@ -380,12 +436,14 @@ static int opMOV_b_r_a32(uint32_t fetchdat) { setr8(cpu_rm, getr8(cpu_reg)); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); } else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); seteab(getr8(cpu_reg)); CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1); } return cpu_state.abrt; } @@ -396,12 +454,14 @@ static int opMOV_w_r_a16(uint32_t fetchdat) { cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); } else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); seteaw(cpu_state.regs[cpu_reg].w); CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0); } return cpu_state.abrt; } @@ -412,12 +472,14 @@ static int opMOV_w_r_a32(uint32_t fetchdat) { cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); } else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); seteaw(cpu_state.regs[cpu_reg].w); CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1); } return cpu_state.abrt; } @@ -428,12 +490,14 @@ static int opMOV_l_r_a16(uint32_t fetchdat) { cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); } else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); seteal(cpu_state.regs[cpu_reg].l); CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 0); } return cpu_state.abrt; } @@ -444,12 +508,14 @@ static int opMOV_l_r_a32(uint32_t fetchdat) { cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); } else { CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); seteal(cpu_state.regs[cpu_reg].l); CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 1); } return cpu_state.abrt; } @@ -461,6 +527,7 @@ static int opMOV_r_b_a16(uint32_t fetchdat) { setr8(cpu_reg, getr8(cpu_rm)); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); } else { @@ -469,6 +536,7 @@ static int opMOV_r_b_a16(uint32_t fetchdat) temp = geteab(); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0); } return 0; } @@ -479,6 +547,7 @@ static int opMOV_r_b_a32(uint32_t fetchdat) { setr8(cpu_reg, getr8(cpu_rm)); CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); } else { @@ -487,6 +556,7 @@ static int opMOV_r_b_a32(uint32_t fetchdat) temp = geteab(); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1); } return 0; } @@ -497,6 +567,7 @@ static int opMOV_r_w_a16(uint32_t fetchdat) { cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); } else { @@ -505,6 +576,7 @@ static int opMOV_r_w_a16(uint32_t fetchdat) temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0); } return 0; } @@ -515,6 +587,7 @@ static int opMOV_r_w_a32(uint32_t fetchdat) { cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); } else { @@ -523,6 +596,7 @@ static int opMOV_r_w_a32(uint32_t fetchdat) temp = geteaw(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; CLOCK_CYCLES((is486) ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1); } return 0; } @@ -533,6 +607,7 @@ static int opMOV_r_l_a16(uint32_t fetchdat) { cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); } else { @@ -541,6 +616,7 @@ static int opMOV_r_l_a16(uint32_t fetchdat) temp = geteal(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 0); } return 0; } @@ -551,6 +627,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) { cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); } else { @@ -559,6 +636,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) temp = geteal(); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 1); } return 0; } diff --git a/src/x86_ops_mov_ctrl.h b/src/x86_ops_mov_ctrl.h index b355476fe..6fa157da4 100644 --- a/src/x86_ops_mov_ctrl.h +++ b/src/x86_ops_mov_ctrl.h @@ -33,6 +33,7 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) break; } CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_r_CRx_a32(uint32_t fetchdat) @@ -70,6 +71,7 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat) break; } CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } @@ -84,6 +86,7 @@ static int opMOV_r_DRx_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); cpu_state.regs[cpu_rm].l = dr[cpu_reg]; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_r_DRx_a32(uint32_t fetchdat) @@ -97,11 +100,14 @@ static int opMOV_r_DRx_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); cpu_state.regs[cpu_rm].l = dr[cpu_reg]; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } static int opMOV_CRx_r_a16(uint32_t fetchdat) { + uint32_t old_cr0 = cr0; + if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load CRx\n"); @@ -119,6 +125,12 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) cr0 |= 0x10; if (!(cr0 & 0x80000000)) mmu_perm=4; + if (is486 && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (is486 && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); break; case 2: cr2 = cpu_state.regs[cpu_rm].l; @@ -141,10 +153,13 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) break; } CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_CRx_r_a32(uint32_t fetchdat) { + uint32_t old_cr0 = cr0; + if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { pclog("Can't load CRx\n"); @@ -162,6 +177,12 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) cr0 |= 0x10; if (!(cr0 & 0x80000000)) mmu_perm=4; + if (is486 && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (is486 && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); break; case 2: cr2 = cpu_state.regs[cpu_rm].l; @@ -184,6 +205,7 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) break; } CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 1); return 0; } @@ -198,6 +220,7 @@ static int opMOV_DRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); dr[cpu_reg] = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_DRx_r_a32(uint32_t fetchdat) @@ -211,6 +234,7 @@ static int opMOV_DRx_r_a32(uint32_t fetchdat) fetch_ea_16(fetchdat); dr[cpu_reg] = cpu_state.regs[cpu_rm].l; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } @@ -225,6 +249,7 @@ static int opMOV_r_TRx_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); cpu_state.regs[cpu_rm].l = 0; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_r_TRx_a32(uint32_t fetchdat) @@ -238,6 +263,7 @@ static int opMOV_r_TRx_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); cpu_state.regs[cpu_rm].l = 0; CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } @@ -251,6 +277,7 @@ static int opMOV_TRx_r_a16(uint32_t fetchdat) } fetch_ea_16(fetchdat); CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_TRx_r_a32(uint32_t fetchdat) @@ -263,6 +290,7 @@ static int opMOV_TRx_r_a32(uint32_t fetchdat) } fetch_ea_16(fetchdat); CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } diff --git a/src/x86_ops_mov_seg.h b/src/x86_ops_mov_seg.h index 700a69da7..1e2f654b1 100644 --- a/src/x86_ops_mov_seg.h +++ b/src/x86_ops_mov_seg.h @@ -25,6 +25,7 @@ static int opMOV_w_seg_a16(uint32_t fetchdat) } CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return cpu_state.abrt; } static int opMOV_w_seg_a32(uint32_t fetchdat) @@ -54,6 +55,7 @@ static int opMOV_w_seg_a32(uint32_t fetchdat) } CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return cpu_state.abrt; } @@ -90,6 +92,7 @@ static int opMOV_l_seg_a16(uint32_t fetchdat) } CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return cpu_state.abrt; } static int opMOV_l_seg_a32(uint32_t fetchdat) @@ -125,6 +128,7 @@ static int opMOV_l_seg_a32(uint32_t fetchdat) } CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return cpu_state.abrt; } @@ -165,6 +169,7 @@ static int opMOV_seg_w_a16(uint32_t fetchdat) } CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); return cpu_state.abrt; } static int opMOV_seg_w_a32(uint32_t fetchdat) @@ -204,6 +209,7 @@ static int opMOV_seg_w_a32(uint32_t fetchdat) } CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); return cpu_state.abrt; } @@ -220,6 +226,7 @@ static int opLDS_w_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); return 0; } static int opLDS_w_a32(uint32_t fetchdat) @@ -234,6 +241,7 @@ static int opLDS_w_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); return 0; } static int opLDS_l_a16(uint32_t fetchdat) @@ -249,6 +257,7 @@ static int opLDS_l_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); return 0; } static int opLDS_l_a32(uint32_t fetchdat) @@ -264,6 +273,7 @@ static int opLDS_l_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); return 0; } @@ -279,6 +289,7 @@ static int opLSS_w_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); return 1; } static int opLSS_w_a32(uint32_t fetchdat) @@ -293,6 +304,7 @@ static int opLSS_w_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); return 1; } static int opLSS_l_a16(uint32_t fetchdat) @@ -308,6 +320,7 @@ static int opLSS_l_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); return 1; } static int opLSS_l_a32(uint32_t fetchdat) @@ -323,6 +336,7 @@ static int opLSS_l_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); return 1; } @@ -339,6 +353,7 @@ static int opLSS_l_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = addr; \ \ CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); \ return 0; \ } \ \ @@ -354,6 +369,7 @@ static int opLSS_l_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = addr; \ \ CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); \ return 0; \ } \ \ @@ -370,6 +386,7 @@ static int opLSS_l_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = addr; \ \ CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); \ return 0; \ } \ \ @@ -386,6 +403,7 @@ static int opLSS_l_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = addr; \ \ CLOCK_CYCLES(7); \ + PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); \ return 0; \ } diff --git a/src/x86_ops_movx.h b/src/x86_ops_movx.h index 9badebc91..2175a63c3 100644 --- a/src/x86_ops_movx.h +++ b/src/x86_ops_movx.h @@ -7,6 +7,7 @@ static int opMOVZX_w_b_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = (uint16_t)temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVZX_w_b_a32(uint32_t fetchdat) @@ -18,6 +19,7 @@ static int opMOVZX_w_b_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = (uint16_t)temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opMOVZX_l_b_a16(uint32_t fetchdat) @@ -29,6 +31,7 @@ static int opMOVZX_l_b_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = (uint32_t)temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVZX_l_b_a32(uint32_t fetchdat) @@ -40,6 +43,7 @@ static int opMOVZX_l_b_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = (uint32_t)temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opMOVZX_w_w_a16(uint32_t fetchdat) @@ -51,6 +55,7 @@ static int opMOVZX_w_w_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVZX_w_w_a32(uint32_t fetchdat) @@ -62,6 +67,7 @@ static int opMOVZX_w_w_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opMOVZX_l_w_a16(uint32_t fetchdat) @@ -73,6 +79,7 @@ static int opMOVZX_l_w_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = (uint32_t)temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVZX_l_w_a32(uint32_t fetchdat) @@ -84,6 +91,7 @@ static int opMOVZX_l_w_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = (uint32_t)temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } @@ -98,6 +106,7 @@ static int opMOVSX_w_b_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w |= 0xff00; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVSX_w_b_a32(uint32_t fetchdat) @@ -111,6 +120,7 @@ static int opMOVSX_w_b_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w |= 0xff00; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opMOVSX_l_b_a16(uint32_t fetchdat) @@ -124,6 +134,7 @@ static int opMOVSX_l_b_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l |= 0xffffff00; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVSX_l_b_a32(uint32_t fetchdat) @@ -137,6 +148,7 @@ static int opMOVSX_l_b_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l |= 0xffffff00; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } static int opMOVSX_l_w_a16(uint32_t fetchdat) @@ -150,6 +162,7 @@ static int opMOVSX_l_w_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l |= 0xffff0000; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); return 0; } static int opMOVSX_l_w_a32(uint32_t fetchdat) @@ -163,5 +176,6 @@ static int opMOVSX_l_w_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l |= 0xffff0000; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); return 0; } diff --git a/src/x86_ops_mul.h b/src/x86_ops_mul.h index 37003bbd4..98cf254cc 100644 --- a/src/x86_ops_mul.h +++ b/src/x86_ops_mul.h @@ -15,6 +15,7 @@ static int opIMUL_w_iw_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 0); return 0; } static int opIMUL_w_iw_a32(uint32_t fetchdat) @@ -34,6 +35,7 @@ static int opIMUL_w_iw_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 1); return 0; } @@ -54,6 +56,7 @@ static int opIMUL_l_il_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(25); + PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 0); return 0; } static int opIMUL_l_il_a32(uint32_t fetchdat) @@ -73,6 +76,7 @@ static int opIMUL_l_il_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(25); + PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 1); return 0; } @@ -94,6 +98,7 @@ static int opIMUL_w_ib_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 0); return 0; } static int opIMUL_w_ib_a32(uint32_t fetchdat) @@ -114,6 +119,7 @@ static int opIMUL_w_ib_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].w = templ & 0xffff; CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); + PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 1); return 0; } @@ -134,6 +140,7 @@ static int opIMUL_l_ib_a16(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(20); + PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 0); return 0; } static int opIMUL_l_ib_a32(uint32_t fetchdat) @@ -153,6 +160,7 @@ static int opIMUL_l_ib_a32(uint32_t fetchdat) cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; CLOCK_CYCLES(20); + PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 1); return 0; } @@ -171,6 +179,7 @@ static int opIMUL_w_w_a16(uint32_t fetchdat) else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(18); + PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 0); return 0; } static int opIMUL_w_w_a32(uint32_t fetchdat) @@ -186,6 +195,7 @@ static int opIMUL_w_w_a32(uint32_t fetchdat) else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(18); + PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 1); return 0; } @@ -202,6 +212,7 @@ static int opIMUL_l_l_a16(uint32_t fetchdat) else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(30); + PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 0); return 0; } static int opIMUL_l_l_a32(uint32_t fetchdat) @@ -217,6 +228,7 @@ static int opIMUL_l_l_a32(uint32_t fetchdat) else flags &= ~(C_FLAG | V_FLAG); CLOCK_CYCLES(30); + PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 1); return 0; } diff --git a/src/x86_ops_pmode.h b/src/x86_ops_pmode.h index 9b4aa029c..1f30fbfa7 100644 --- a/src/x86_ops_pmode.h +++ b/src/x86_ops_pmode.h @@ -18,6 +18,7 @@ static int opARPL_a16(uint32_t fetchdat) flags &= ~Z_FLAG; CLOCK_CYCLES(is486 ? 9 : 20); + PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 0); return 0; } static int opARPL_a32(uint32_t fetchdat) @@ -40,10 +41,11 @@ static int opARPL_a32(uint32_t fetchdat) flags &= ~Z_FLAG; CLOCK_CYCLES(is486 ? 9 : 20); + PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 1); return 0; } -#define opLAR(name, fetch_ea, is32) \ +#define opLAR(name, fetch_ea, is32, ea32) \ static int opLAR_ ## name(uint32_t fetchdat) \ { \ int valid; \ @@ -84,15 +86,16 @@ static int opARPL_a32(uint32_t fetchdat) cpl_override = 0; \ } \ CLOCK_CYCLES(11); \ + PREFETCH_RUN(11, 2, rmdat, 2,0,0,0, ea32); \ return cpu_state.abrt; \ } -opLAR(w_a16, fetch_ea_16, 0) -opLAR(w_a32, fetch_ea_32, 0) -opLAR(l_a16, fetch_ea_16, 1) -opLAR(l_a32, fetch_ea_32, 1) +opLAR(w_a16, fetch_ea_16, 0, 0) +opLAR(w_a32, fetch_ea_32, 0, 1) +opLAR(l_a16, fetch_ea_16, 1, 0) +opLAR(l_a32, fetch_ea_32, 1, 1) -#define opLSL(name, fetch_ea, is32) \ +#define opLSL(name, fetch_ea, is32, ea32) \ static int opLSL_ ## name(uint32_t fetchdat) \ { \ int valid; \ @@ -139,16 +142,17 @@ opLAR(l_a32, fetch_ea_32, 1) cpl_override = 0; \ } \ CLOCK_CYCLES(10); \ + PREFETCH_RUN(10, 2, rmdat, 4,0,0,0, ea32); \ return cpu_state.abrt; \ } -opLSL(w_a16, fetch_ea_16, 0) -opLSL(w_a32, fetch_ea_32, 0) -opLSL(l_a16, fetch_ea_16, 1) -opLSL(l_a32, fetch_ea_32, 1) +opLSL(w_a16, fetch_ea_16, 0, 0) +opLSL(w_a32, fetch_ea_32, 0, 1) +opLSL(l_a16, fetch_ea_16, 1, 0) +opLSL(l_a32, fetch_ea_32, 1, 1) -static int op0F00_common(uint32_t fetchdat) +static int op0F00_common(uint32_t fetchdat, int ea32) { int dpl, valid, granularity; uint32_t addr, base, limit; @@ -161,10 +165,12 @@ static int op0F00_common(uint32_t fetchdat) case 0x00: /*SLDT*/ seteaw(ldt.seg); CLOCK_CYCLES(4); + PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x08: /*STR*/ seteaw(tr.seg); CLOCK_CYCLES(4); + PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x10: /*LLDT*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) @@ -190,6 +196,7 @@ static int op0F00_common(uint32_t fetchdat) ldt.base = base; ldt.seg = sel; CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32); break; case 0x18: /*LTR*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) @@ -215,6 +222,7 @@ static int op0F00_common(uint32_t fetchdat) } tr.base = base; CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32); break; case 0x20: /*VERR*/ sel = geteaw(); if (cpu_state.abrt) return 1; @@ -234,6 +242,7 @@ static int op0F00_common(uint32_t fetchdat) if ((desc & 0x0800) && !(desc & 0x0200)) valid = 0; /*Non-readable code*/ if (valid) flags |= Z_FLAG; CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); break; case 0x28: /*VERW*/ sel = geteaw(); if (cpu_state.abrt) return 1; @@ -251,6 +260,7 @@ static int op0F00_common(uint32_t fetchdat) if (!(desc & 0x0200)) valid = 0; /*Read-only data*/ if (valid) flags |= Z_FLAG; CLOCK_CYCLES(20); + PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32); break; default: @@ -268,7 +278,7 @@ static int op0F00_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); - return op0F00_common(fetchdat); + return op0F00_common(fetchdat, 0); } static int op0F00_a32(uint32_t fetchdat) { @@ -276,10 +286,10 @@ static int op0F00_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); - return op0F00_common(fetchdat); + return op0F00_common(fetchdat, 1); } -static int op0F01_common(uint32_t fetchdat, int is32, int is286) +static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) { uint32_t base; uint16_t limit, tempw; @@ -293,6 +303,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286) base |= 0xff000000; writememl(easeg, cpu_state.eaaddr + 2, base); CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32); break; case 0x08: /*SIDT*/ seteaw(idt.limit); @@ -301,6 +312,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286) base |= 0xff000000; writememl(easeg, cpu_state.eaaddr + 2, base); CLOCK_CYCLES(7); + PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32); break; case 0x10: /*LGDT*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) @@ -317,6 +329,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286) gdt.base = base; if (!is32) gdt.base &= 0xffffff; CLOCK_CYCLES(11); + PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32); break; case 0x18: /*LIDT*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) @@ -333,12 +346,14 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286) idt.base = base; if (!is32) idt.base &= 0xffffff; CLOCK_CYCLES(11); + PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32); break; case 0x20: /*SMSW*/ if (is486) seteaw(msw); else seteaw(msw | 0xFF00); CLOCK_CYCLES(2); + PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x30: /*LMSW*/ if ((CPL || eflags&VM_FLAG) && (msw&1)) @@ -350,6 +365,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286) tempw = geteaw(); if (cpu_state.abrt) return 1; if (msw & 1) tempw |= 1; msw = tempw; + PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; case 0x38: /*INVLPG*/ @@ -363,6 +379,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286) } mmu_invalidate(ds + cpu_state.eaaddr); CLOCK_CYCLES(12); + PREFETCH_RUN(12, 2, rmdat, 0,0,0,0, ea32); break; } @@ -379,30 +396,30 @@ static int op0F01_w_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - return op0F01_common(fetchdat, 0, 0); + return op0F01_common(fetchdat, 0, 0, 0); } static int op0F01_w_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - return op0F01_common(fetchdat, 0, 0); + return op0F01_common(fetchdat, 0, 0, 1); } static int op0F01_l_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - return op0F01_common(fetchdat, 1, 0); + return op0F01_common(fetchdat, 1, 0, 0); } static int op0F01_l_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - return op0F01_common(fetchdat, 1, 0); + return op0F01_common(fetchdat, 1, 0, 1); } static int op0F01_286(uint32_t fetchdat) { fetch_ea_16(fetchdat); - return op0F01_common(fetchdat, 0, 1); + return op0F01_common(fetchdat, 0, 1, 0); } diff --git a/src/x86_ops_prefix.h b/src/x86_ops_prefix.h index 3777894b7..c5d5b3042 100644 --- a/src/x86_ops_prefix.h +++ b/src/x86_ops_prefix.h @@ -8,6 +8,7 @@ static int op ## name ## _w_a16(uint32_t fetchdat) \ cpu_state.ea_seg = &seg; \ cpu_state.ssegs = 1; \ CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ \ return x86_opcodes[fetchdat & 0xff](fetchdat >> 8); \ } \ @@ -21,6 +22,7 @@ static int op ## name ## _l_a16(uint32_t fetchdat) \ cpu_state.ea_seg = &seg; \ cpu_state.ssegs = 1; \ CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ \ return x86_opcodes[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ } \ @@ -34,6 +36,7 @@ static int op ## name ## _w_a32(uint32_t fetchdat) \ cpu_state.ea_seg = &seg; \ cpu_state.ssegs = 1; \ CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ \ return x86_opcodes[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ } \ @@ -47,6 +50,7 @@ static int op ## name ## _l_a32(uint32_t fetchdat) \ cpu_state.ea_seg = &seg; \ cpu_state.ssegs = 1; \ CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ \ return x86_opcodes[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ } @@ -66,6 +70,7 @@ static int op_66(uint32_t fetchdat) /*Data size select*/ cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); CLOCK_CYCLES(2); + PREFETCH_PREFIX(); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } static int op_67(uint32_t fetchdat) /*Address size select*/ @@ -76,5 +81,6 @@ static int op_67(uint32_t fetchdat) /*Address size select*/ cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); CLOCK_CYCLES(2); + PREFETCH_PREFIX(); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } diff --git a/src/x86_ops_ret.h b/src/x86_ops_ret.h index 7775ce6fd..4f41a2049 100644 --- a/src/x86_ops_ret.h +++ b/src/x86_ops_ret.h @@ -44,34 +44,56 @@ static int opRETF_a16(uint32_t fetchdat) { + int cycles_old = cycles; + CPU_BLOCK_END(); RETF_a16(0); + + PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opRETF_a32(uint32_t fetchdat) { + int cycles_old = cycles; + CPU_BLOCK_END(); RETF_a32(0); + + PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1); + PREFETCH_FLUSH(); return 0; } static int opRETF_a16_imm(uint32_t fetchdat) { + int cycles_old = cycles; uint16_t offset = getwordf(); + CPU_BLOCK_END(); RETF_a16(offset); + + PREFETCH_RUN(cycles_old-cycles, 3, -1, 2,0,0,0, 0); + PREFETCH_FLUSH(); return 0; } static int opRETF_a32_imm(uint32_t fetchdat) { + int cycles_old = cycles; uint16_t offset = getwordf(); + CPU_BLOCK_END(); RETF_a32(offset); + + PREFETCH_RUN(cycles_old-cycles, 3, -1, 0,2,0,0, 1); + PREFETCH_FLUSH(); return 0; } static int opIRET_286(uint32_t fetchdat) { + int cycles_old = cycles; + if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); @@ -107,11 +129,16 @@ static int opIRET_286(uint32_t fetchdat) flags_extract(); nmi_enable = 1; CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); + PREFETCH_FLUSH(); return cpu_state.abrt; } static int opIRET(uint32_t fetchdat) { + int cycles_old = cycles; + if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); @@ -147,11 +174,16 @@ static int opIRET(uint32_t fetchdat) flags_extract(); nmi_enable = 1; CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); + PREFETCH_FLUSH(); return cpu_state.abrt; } static int opIRETD(uint32_t fetchdat) { + int cycles_old = cycles; + if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) { x86gpf(NULL,0); @@ -189,6 +221,9 @@ static int opIRETD(uint32_t fetchdat) flags_extract(); nmi_enable = 1; CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1); + PREFETCH_FLUSH(); return cpu_state.abrt; } diff --git a/src/x86_ops_shift.h b/src/x86_ops_shift.h index 25babcf36..495a1bf47 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -1,4 +1,4 @@ -#define OP_SHIFT_b(c) \ +#define OP_SHIFT_b(c, ea32) \ { \ uint8_t temp_orig = temp; \ if (!c) return 0; \ @@ -17,6 +17,7 @@ if (temp2) flags |= C_FLAG; \ if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR b,CL*/ \ while (c > 0) \ @@ -31,6 +32,7 @@ if (temp2) flags |= C_FLAG; \ if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x10: /*RCL b,CL*/ \ temp2 = flags & C_FLAG; \ @@ -47,6 +49,7 @@ if (temp2) flags |= C_FLAG; \ if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x18: /*RCR b,CL*/ \ temp2 = flags & C_FLAG; \ @@ -63,27 +66,31 @@ if (temp2) flags |= C_FLAG; \ if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x20: case 0x30: /*SHL b,CL*/ \ seteab(temp << c); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SHL8, temp_orig, c, (temp << c) & 0xff); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x28: /*SHR b,CL*/ \ seteab(temp >> c); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x38: /*SAR b,CL*/ \ temp = (int8_t)temp >> c; \ seteab(temp); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SAR8, temp_orig, c, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ } \ } -#define OP_SHIFT_w(c) \ +#define OP_SHIFT_w(c, ea32) \ { \ uint16_t temp_orig = temp; \ if (!c) return 0; \ @@ -102,6 +109,7 @@ if (temp2) flags |= C_FLAG; \ if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x08: /*ROR w, c*/ \ while (c > 0) \ @@ -116,6 +124,7 @@ if (temp2) flags |= C_FLAG; \ if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x10: /*RCL w, c*/ \ temp2 = flags & C_FLAG; \ @@ -132,6 +141,7 @@ if (temp2) flags |= C_FLAG; \ if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x18: /*RCR w, c*/ \ temp2 = flags & C_FLAG; \ @@ -148,27 +158,31 @@ if (temp2) flags |= C_FLAG; \ if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x20: case 0x30: /*SHL w, c*/ \ seteaw(temp << c); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SHL16, temp_orig, c, (temp << c) & 0xffff); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x28: /*SHR w, c*/ \ seteaw(temp >> c); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ case 0x38: /*SAR w, c*/ \ temp = (int16_t)temp >> c; \ seteaw(temp); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SAR16, temp_orig, c, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \ break; \ } \ } -#define OP_SHIFT_l(c) \ +#define OP_SHIFT_l(c, ea32) \ { \ uint32_t temp_orig = temp; \ if (!c) return 0; \ @@ -187,6 +201,7 @@ if (temp2) flags |= C_FLAG; \ if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x08: /*ROR l, c*/ \ while (c > 0) \ @@ -201,6 +216,7 @@ if (temp2) flags |= C_FLAG; \ if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x10: /*RCL l, c*/ \ temp2 = CF_SET(); \ @@ -217,6 +233,7 @@ if (temp2) flags |= C_FLAG; \ if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x18: /*RCR l, c*/ \ temp2 = flags & C_FLAG; \ @@ -233,22 +250,26 @@ if (temp2) flags |= C_FLAG; \ if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG; \ CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \ + PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x20: case 0x30: /*SHL l, c*/ \ seteal(temp << c); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x28: /*SHR l, c*/ \ seteal(temp >> c); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ case 0x38: /*SAR l, c*/ \ temp = (int32_t)temp >> c; \ seteal(temp); if (cpu_state.abrt) return 1; \ set_flags_shift(FLAGS_SAR32, temp_orig, c, temp); \ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \ + PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \ break; \ } \ } @@ -261,8 +282,9 @@ static int opC0_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; + PREFETCH_PREFIX(); temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c); + OP_SHIFT_b(c, 0); return 0; } static int opC0_a32(uint32_t fetchdat) @@ -273,8 +295,9 @@ static int opC0_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; + PREFETCH_PREFIX(); temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c); + OP_SHIFT_b(c, 1); return 0; } static int opC1_w_a16(uint32_t fetchdat) @@ -285,8 +308,9 @@ static int opC1_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; + PREFETCH_PREFIX(); temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c); + OP_SHIFT_w(c, 0); return 0; } static int opC1_w_a32(uint32_t fetchdat) @@ -297,8 +321,9 @@ static int opC1_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; + PREFETCH_PREFIX(); temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c); + OP_SHIFT_w(c, 1); return 0; } static int opC1_l_a16(uint32_t fetchdat) @@ -309,8 +334,9 @@ static int opC1_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; + PREFETCH_PREFIX(); temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c); + OP_SHIFT_l(c, 0); return 0; } static int opC1_l_a32(uint32_t fetchdat) @@ -321,8 +347,9 @@ static int opC1_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++; + PREFETCH_PREFIX(); temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c); + OP_SHIFT_l(c, 1); return 0; } @@ -334,7 +361,7 @@ static int opD0_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c); + OP_SHIFT_b(c, 0); return 0; } static int opD0_a32(uint32_t fetchdat) @@ -345,7 +372,7 @@ static int opD0_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c); + OP_SHIFT_b(c, 1); return 0; } static int opD1_w_a16(uint32_t fetchdat) @@ -356,7 +383,7 @@ static int opD1_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c); + OP_SHIFT_w(c, 0); return 0; } static int opD1_w_a32(uint32_t fetchdat) @@ -367,7 +394,7 @@ static int opD1_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c); + OP_SHIFT_w(c, 1); return 0; } static int opD1_l_a16(uint32_t fetchdat) @@ -378,7 +405,7 @@ static int opD1_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c); + OP_SHIFT_l(c, 0); return 0; } static int opD1_l_a32(uint32_t fetchdat) @@ -389,7 +416,7 @@ static int opD1_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c); + OP_SHIFT_l(c, 1); return 0; } @@ -402,7 +429,7 @@ static int opD2_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); c = CL & 31; temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c); + OP_SHIFT_b(c, 0); return 0; } static int opD2_a32(uint32_t fetchdat) @@ -414,7 +441,7 @@ static int opD2_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); c = CL & 31; temp = geteab(); if (cpu_state.abrt) return 1; - OP_SHIFT_b(c); + OP_SHIFT_b(c, 1); return 0; } static int opD3_w_a16(uint32_t fetchdat) @@ -426,7 +453,7 @@ static int opD3_w_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); c = CL & 31; temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c); + OP_SHIFT_w(c, 0); return 0; } static int opD3_w_a32(uint32_t fetchdat) @@ -438,7 +465,7 @@ static int opD3_w_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); c = CL & 31; temp = geteaw(); if (cpu_state.abrt) return 1; - OP_SHIFT_w(c); + OP_SHIFT_w(c, 1); return 0; } static int opD3_l_a16(uint32_t fetchdat) @@ -450,7 +477,7 @@ static int opD3_l_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); c = CL & 31; temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c); + OP_SHIFT_l(c, 0); return 0; } static int opD3_l_a32(uint32_t fetchdat) @@ -462,7 +489,7 @@ static int opD3_l_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); c = CL & 31; temp = geteal(); if (cpu_state.abrt) return 1; - OP_SHIFT_l(c); + OP_SHIFT_l(c, 1); return 0; } @@ -529,6 +556,7 @@ static int opD3_l_a32(uint32_t fetchdat) operation(); \ \ CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); \ return 0; \ } \ static int op ## operation ## _CL_a16(uint32_t fetchdat) \ @@ -540,6 +568,7 @@ static int opD3_l_a32(uint32_t fetchdat) operation(); \ \ CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); \ return 0; \ } \ static int op ## operation ## _i_a32(uint32_t fetchdat) \ @@ -551,6 +580,7 @@ static int opD3_l_a32(uint32_t fetchdat) operation(); \ \ CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); \ return 0; \ } \ static int op ## operation ## _CL_a32(uint32_t fetchdat) \ @@ -562,6 +592,7 @@ static int opD3_l_a32(uint32_t fetchdat) operation(); \ \ CLOCK_CYCLES(3); \ + PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); \ return 0; \ } diff --git a/src/x86_ops_stack.h b/src/x86_ops_stack.h index 766cc0616..86daf52aa 100644 --- a/src/x86_ops_stack.h +++ b/src/x86_ops_stack.h @@ -3,6 +3,7 @@ { \ PUSH_W(reg); \ CLOCK_CYCLES((is486) ? 1 : 2); \ + PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \ return cpu_state.abrt; \ } @@ -11,6 +12,7 @@ { \ PUSH_L(reg); \ CLOCK_CYCLES((is486) ? 1 : 2); \ + PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \ return cpu_state.abrt; \ } @@ -19,6 +21,7 @@ { \ reg = POP_W(); \ CLOCK_CYCLES((is486) ? 1 : 4); \ + PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0); \ return cpu_state.abrt; \ } @@ -27,6 +30,7 @@ { \ reg = POP_L(); \ CLOCK_CYCLES((is486) ? 1 : 4); \ + PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0); \ return cpu_state.abrt; \ } @@ -94,6 +98,7 @@ static int opPUSHA_w(uint32_t fetchdat) if (!cpu_state.abrt) SP -= 16; } CLOCK_CYCLES((is486) ? 11 : 18); + PREFETCH_RUN(18, 1, -1, 0,0,8,0, 0); return cpu_state.abrt; } static int opPUSHA_l(uint32_t fetchdat) @@ -123,6 +128,7 @@ static int opPUSHA_l(uint32_t fetchdat) if (!cpu_state.abrt) SP -= 32; } CLOCK_CYCLES((is486) ? 11 : 18); + PREFETCH_RUN(18, 1, -1, 0,0,0,8, 0); return cpu_state.abrt; } @@ -151,6 +157,7 @@ static int opPOPA_w(uint32_t fetchdat) SP += 16; } CLOCK_CYCLES((is486) ? 9 : 24); + PREFETCH_RUN(24, 1, -1, 7,0,0,0, 0); return 0; } static int opPOPA_l(uint32_t fetchdat) @@ -178,6 +185,7 @@ static int opPOPA_l(uint32_t fetchdat) SP += 32; } CLOCK_CYCLES((is486) ? 9 : 24); + PREFETCH_RUN(24, 1, -1, 0,7,0,0, 0); return 0; } @@ -186,6 +194,7 @@ static int opPUSH_imm_w(uint32_t fetchdat) uint16_t val = getwordf(); PUSH_W(val); CLOCK_CYCLES(2); + PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); return cpu_state.abrt; } static int opPUSH_imm_l(uint32_t fetchdat) @@ -193,6 +202,7 @@ static int opPUSH_imm_l(uint32_t fetchdat) uint32_t val = getlong(); if (cpu_state.abrt) return 1; PUSH_L(val); CLOCK_CYCLES(2); + PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0); return cpu_state.abrt; } @@ -204,6 +214,7 @@ static int opPUSH_imm_bw(uint32_t fetchdat) PUSH_W(tempw); CLOCK_CYCLES(2); + PREFETCH_RUN(2, 2, -1, 0,0,1,0, 0); return cpu_state.abrt; } static int opPUSH_imm_bl(uint32_t fetchdat) @@ -214,6 +225,7 @@ static int opPUSH_imm_bl(uint32_t fetchdat) PUSH_L(templ); CLOCK_CYCLES(2); + PREFETCH_RUN(2, 2, -1, 0,0,0,1, 0); return cpu_state.abrt; } @@ -233,6 +245,7 @@ static int opPOPW_a16(uint32_t fetchdat) if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 0); return cpu_state.abrt; } static int opPOPW_a32(uint32_t fetchdat) @@ -251,6 +264,7 @@ static int opPOPW_a32(uint32_t fetchdat) if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 1); return cpu_state.abrt; } @@ -270,6 +284,7 @@ static int opPOPL_a16(uint32_t fetchdat) if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 0); return cpu_state.abrt; } static int opPOPL_a32(uint32_t fetchdat) @@ -288,6 +303,7 @@ static int opPOPL_a32(uint32_t fetchdat) if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6); else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 1); return cpu_state.abrt; } @@ -297,6 +313,7 @@ static int opENTER_w(uint32_t fetchdat) uint16_t offset = getwordf(); int count = (fetchdat >> 16) & 0xff; cpu_state.pc++; uint32_t tempEBP = EBP, tempESP = ESP, frame_ptr; + int reads = 0, writes = 1, instr_cycles = 0; PUSH_W(BP); if (cpu_state.abrt) return 1; frame_ptr = ESP; @@ -313,16 +330,20 @@ static int opENTER_w(uint32_t fetchdat) PUSH_W(tempw); if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } CLOCK_CYCLES((is486) ? 3 : 4); + reads++; writes++; instr_cycles += (is486) ? 3 : 4; } PUSH_W(frame_ptr); if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } CLOCK_CYCLES((is486) ? 3 : 5); + writes++; instr_cycles += (is486) ? 3 : 5; } BP = frame_ptr; if (stack32) ESP -= offset; else SP -= offset; CLOCK_CYCLES((is486) ? 14 : 10); + instr_cycles += (is486) ? 14 : 10; + PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0); return 0; } static int opENTER_l(uint32_t fetchdat) @@ -330,6 +351,7 @@ static int opENTER_l(uint32_t fetchdat) uint16_t offset = getwordf(); int count = (fetchdat >> 16) & 0xff; cpu_state.pc++; uint32_t tempEBP = EBP, tempESP = ESP, frame_ptr; + int reads = 0, writes = 1, instr_cycles = 0; PUSH_L(EBP); if (cpu_state.abrt) return 1; frame_ptr = ESP; @@ -346,16 +368,20 @@ static int opENTER_l(uint32_t fetchdat) PUSH_L(templ); if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } CLOCK_CYCLES((is486) ? 3 : 4); + reads++; writes++; instr_cycles += (is486) ? 3 : 4; } PUSH_L(frame_ptr); if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; } CLOCK_CYCLES((is486) ? 3 : 5); + writes++; instr_cycles += (is486) ? 3 : 5; } EBP = frame_ptr; if (stack32) ESP -= offset; else SP -= offset; CLOCK_CYCLES((is486) ? 14 : 10); + instr_cycles += (is486) ? 14 : 10; + PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0); return 0; } @@ -371,6 +397,7 @@ static int opLEAVE_w(uint32_t fetchdat) BP = temp; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0); return 0; } static int opLEAVE_l(uint32_t fetchdat) @@ -384,6 +411,7 @@ static int opLEAVE_l(uint32_t fetchdat) EBP = temp; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0); return 0; } @@ -393,12 +421,14 @@ static int opLEAVE_l(uint32_t fetchdat) { \ PUSH_W(seg); \ CLOCK_CYCLES(2); \ + PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \ return cpu_state.abrt; \ } \ static int opPUSH_ ## seg ## _l(uint32_t fetchdat) \ { \ PUSH_L(seg); \ CLOCK_CYCLES(2); \ + PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \ return cpu_state.abrt; \ } @@ -410,6 +440,7 @@ static int opLEAVE_l(uint32_t fetchdat) temp_seg = POP_W(); if (cpu_state.abrt) return 1; \ loadseg(temp_seg, realseg); if (cpu_state.abrt) ESP = temp_esp; \ CLOCK_CYCLES(is486 ? 3 : 7); \ + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \ return cpu_state.abrt; \ } \ static int opPOP_ ## seg ## _l(uint32_t fetchdat) \ @@ -419,6 +450,7 @@ static int opLEAVE_l(uint32_t fetchdat) temp_seg = POP_L(); if (cpu_state.abrt) return 1; \ loadseg(temp_seg & 0xffff, realseg); if (cpu_state.abrt) ESP = temp_esp; \ CLOCK_CYCLES(is486 ? 3 : 7); \ + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \ return cpu_state.abrt; \ } @@ -443,7 +475,8 @@ static int opPOP_SS_w(uint32_t fetchdat) temp_seg = POP_W(); if (cpu_state.abrt) return 1; loadseg(temp_seg, &_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } CLOCK_CYCLES(is486 ? 3 : 7); - + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); + cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; cpu_state.ssegs = 0; @@ -462,6 +495,7 @@ static int opPOP_SS_l(uint32_t fetchdat) temp_seg = POP_L(); if (cpu_state.abrt) return 1; loadseg(temp_seg & 0xffff, &_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; } CLOCK_CYCLES(is486 ? 3 : 7); + PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); cpu_state.oldpc = cpu_state.pc; cpu_state.op32 = use32; diff --git a/src/x86_ops_string.h b/src/x86_ops_string.h index c00c68c3e..8c8ba6816 100644 --- a/src/x86_ops_string.h +++ b/src/x86_ops_string.h @@ -5,6 +5,7 @@ static int opMOVSB_a16(uint32_t fetchdat) if (flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0); return 0; } static int opMOVSB_a32(uint32_t fetchdat) @@ -14,6 +15,7 @@ static int opMOVSB_a32(uint32_t fetchdat) if (flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1); return 0; } @@ -24,6 +26,7 @@ static int opMOVSW_a16(uint32_t fetchdat) if (flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0); return 0; } static int opMOVSW_a32(uint32_t fetchdat) @@ -33,6 +36,7 @@ static int opMOVSW_a32(uint32_t fetchdat) if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1); return 0; } @@ -43,6 +47,7 @@ static int opMOVSL_a16(uint32_t fetchdat) if (flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0,1,0,1, 0); return 0; } static int opMOVSL_a32(uint32_t fetchdat) @@ -52,6 +57,7 @@ static int opMOVSL_a32(uint32_t fetchdat) if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0,1,0,1, 1); return 0; } @@ -64,6 +70,7 @@ static int opCMPSB_a16(uint32_t fetchdat) if (flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0); return 0; } static int opCMPSB_a32(uint32_t fetchdat) @@ -74,6 +81,7 @@ static int opCMPSB_a32(uint32_t fetchdat) if (flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1); return 0; } @@ -85,6 +93,7 @@ static int opCMPSW_a16(uint32_t fetchdat) if (flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0); return 0; } static int opCMPSW_a32(uint32_t fetchdat) @@ -95,6 +104,7 @@ static int opCMPSW_a32(uint32_t fetchdat) if (flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1); return 0; } @@ -106,6 +116,7 @@ static int opCMPSL_a16(uint32_t fetchdat) if (flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 0); return 0; } static int opCMPSL_a32(uint32_t fetchdat) @@ -116,6 +127,7 @@ static int opCMPSL_a32(uint32_t fetchdat) if (flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } CLOCK_CYCLES((is486) ? 8 : 10); + PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 1); return 0; } @@ -125,6 +137,7 @@ static int opSTOSB_a16(uint32_t fetchdat) if (flags & D_FLAG) DI--; else DI++; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); return 0; } static int opSTOSB_a32(uint32_t fetchdat) @@ -133,6 +146,7 @@ static int opSTOSB_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI--; else EDI++; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1); return 0; } @@ -142,6 +156,7 @@ static int opSTOSW_a16(uint32_t fetchdat) if (flags & D_FLAG) DI -= 2; else DI += 2; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); return 0; } static int opSTOSW_a32(uint32_t fetchdat) @@ -150,6 +165,7 @@ static int opSTOSW_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI -= 2; else EDI += 2; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1); return 0; } @@ -159,6 +175,7 @@ static int opSTOSL_a16(uint32_t fetchdat) if (flags & D_FLAG) DI -= 4; else DI += 4; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); return 0; } static int opSTOSL_a32(uint32_t fetchdat) @@ -167,6 +184,7 @@ static int opSTOSL_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI -= 4; else EDI += 4; CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0,0,0,1, 1); return 0; } @@ -178,6 +196,7 @@ static int opLODSB_a16(uint32_t fetchdat) if (flags & D_FLAG) SI--; else SI++; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); return 0; } static int opLODSB_a32(uint32_t fetchdat) @@ -187,6 +206,7 @@ static int opLODSB_a32(uint32_t fetchdat) if (flags & D_FLAG) ESI--; else ESI++; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); return 0; } @@ -197,6 +217,7 @@ static int opLODSW_a16(uint32_t fetchdat) if (flags & D_FLAG) SI -= 2; else SI += 2; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); return 0; } static int opLODSW_a32(uint32_t fetchdat) @@ -206,6 +227,7 @@ static int opLODSW_a32(uint32_t fetchdat) if (flags & D_FLAG) ESI -= 2; else ESI += 2; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); return 0; } @@ -216,6 +238,7 @@ static int opLODSL_a16(uint32_t fetchdat) if (flags & D_FLAG) SI -= 4; else SI += 4; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); return 0; } static int opLODSL_a32(uint32_t fetchdat) @@ -225,6 +248,7 @@ static int opLODSL_a32(uint32_t fetchdat) if (flags & D_FLAG) ESI -= 4; else ESI += 4; CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0,1,0,0, 1); return 0; } @@ -236,6 +260,7 @@ static int opSCASB_a16(uint32_t fetchdat) if (flags & D_FLAG) DI--; else DI++; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0); return 0; } static int opSCASB_a32(uint32_t fetchdat) @@ -245,6 +270,7 @@ static int opSCASB_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI--; else EDI++; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1); return 0; } @@ -255,6 +281,7 @@ static int opSCASW_a16(uint32_t fetchdat) if (flags & D_FLAG) DI -= 2; else DI += 2; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0); return 0; } static int opSCASW_a32(uint32_t fetchdat) @@ -264,6 +291,7 @@ static int opSCASW_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI -= 2; else EDI += 2; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1); return 0; } @@ -274,6 +302,7 @@ static int opSCASL_a16(uint32_t fetchdat) if (flags & D_FLAG) DI -= 4; else DI += 4; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0,1,0,0, 0); return 0; } static int opSCASL_a32(uint32_t fetchdat) @@ -283,6 +312,7 @@ static int opSCASL_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI -= 4; else EDI += 4; CLOCK_CYCLES(7); + PREFETCH_RUN(7, 1, -1, 0,1,0,0, 1); return 0; } @@ -295,6 +325,7 @@ static int opINSB_a16(uint32_t fetchdat) if (flags & D_FLAG) DI--; else DI++; CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0); return 0; } static int opINSB_a32(uint32_t fetchdat) @@ -306,6 +337,7 @@ static int opINSB_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI--; else EDI++; CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1); return 0; } @@ -319,6 +351,7 @@ static int opINSW_a16(uint32_t fetchdat) if (flags & D_FLAG) DI -= 2; else DI += 2; CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0); return 0; } static int opINSW_a32(uint32_t fetchdat) @@ -331,6 +364,7 @@ static int opINSW_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI -= 2; else EDI += 2; CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1); return 0; } @@ -346,6 +380,7 @@ static int opINSL_a16(uint32_t fetchdat) if (flags & D_FLAG) DI -= 4; else DI += 4; CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 0,1,0,1, 0); return 0; } static int opINSL_a32(uint32_t fetchdat) @@ -360,6 +395,7 @@ static int opINSL_a32(uint32_t fetchdat) if (flags & D_FLAG) EDI -= 4; else EDI += 4; CLOCK_CYCLES(15); + PREFETCH_RUN(15, 1, -1, 0,1,0,1, 1); return 0; } @@ -371,6 +407,7 @@ static int opOUTSB_a16(uint32_t fetchdat) else SI++; outb(DX, temp); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0); return 0; } static int opOUTSB_a32(uint32_t fetchdat) @@ -381,6 +418,7 @@ static int opOUTSB_a32(uint32_t fetchdat) else ESI++; outb(DX, temp); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1); return 0; } @@ -393,6 +431,7 @@ static int opOUTSW_a16(uint32_t fetchdat) else SI += 2; outw(DX, temp); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0); return 0; } static int opOUTSW_a32(uint32_t fetchdat) @@ -404,6 +443,7 @@ static int opOUTSW_a32(uint32_t fetchdat) else ESI += 2; outw(DX, temp); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1); return 0; } @@ -418,6 +458,7 @@ static int opOUTSL_a16(uint32_t fetchdat) else SI += 4; outl(EDX, temp); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 0,1,0,1, 0); return 0; } static int opOUTSL_a32(uint32_t fetchdat) @@ -431,5 +472,6 @@ static int opOUTSL_a32(uint32_t fetchdat) else ESI += 4; outl(EDX, temp); CLOCK_CYCLES(14); + PREFETCH_RUN(14, 1, -1, 0,1,0,1, 1); return 0; } diff --git a/src/x86_ops_xchg.h b/src/x86_ops_xchg.h index 4ab58e897..77191ae43 100644 --- a/src/x86_ops_xchg.h +++ b/src/x86_ops_xchg.h @@ -6,6 +6,7 @@ static int opXCHG_b_a16(uint32_t fetchdat) seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } static int opXCHG_b_a32(uint32_t fetchdat) @@ -16,6 +17,7 @@ static int opXCHG_b_a32(uint32_t fetchdat) seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1; setr8(cpu_reg, temp); CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); return 0; } @@ -27,6 +29,7 @@ static int opXCHG_w_a16(uint32_t fetchdat) seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); return 0; } static int opXCHG_w_a32(uint32_t fetchdat) @@ -37,6 +40,7 @@ static int opXCHG_w_a32(uint32_t fetchdat) seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = temp; CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); return 0; } @@ -48,6 +52,7 @@ static int opXCHG_l_a16(uint32_t fetchdat) seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); return 0; } static int opXCHG_l_a32(uint32_t fetchdat) @@ -58,6 +63,7 @@ static int opXCHG_l_a32(uint32_t fetchdat) seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = temp; CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5); + PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); return 0; } @@ -68,6 +74,7 @@ static int opXCHG_AX_BX(uint32_t fetchdat) AX = BX; BX = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_AX_CX(uint32_t fetchdat) @@ -76,6 +83,7 @@ static int opXCHG_AX_CX(uint32_t fetchdat) AX = CX; CX = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_AX_DX(uint32_t fetchdat) @@ -84,6 +92,7 @@ static int opXCHG_AX_DX(uint32_t fetchdat) AX = DX; DX = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_AX_SI(uint32_t fetchdat) @@ -92,6 +101,7 @@ static int opXCHG_AX_SI(uint32_t fetchdat) AX = SI; SI = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_AX_DI(uint32_t fetchdat) @@ -100,6 +110,7 @@ static int opXCHG_AX_DI(uint32_t fetchdat) AX = DI; DI = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_AX_BP(uint32_t fetchdat) @@ -108,6 +119,7 @@ static int opXCHG_AX_BP(uint32_t fetchdat) AX = BP; BP = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_AX_SP(uint32_t fetchdat) @@ -116,6 +128,7 @@ static int opXCHG_AX_SP(uint32_t fetchdat) AX = SP; SP = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } @@ -125,6 +138,7 @@ static int opXCHG_EAX_EBX(uint32_t fetchdat) EAX = EBX; EBX = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_EAX_ECX(uint32_t fetchdat) @@ -133,6 +147,7 @@ static int opXCHG_EAX_ECX(uint32_t fetchdat) EAX = ECX; ECX = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_EAX_EDX(uint32_t fetchdat) @@ -141,6 +156,7 @@ static int opXCHG_EAX_EDX(uint32_t fetchdat) EAX = EDX; EDX = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_EAX_ESI(uint32_t fetchdat) @@ -149,6 +165,7 @@ static int opXCHG_EAX_ESI(uint32_t fetchdat) EAX = ESI; ESI = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_EAX_EDI(uint32_t fetchdat) @@ -157,6 +174,7 @@ static int opXCHG_EAX_EDI(uint32_t fetchdat) EAX = EDI; EDI = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_EAX_EBP(uint32_t fetchdat) @@ -165,6 +183,7 @@ static int opXCHG_EAX_EBP(uint32_t fetchdat) EAX = EBP; EBP = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } static int opXCHG_EAX_ESP(uint32_t fetchdat) @@ -173,6 +192,7 @@ static int opXCHG_EAX_ESP(uint32_t fetchdat) EAX = ESP; ESP = temp; CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } @@ -182,6 +202,7 @@ static int opXCHG_EAX_ESP(uint32_t fetchdat) { \ reg = (reg >> 24) | ((reg >> 8) & 0xff00) | ((reg << 8) & 0xff0000) | ((reg << 24) & 0xff000000); \ CLOCK_CYCLES(1); \ + PREFETCH_RUN(1, 1, -1, 0,0,0,0, 0); \ return 0; \ } diff --git a/src/x86seg.c b/src/x86seg.c index 74e177b9a..a6db3f8ac 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -1627,6 +1627,7 @@ void pmodeint(int num, int soft) // pclog("Triple fault!\n"); // output=1; softresetx86(); + cpu_set_edx(); } else if (num==0xD) {