From b325a5174a3c0d73dff187c32785312a0ea50c87 Mon Sep 17 00:00:00 2001 From: waltje Date: Mon, 11 Feb 2019 23:52:27 -0500 Subject: [PATCH] Applied relevent upstream patches. Cleaned up and fixed small things. --- src/cpu/808x.c | 1464 ++++++++++++++------------ src/cpu/cpu.h | 5 +- src/cpu/cpu_table.c | 33 +- src/devices/input/keyboard.h | 12 +- src/devices/input/keyboard_xt.c | 199 +++- src/devices/sound/snd_opl.c | 14 +- src/devices/system/dma.c | 6 +- src/devices/system/pit.c | 148 ++- src/devices/video/vid_hercules.c | 54 +- src/devices/video/vid_herculesplus.c | 69 +- src/devices/video/vid_incolor.c | 81 +- src/machines/m_europc.c | 7 +- src/machines/m_xt.c | 54 +- src/machines/m_xt_laserxt.c | 10 +- src/machines/machine.h | 10 +- src/machines/machine_table.c | 22 +- src/pc.c | 9 +- src/ui/lang/VARCem.str | 12 +- src/win/mingw/Makefile.MinGW | 13 +- src/win/msvc/Makefile.VC | 13 +- 20 files changed, 1298 insertions(+), 937 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 8795ad7..0cfd5db 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -8,7 +8,7 @@ * * 808x CPU emulation. * - * Version: @(#)808x.c 1.0.9 2019/02/10 + * Version: @(#)808x.c 1.0.10 2019/02/11 * * Authors: Miran Grca, * Andrew Jenner, @@ -56,78 +56,74 @@ /* Misc */ -int use32, stack32; -int oldcpl; +int use32, stack32; +int oldcpl; /* The previous value of the CS segment register. */ -uint16_t oldcs; +uint16_t oldcs; /* The opcode of the instruction currently being executed. */ -uint8_t opcode; +uint8_t opcode; /* The tables to speed up the setting of the Z, N, and P flags. */ -uint8_t znptable8[256]; -uint16_t znptable16[65536]; +uint8_t znptable8[256]; +uint16_t znptable16[65536]; /* A 16-bit zero, needed because some speed-up arrays contain pointers to it. */ -uint16_t zero = 0; +uint16_t zero = 0; /* MOD and R/M stuff. */ -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; -int rmdat; +uint16_t *mod1add[2][8]; +uint32_t *mod1seg[8]; +int rmdat; /* XT CPU multiplier. */ -int xt_cpu_multi; +int xt_cpu_multi; /* Is the CPU 8088 or 8086. */ -int is8086 = 0; +int is8086 = 0; /* Variables for handling the non-maskable interrupts. */ -int nmi = 0, nmi_auto_clear = 0; -int nmi_enable = 1; +int nmi = 0, nmi_auto_clear = 0; +int nmi_enable = 1; /* Was the CPU ever reset? */ -int x86_was_reset = 0; +int x86_was_reset = 0; /* Variables used elsewhere in the emulator. */ -int tempc; +int tempc; -/* Amount of instructions executed - used to calculate the % shown in the title bar. */ -int ins = 0; +/* Number of instructions executed - used to calculate the % shown in the title bar. */ +int ins = 0; /* Is the TRAP flag on? */ -int trap = 0; +int trap = 0; /* The current effective address's segment. */ -uint32_t easeg; - +uint32_t easeg; /* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */ -static uint8_t pfq[6]; +static uint8_t pfq[6]; /* Variables to aid with the prefetch queue operation. */ -static int fetchcycles = 0; -static int fetchclocks, pfq_pos = 0; +static int fetchcycles = 0, + pfq_pos = 0; /* The IP equivalent of the current prefetch queue position. */ static uint16_t pfq_ip; -/* Where is this even used?! */ -static int nextcyc = 0; - /* Pointer tables needed for segment overrides. */ -static uint32_t *opseg[4]; -static x86seg *_opseg[4]; +static uint32_t *opseg[4]; +static x86seg *_opseg[4]; -static int takeint = 0, noint = 0; -static int in_lock = 0, halt = 0; -static int cpu_alu_op, pfq_size; +static int takeint = 0, noint = 0; +static int in_lock = 0, halt = 0; +static int cpu_alu_op, pfq_size; -static uint16_t cpu_src = 0, cpu_dest = 0; -static uint16_t cpu_data = 0; +static uint16_t cpu_src = 0, cpu_dest = 0; +static uint16_t cpu_data = 0; -static uint32_t *ovr_seg = NULL; +static uint32_t *ovr_seg = NULL; int indump = 0; @@ -198,7 +194,7 @@ irq_pending(void) static void -wait(int c, int bus) +cpu_wait(int c, int bus) { cycles -= c; if (!bus) @@ -209,6 +205,26 @@ wait(int c, int bus) #undef readmemb #undef readmemw + +/* Common read function. */ +static uint8_t +readmemb_common(uint32_t a) +{ + uint8_t ret; + + if (readlookup2 == NULL) + ret = readmembl(a); + else { + if (readlookup2[(a) >> 12] == ((uintptr_t) -1)) + ret = readmembl(a); + else + ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a)); + } + + return ret; +} + + /* Reads a byte from the memory and accounts for memory transfer cycles to subtract from the cycles to use for adding to the prefetch queue. */ static uint8_t @@ -216,16 +232,8 @@ readmemb(uint32_t a) { uint8_t ret; - wait(4, 1); - - if (readlookup2 == NULL) - ret = readmembl(a); - else { - if (readlookup2[(a) >> 12] == -1) - ret = readmembl(a); - else - ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a)); - } + cpu_wait(4, 1); + ret = readmemb_common(a); return ret; } @@ -241,14 +249,7 @@ readmembf(uint32_t a) a = cs + (a & 0xffff); - if (readlookup2 == NULL) - ret = readmembl(a); - else { - if (readlookup2[(a) >> 12] == -1) - ret = readmembl(a); - else - ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a)); - } + ret = readmemb_common(a); return ret; } @@ -256,26 +257,39 @@ readmembf(uint32_t a) /* Reads a word from the memory and accounts for memory transfer cycles to subtract from the cycles to use for adding to the prefetch queue. */ +static uint16_t +readmemw_common(uint32_t s, uint16_t a) +{ + uint16_t ret; + + ret = readmemb_common(s + a); + ret |= readmemb_common(s + ((a + 1) & 0xffff)) << 8; + + return ret; +} + + static uint16_t readmemw(uint32_t s, uint16_t a) { uint16_t ret; - if (!is8086 || (a & 1)) { - ret = readmemb(s + a); - ret |= readmemb(s + ((a + 1) & 0xffff)) << 8; - } else { - wait(4, 1); + if (is8086 && !(a & 1)) + cpu_wait(4, 1); + else + cpu_wait(8, 1); + ret = readmemw_common(s, a); - if (readlookup2 == NULL) - ret = readmemwl(s, a); - else { - if ((readlookup2[((s) + (a)) >> 12] == -1 || (s) == 0xFFFFFFFF)) - ret = readmemwl(s, a); - else - ret = *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); - } - } + return ret; +} + + +static uint16_t +readmemwf(uint16_t a) +{ + uint16_t ret; + + ret = readmemw_common(cs, a & 0xffff); return ret; } @@ -284,14 +298,12 @@ readmemw(uint32_t s, uint16_t a) /* Writes a byte from the memory and accounts for memory transfer cycles to subtract from the cycles to use for adding to the prefetch queue. */ static void -writememb(uint32_t a, uint8_t v) +writememb_common(uint32_t a, uint8_t v) { - wait(4, 1); - if (writelookup2 == NULL) writemembl(a, v); else { - if (writelookup2[(a) >> 12] == -1) + if (writelookup2[(a) >> 12] == ((uintptr_t) -1)) writemembl(a, v); else *(uint8_t *)(writelookup2[a >> 12] + a) = v; @@ -299,56 +311,92 @@ writememb(uint32_t a, uint8_t v) } +static void +writememb(uint32_t a, uint8_t v) +{ + cpu_wait(4, 1); + + writememb_common(a, v); +} + + /* Writes a word from the memory and accounts for memory transfer cycles to subtract from the cycles to use for adding to the prefetch queue. */ static void writememw(uint32_t s, uint32_t a, uint16_t v) { - if (!is8086 || (a & 1)) { - writememb(s + a, v & 0xff); - writememb(s + ((a + 1) & 0xffff), v >> 8); - } else { - wait(4, 1); + if (is8086 && !(a & 1)) + cpu_wait(4, 1); + else + cpu_wait(8, 1); - if (writelookup2 == NULL) - writememwl(s, a, v); - else { - if ((writelookup2[((s) + (a)) >> 12]== -1) || ((s) == 0xFFFFFFFF)) - writememwl(s, a, v); - else - *(uint16_t *) (writelookup2[(s + a) >> 12] + s + a) = v; - } + writememb_common(s + a, v & 0xff); + writememb_common(s + ((a + 1) & 0xffff), v >> 8); +} + + +static void +pfq_write(void) +{ + uint16_t tempw; + + /* On 8086 and even IP, fetch *TWO* bytes at once. */ + if (pfq_pos < pfq_size) { + /* If we're filling the last byte of the prefetch queue, do *NOT* + read more than one byte even on the 8086. */ + if (is8086 && !(pfq_ip & 1) && !(pfq_pos & 1)) { + tempw = readmemwf(pfq_ip); + *(uint16_t *) &(pfq[pfq_pos]) = tempw; + pfq_ip += 2; + pfq_pos += 2; + } else { + pfq[pfq_pos] = readmembf(pfq_ip); + pfq_ip++; + pfq_pos++; + } } } +static uint8_t +pfq_read(void) +{ + uint8_t temp, i; + + temp = pfq[0]; + + for (i = 0; i < (pfq_size - 1); i++) + pfq[i] = pfq[i + 1]; + pfq_pos--; + + cpu_state.pc++; + + return temp; +} + + /* Fetches a byte from the prefetch queue, or from memory if the queue has been drained. */ static uint8_t pfq_fetchb(void) { - uint8_t temp, i; + uint8_t temp; if (pfq_pos == 0) { - cycles -= (4 - (fetchcycles & 3)); - fetchclocks += (4 - (fetchcycles & 3)); + /* Extra cycles due to having to fetch on read. */ + cpu_wait(4 - (fetchcycles & 3), 1); fetchcycles = 4; - temp = readmembf(cpu_state.pc); - pfq_ip = cpu_state.pc = cpu_state.pc + 1; - if (is8086 && (cpu_state.pc & 1)) { - pfq[0] = readmembf(cpu_state.pc); - pfq_ip++; - pfq_pos++; - } - } else { - temp = pfq[0]; - for (i = 0; i < (pfq_size - 1); i++) - pfq[i] = pfq[i + 1]; - pfq_pos--; + /* Reset prefetch queue internal position. */ + pfq_ip = cpu_state.pc; + /* Fill the queue. */ + pfq_write(); + } else fetchcycles -= 4; - cpu_state.pc++; - } - wait(1, 0); + + /* Fetch. */ + temp = pfq_read(); + cpu_wait(1, 0); + return temp; } @@ -375,16 +423,7 @@ pfq_add(int c) d = c + (fetchcycles & 3); while ((d > 3) && (pfq_pos < pfq_size)) { d -= 4; - if (is8086 && !(pfq_ip & 1)) { - pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip++; - pfq_pos++; - } - if (pfq_pos < pfq_size) { - pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip++; - pfq_pos++; - } + pfq_write(); } fetchcycles += c; if (fetchcycles > 16) @@ -392,46 +431,12 @@ pfq_add(int c) } -/* Completes a fetch (called by refreshread()). */ -static void -pfq_complete(void) -{ - if (!(fetchcycles & 3)) - return; - if (pfq_pos >= pfq_size) - return; - if (!pfq_pos) - nextcyc = (4 - (fetchcycles & 3)); - cycles -= (4 - (fetchcycles & 3)); - fetchclocks += (4 - (fetchcycles & 3)); - if (is8086 && !(pfq_ip & 1)) { - pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip++; - pfq_pos++; - } - if (pfq_pos < pfq_size) { - pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip++; - pfq_pos++; - } - fetchcycles += (4 - (fetchcycles & 3)); -} - - /* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ static void -pfq_clear() +pfq_clear(void) { pfq_ip = cpu_state.pc; pfq_pos = 0; - fetchclocks = 0; -} - - -/* Memory refresh read - called by reads and writes on DMA channel 0. */ -void -refreshread(void) { - pfq_complete(); } @@ -486,22 +491,22 @@ do_mod_rm(void) if (cpu_mod == 3) return; - wait(3, 0); + cpu_wait(3, 0); if (!cpu_mod && (cpu_rm == 6)) { - wait(2, 0); + cpu_wait(2, 0); cpu_state.eaaddr = pfq_fetchw(); easeg = ds; - wait(1, 0); + cpu_wait(1, 0); } else { switch (cpu_rm) { case 0: case 3: - wait(2, 0); + cpu_wait(2, 0); break; case 1: case 2: - wait(3, 0); + cpu_wait(3, 0); break; } @@ -510,15 +515,15 @@ do_mod_rm(void) switch (cpu_mod) { case 1: - wait(4, 0); + cpu_wait(4, 0); cpu_state.eaaddr += (uint16_t) (int8_t) pfq_fetchb(); break; case 2: - wait(4, 0); + cpu_wait(4, 0); cpu_state.eaaddr += pfq_fetchw(); break; } - wait(2, 0); + cpu_wait(2, 0); } cpu_state.eaaddr &= 0xffff; @@ -555,6 +560,7 @@ geteaw(void) { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; + return readmemw(easeg, cpu_state.eaaddr); } @@ -569,7 +575,8 @@ read_ea(int memory_only, int bits) cpu_data = readmemb(easeg + cpu_state.eaaddr); return; } - if (!memory_only) { + + if (! memory_only) { if (bits == 8) { cpu_data = getr8(cpu_rm); } else @@ -609,6 +616,7 @@ seteaw(uint16_t val) writememw(easeg, cpu_state.eaaddr, val); } + /* Prepare the ZNP table needed to speed up the setting of the Z, N, and P flags. */ static void makeznptable(void) @@ -638,6 +646,8 @@ makeznptable(void) znptable8[c] = P_FLAG; if (c == 0xb1) DEBUG("znp8 b1 = %i %02X\n", d, znptable8[c]); + if (c == 0x65b1) + DEBUG("znp16 65b1 = %i %02X\n", d, znptable16[c]); if (!c) znptable8[c] |= Z_FLAG; if (c & 0x80) @@ -739,42 +749,27 @@ reset_common(int hard) } -/* Hard reset. */ -void -resetx86(void) -{ - reset_common(1); -} - - -/* Soft reset. */ -void -softresetx86(void) -{ - reset_common(0); -} - - /* Pushes a word to the stack. */ static void -push_ex(uint16_t val) +do_push_ex(uint16_t val) { - writememw(ss, (SP & 0xFFFF), val); + writememw(ss, (SP & 0xffff), val); cpu_state.last_ea = SP; } static void -push(uint16_t val) +do_push(uint16_t val) { SP -= 2; - push_ex(val); + + do_push_ex(val); } /* Pops a word from the stack. */ static uint16_t -pop(void) +do_pop(void) { uint16_t tempw; @@ -786,7 +781,7 @@ pop(void) static void -access(int num, int bits) +do_access(int num, int bits) { switch (num) { case 0: case 61: case 63: case 64: @@ -796,92 +791,92 @@ access(int num, int bits) case 1: case 6: case 8: case 9: case 17: case 20: case 21: case 24: case 28: case 55: case 56: - wait(1 + (cycles % 3), 0); + cpu_wait(1 + (cycles % 3), 0); break; case 2: case 15: case 22: case 23: case 25: case 26: case 46: case 53: - wait(2 + (cycles % 3), 0); + cpu_wait(2 + (cycles % 3), 0); break; case 3: case 44: case 45: case 52: case 54: - wait(2 + (cycles & 1), 0); + cpu_wait(2 + (cycles & 1), 0); break; case 4: - wait(5 + (cycles & 1), 0); + cpu_wait(5 + (cycles & 1), 0); break; case 5: if (opcode == 0xcc) - wait(7 + (cycles % 3), 0); + cpu_wait(7 + (cycles % 3), 0); else - wait(4 + (cycles & 1), 0); + cpu_wait(4 + (cycles & 1), 0); break; case 7: case 47: case 48: case 49: case 50: case 51: - wait(1 + (cycles % 4), 0); + cpu_wait(1 + (cycles % 4), 0); break; case 10: case 11: case 18: case 19: case 43: - wait(3 + (cycles % 3), 0); + cpu_wait(3 + (cycles % 3), 0); break; case 12: case 13: case 14: case 29: case 30: case 33: - wait(4 + (cycles % 3), 0); + cpu_wait(4 + (cycles % 3), 0); break; case 16: if (!(opcode & 1) && (cycles & 1)) - wait(1, 0); + cpu_wait(1, 0); /* Fall through. */ case 42: - wait(3 + (cycles & 1), 0); + cpu_wait(3 + (cycles & 1), 0); break; case 27: case 32: case 37: - wait(3, 0); + cpu_wait(3, 0); break; case 31: - wait(6 + (cycles % 3), 0); + cpu_wait(6 + (cycles % 3), 0); break; case 34: case 39: case 41: case 60: - wait(4, 0); + cpu_wait(4, 0); break; case 35: - wait(2, 0); + cpu_wait(2, 0); break; case 36: - wait(5 + (cycles & 1), 0); + cpu_wait(5 + (cycles & 1), 0); if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); break; case 38: - wait(5 + (cycles % 3), 0); + cpu_wait(5 + (cycles % 3), 0); break; case 40: - wait(6, 0); + cpu_wait(6, 0); break; case 57: if (cpu_mod != 3) - wait(2, 0); - wait(4 + (cycles & 1), 0); + cpu_wait(2, 0); + cpu_wait(4 + (cycles & 1), 0); break; case 58: if (cpu_mod != 3) - wait(1, 0); - wait(4 + (cycles & 1), 0); + cpu_wait(1, 0); + cpu_wait(4 + (cycles & 1), 0); break; case 59: if (cpu_mod != 3) - wait(1, 0); - wait(5 + (cycles & 1), 0); + cpu_wait(1, 0); + cpu_wait(5 + (cycles & 1), 0); break; case 62: - wait(1, 0); + cpu_wait(1, 0); break; case 65: - wait(3 + (cycles & 1), 0); + cpu_wait(3 + (cycles & 1), 0); if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); break; case 70: - wait(5, 0); + cpu_wait(5, 0); break; } } @@ -889,31 +884,31 @@ access(int num, int bits) /* Calls an interrupt. */ static void -interrupt(uint16_t addr, int cli) +do_intr(uint16_t addr, int cli) { uint16_t old_cs, old_ip; uint16_t new_cs, new_ip; addr <<= 2; old_cs = CS; - access(5, 16); + do_access(5, 16); new_ip = readmemw(0, addr); - wait(1, 0); - access(6, 16); + cpu_wait(1, 0); + do_access(6, 16); new_cs = readmemw(0, (addr + 2) & 0xffff); - access(39, 16); - push(flags & 0x0fd7); + do_access(39, 16); + do_push(flags & 0x0fd7); if (cli) flags &= ~I_FLAG; flags &= ~T_FLAG; - access(40, 16); - push(old_cs); + do_access(40, 16); + do_push(old_cs); old_ip = cpu_state.pc; loadcs(new_cs); - access(68, 16); + do_access(68, 16); cpu_state.pc = new_ip; - access(41, 16); - push(old_ip); + do_access(41, 16); + do_push(old_ip); pfq_clear(); } @@ -925,35 +920,35 @@ rep_action(int *completed, int *repeating, int in_rep, int bits) if (in_rep == 0) return 0; - wait(2, 0); + cpu_wait(2, 0); t = CX; if (irq_pending()) { - access(71, bits); + do_access(71, bits); pfq_clear(); cpu_state.pc = cpu_state.pc - 2; t = 0; } if (t == 0) { - wait(1, 0); + cpu_wait(1, 0); *completed = 1; *repeating = 0; return 1; } --CX; *completed = 0; - wait(2, 0); + cpu_wait(2, 0); if (!*repeating) - wait(2, 0); + cpu_wait(2, 0); return 0; } static uint16_t -jump(uint16_t delta) +do_jump(uint16_t delta) { uint16_t old_ip; - access(67, 8); - wait(5, 0); + do_access(67, 8); + cpu_wait(5, 0); old_ip = cpu_state.pc; cpu_state.pc = (cpu_state.pc + delta) & 0xffff; pfq_clear(); @@ -971,26 +966,26 @@ sign_extend(uint8_t data) static void jump_short(void) { - jump(sign_extend((uint8_t) cpu_data)); + do_jump(sign_extend((uint8_t) cpu_data)); } static uint16_t jump_near(void) { - return jump(pfq_fetchw()); + return do_jump(pfq_fetchw()); } /* Performs a conditional jump. */ static void -jcc(uint8_t opcode, int cond) +do_jcc(uint8_t opcode, int cond) { /* int8_t offset; */ - wait(1, 0); + cpu_wait(1, 0); cpu_data = pfq_fetchb(); - wait(1, 0); + cpu_wait(1, 0); if ((!cond) == (opcode & 0x01)) jump_short(); } @@ -1027,7 +1022,7 @@ bitwise(int bits, uint16_t data) static void -test(int bits, uint16_t dest, uint16_t src) +do_test(int bits, uint16_t dest, uint16_t src) { cpu_dest = dest; cpu_src = src; @@ -1089,7 +1084,7 @@ set_apzs(int bits) static void -add(int bits) +do_add(int bits) { int size_mask = (1 << bits) - 1; @@ -1107,7 +1102,7 @@ add(int bits) static void -sub(int bits) +do_sub(int bits) { int size_mask = (1 << bits) - 1; @@ -1136,17 +1131,17 @@ alu_op(int bits) cpu_src++; /* Fall through. */ case 0: - add(bits); + do_add(bits); break; case 3: if (flags & C_FLAG) cpu_src++; /* Fall through. */ case 5: case 7: - sub(bits); + do_sub(bits); break; case 4: - test(bits, cpu_dest, cpu_src); + do_test(bits, cpu_dest, cpu_src); break; case 6: bitwise(bits, (cpu_dest ^ cpu_src)); @@ -1188,7 +1183,7 @@ set_pf(void) static void -mul(uint16_t a, uint16_t b) +do_mul(uint16_t a, uint16_t b) { int negate = 0; int bit_count = 8; @@ -1204,32 +1199,32 @@ mul(uint16_t a, uint16_t b) bit_count = 16; high_bit = 0x8000; } else - wait(8, 0); + cpu_wait(8, 0); size_mask = (1 << bit_count) - 1; if ((rmdat & 0x38) == 0x28) { if (!top_bit(a, bit_count)) { if (top_bit(b, bit_count)) { - wait(1, 0); + cpu_wait(1, 0); if ((b & size_mask) != ((opcode & 1) ? 0x8000 : 0x80)) - wait(1, 0); + cpu_wait(1, 0); b = ~b + 1; negate = 1; } } else { - wait(1, 0); + cpu_wait(1, 0); a = ~a + 1; negate = 1; if (top_bit(b, bit_count)) { b = ~b + 1; negate = 0; } else - wait(4, 0); + cpu_wait(4, 0); } - wait(10, 0); + cpu_wait(10, 0); } - wait(3, 0); + cpu_wait(3, 0); } c = 0; @@ -1237,13 +1232,13 @@ mul(uint16_t a, uint16_t b) carry = (a & 1) != 0; a >>= 1; for (i = 0; i < bit_count; ++i) { - wait(7, 0); + cpu_wait(7, 0); if (carry) { cpu_src = c; cpu_dest = b; - add(bit_count); + do_add(bit_count); c = cpu_data & size_mask; - wait(1, 0); + cpu_wait(1, 0); carry = !!(flags & C_FLAG); } r = (c >> 1) + (carry ? high_bit : 0); @@ -1258,7 +1253,7 @@ mul(uint16_t a, uint16_t b) a = (~a + 1) & size_mask; if (a == 0) ++c; - wait(9, 0); + cpu_wait(9, 0); } cpu_data = a; cpu_dest = c; @@ -1299,12 +1294,12 @@ set_co_mul(int carry) set_cf(carry); set_of(carry); if (!carry) - wait(1, 0); + cpu_wait(1, 0); } static int -div(uint16_t l, uint16_t h) +do_div(uint16_t l, uint16_t h) { int b, bit_count = 8; int negative = 0; @@ -1330,28 +1325,28 @@ div(uint16_t l, uint16_t h) h &= size_mask; negative = 1; dividend_negative = 1; - wait(4, 0); + cpu_wait(4, 0); } if (top_bit(cpu_src, bit_count)) { cpu_src = ~cpu_src + 1; negative = !negative; } else - wait(1, 0); - wait(9, 0); + cpu_wait(1, 0); + cpu_wait(9, 0); } - wait(3, 0); + cpu_wait(3, 0); } - cycles -= 8; + cpu_wait(8, 0); cpu_src &= size_mask; if (h >= cpu_src) { if (opcode != 0xd4) - wait(1, 0); - interrupt(0, 1); + cpu_wait(1, 0); + do_intr(0, 1); return 0; } if (opcode != 0xd4) - wait(1, 0); - wait(2, 0); + cpu_wait(1, 0); + cpu_wait(2, 0); carry = 1; for (b = 0; b < bit_count; ++b) { r = (l << 1) + (carry ? 1 : 0); @@ -1360,32 +1355,32 @@ div(uint16_t l, uint16_t h) r = (h << 1) + (carry ? 1 : 0); carry = top_bit(h, bit_count); h = r; - wait(8, 0); + cpu_wait(8, 0); if (carry) { carry = 0; h -= cpu_src; if (b == bit_count - 1) - wait(2, 0); + cpu_wait(2, 0); } else { carry = cpu_src > h; if (!carry) { h -= cpu_src; - wait(1, 0); + cpu_wait(1, 0); if (b == bit_count - 1) - wait(2, 0); + cpu_wait(2, 0); } } } l = ~((l << 1) + (carry ? 1 : 0)); if (opcode != 0xd4 && (rmdat & 0x38) == 0x38) { - wait(4, 0); + cpu_wait(4, 0); if (top_bit(l, bit_count)) { if (cpu_mod == 3) - wait(1, 0); - interrupt(0, 1); + cpu_wait(1, 0); + do_intr(0, 1); return 0; } - wait(7, 0); + cpu_wait(7, 0); if (negative) l = ~l + 1; if (dividend_negative) @@ -1407,7 +1402,7 @@ div(uint16_t l, uint16_t h) static void -lods(int bits) +do_lods(int bits) { if (bits == 16) cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), SI); @@ -1421,7 +1416,7 @@ lods(int bits) static void -stos(int bits) +do_stos(int bits) { if (bits == 16) writememw(es, DI, cpu_data); @@ -1435,19 +1430,19 @@ stos(int bits) static void -da(void) +do_da(void) { set_pzs(8); - wait(2, 0); + cpu_wait(2, 0); } static void -aa(void) +do_aa(void) { set_of(0); AL &= 0x0f; - wait(6, 0); + cpu_wait(6, 0); } @@ -1472,7 +1467,7 @@ void execx86(int cycs) { uint8_t temp = 0, temp2; - uint16_t addr, tempw; + uint16_t do_addr, tempw; uint16_t new_cs, new_ip; int bits, completed; int in_rep, repeating; @@ -1482,50 +1477,57 @@ execx86(int cycs) while (cycles > 0) { timer_start_period(cycles * xt_cpu_multi); - wait(nextcyc, 0); - nextcyc = 0; - fetchclocks = 0; cpu_state.oldpc = cpu_state.pc; in_rep = repeating = 0; completed = 0; opcodestart: if (halt) { - wait(2, 0); + cpu_wait(2, 0); goto on_halt; } - if (!repeating) { + if (! repeating) { opcode = pfq_fetchb(); oldc = flags & C_FLAG; trap = flags & T_FLAG; - wait(1, 0); + cpu_wait(1, 0); - /* if (!in_rep && !ovr_seg && (CS < 0xf000)) - pclog("%04X:%04X %02X\n", CS, (cpu_state.pc - 1) & 0xFFFF, opcode); */ +#if 0 + if (!in_rep && !ovr_seg && (CS < 0xf000)) + DEBUG("%04X:%04X %02X\n", + CS, (cpu_state.pc - 1) & 0xffff, opcode); +#endif } switch (opcode) { - case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ - access(29, 16); - push(_opseg[(opcode >> 3) & 0x03]->seg); + case 0x06: /* PUSH seg */ + case 0x0e: + case 0x16: + case 0x1e: + do_access(29, 16); + do_push(_opseg[(opcode >> 3) & 0x03]->seg); break; - case 0x07: case 0x0F: case 0x17: case 0x1F: /* POP seg */ - access(22, 16); - if (opcode == 0x0F) { - loadcs(pop()); + + case 0x07: /* POP seg */ + case 0x0f: + case 0x17: + case 0x1f: + do_access(22, 16); + if (opcode == 0x0f) { + loadcs(do_pop()); pfq_clear(); } else - loadseg(pop(), _opseg[(opcode >> 3) & 0x03]); - wait(1, 0); + loadseg(do_pop(), _opseg[(opcode >> 3) & 0x03]); + cpu_wait(1, 0); noint = 1; break; case 0x26: /*ES:*/ - case 0x2E: /*CS:*/ + case 0x2e: /*CS:*/ case 0x36: /*SS:*/ - case 0x3E: /*DS:*/ - wait(1, 0); + case 0x3e: /*DS:*/ + cpu_wait(1, 0); ovr_seg = opseg[(opcode >> 3) & 0x03]; goto opcodestart; @@ -1540,7 +1542,7 @@ opcodestart: /* alu rm, r / r, rm */ bits = 8 << (opcode & 1); do_mod_rm(); - access(46, bits); + do_access(46, bits); if (opcode & 1) tempw = geteaw(); else @@ -1554,27 +1556,27 @@ opcodestart: cpu_src = tempw; } if (cpu_mod != 3) - wait(2, 0); - wait(1, 0); + cpu_wait(2, 0); + cpu_wait(1, 0); alu_op(bits); if (cpu_alu_op != 7) { if ((opcode & 2) == 0) { - access(10, bits); + do_access(10, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t) (cpu_data & 0xff)); if (cpu_mod == 3) - wait(1, 0); + cpu_wait(1, 0); } else { if (opcode & 1) cpu_state.regs[cpu_reg].w = cpu_data; else setr8(cpu_reg, (uint8_t)(cpu_data & 0xff)); - wait(1, 0); + cpu_wait(1, 0); } } else - wait(1, 0); + cpu_wait(1, 0); break; case 0x04: case 0x05: case 0x0c: case 0x0d: @@ -1583,7 +1585,7 @@ opcodestart: case 0x34: case 0x35: case 0x3c: case 0x3d: /* alu A, imm */ bits = 8 << (opcode & 1); - wait(1, 0); + cpu_wait(1, 0); if (opcode & 1) { cpu_data = pfq_fetchw(); cpu_dest = AX; @@ -1600,71 +1602,74 @@ opcodestart: else AL = cpu_data & 0xff; } - wait(1, 0); + cpu_wait(1, 0); break; case 0x27: /*DAA*/ - wait(1, 0); + cpu_wait(1, 0); if ((flags & A_FLAG) || (AL & 0x0f) > 9) { cpu_data = AL + 6; AL = (uint8_t) cpu_data; set_af(1); - if ((cpu_data & 0x100) != 0) + if ((cpu_data & 0x0100) != 0) set_cf(1); } if ((flags & C_FLAG) || AL > 0x9f) { AL += 0x60; set_cf(1); } - da(); + do_da(); break; - case 0x2F: /*DAS*/ - wait(1, 0); + + case 0x2f: /*DAS*/ + cpu_wait(1, 0); temp = AL; - if ((flags & A_FLAG) || ((AL & 0xf) > 9)) { + if ((flags & A_FLAG) || ((AL & 0x0f) > 9)) { cpu_data = AL - 6; AL = (uint8_t) cpu_data; set_af(1); - if ((cpu_data & 0x100) != 0) + if ((cpu_data & 0x0100) != 0) set_cf(1); } if ((flags & C_FLAG) || temp > 0x9f) { AL -= 0x60; set_cf(1); } - da(); + do_da(); break; + case 0x37: /*AAA*/ - wait(1, 0); - if ((flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_wait(1, 0); + if ((flags & A_FLAG) || ((AL & 0x0f) > 9)) { AL += 6; ++AH; set_ca(); } else { clear_ca(); - wait(1, 0); + cpu_wait(1, 0); } - aa(); + do_aa(); break; - case 0x3F: /*AAS*/ - wait(1, 0); - if ((flags & A_FLAG) || ((AL & 0xf) > 9)) { + + case 0x3f: /*AAS*/ + cpu_wait(1, 0); + if ((flags & A_FLAG) || ((AL & 0x0f) > 9)) { AL -= 6; --AH; set_ca(); } else { clear_ca(); - wait(1, 0); + cpu_wait(1, 0); } - aa(); + do_aa(); break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4A: case 0x4B: - case 0x4C: case 0x4D: case 0x4E: case 0x4F: + case 0x48: case 0x49: case 0x4a: case 0x4b: + case 0x4c: case 0x4d: case 0x4e: case 0x4f: /* INCDEC rw */ - wait(1, 0); + cpu_wait(1, 0); cpu_dest = cpu_state.regs[opcode & 7].w; cpu_src = 1; bits = 16; @@ -1682,109 +1687,117 @@ opcodestart: case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ case 0x54: case 0x55: case 0x56: case 0x57: - access(30, 16); + do_access(30, 16); if (opcode == 0x54) { SP -= 2; - push_ex(cpu_state.regs[opcode & 0x07].w); + do_push_ex(cpu_state.regs[opcode & 0x07].w); } else - push(cpu_state.regs[opcode & 0x07].w); + do_push(cpu_state.regs[opcode & 0x07].w); break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - access(23, 16); - cpu_state.regs[opcode & 0x07].w = pop(); - wait(1, 0); + + case 0x58: case 0x59: case 0x5a: case 0x5b: /*POP r16*/ + case 0x5c: case 0x5d: case 0x5e: case 0x5f: + do_access(23, 16); + cpu_state.regs[opcode & 0x07].w = do_pop(); + cpu_wait(1, 0); break; case 0x60: /*JO alias*/ case 0x70: /*JO*/ case 0x61: /*JNO alias*/ case 0x71: /*JNO*/ - jcc(opcode, flags & V_FLAG); + do_jcc(opcode, flags & V_FLAG); break; + case 0x62: /*JB alias*/ case 0x72: /*JB*/ case 0x63: /*JNB alias*/ case 0x73: /*JNB*/ - jcc(opcode, flags & C_FLAG); + do_jcc(opcode, flags & C_FLAG); break; + case 0x64: /*JE alias*/ case 0x74: /*JE*/ case 0x65: /*JNE alias*/ case 0x75: /*JNE*/ - jcc(opcode, flags & Z_FLAG); + do_jcc(opcode, flags & Z_FLAG); break; + case 0x66: /*JBE alias*/ case 0x76: /*JBE*/ case 0x67: /*JNBE alias*/ case 0x77: /*JNBE*/ - jcc(opcode, flags & (C_FLAG | Z_FLAG)); + do_jcc(opcode, flags & (C_FLAG | Z_FLAG)); break; + case 0x68: /*JS alias*/ case 0x78: /*JS*/ case 0x69: /*JNS alias*/ case 0x79: /*JNS*/ - jcc(opcode, flags & N_FLAG); + do_jcc(opcode, flags & N_FLAG); break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - jcc(opcode, flags & P_FLAG); + + case 0x6a: /*JP alias*/ + case 0x7a: /*JP*/ + case 0x6b: /*JNP alias*/ + case 0x7b: /*JNP*/ + do_jcc(opcode, flags & P_FLAG); break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ + + case 0x6c: /*JL alias*/ + case 0x7c: /*JL*/ + case 0x6d: /*JNL alias*/ + case 0x7d: /*JNL*/ temp = (flags & N_FLAG) ? 1 : 0; temp2 = (flags & V_FLAG) ? 1 : 0; - jcc(opcode, temp ^ temp2); + do_jcc(opcode, temp ^ temp2); break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ + + case 0x6e: /*JLE alias*/ + case 0x7e: /*JLE*/ + case 0x6f: /*JNLE alias*/ + case 0x7f: /*JNLE*/ temp = (flags & N_FLAG) ? 1 : 0; temp2 = (flags & V_FLAG) ? 1 : 0; - jcc(opcode, (flags & Z_FLAG) || (temp != temp2)); + do_jcc(opcode, (flags & Z_FLAG) || (temp != temp2)); break; case 0x80: case 0x81: case 0x82: case 0x83: /* alu rm, imm */ bits = 8 << (opcode & 1); do_mod_rm(); - access(47, bits); + do_access(47, bits); if (opcode & 1) cpu_data = geteaw(); else cpu_data = geteab(); cpu_dest = cpu_data; if (cpu_mod != 3) - wait(3, 0); + cpu_wait(3, 0); if (opcode == 0x81) { if (cpu_mod == 3) - wait(1, 0); + cpu_wait(1, 0); cpu_src = pfq_fetchw(); } else { if (cpu_mod == 3) - wait(1, 0); + cpu_wait(1, 0); if (opcode == 0x83) cpu_src = sign_extend(pfq_fetchb()); else cpu_src = pfq_fetchb() | 0xff00; } - wait(1, 0); + cpu_wait(1, 0); cpu_alu_op = (rmdat & 0x38) >> 3; alu_op(bits); if (cpu_alu_op != 7) { - access(11, bits); + do_access(11, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); } else { if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); } break; @@ -1792,23 +1805,24 @@ opcodestart: /* TEST rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); - access(48, bits); + do_access(48, bits); if (opcode & 1) { cpu_data = geteaw(); - test(bits, cpu_data, cpu_state.regs[cpu_reg].w); + do_test(bits, cpu_data, cpu_state.regs[cpu_reg].w); } else { cpu_data = geteab(); - test(bits, cpu_data, getr8(cpu_reg)); + do_test(bits, cpu_data, getr8(cpu_reg)); } if (cpu_mod == 3) - wait(2, 0); - wait(2, 0); + cpu_wait(2, 0); + cpu_wait(2, 0); break; + case 0x86: case 0x87: /* XCHG rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); - access(49, bits); + do_access(49, bits); if (opcode & 1) { cpu_data = geteaw(); cpu_src = cpu_state.regs[cpu_reg].w; @@ -1818,252 +1832,271 @@ opcodestart: cpu_src = getr8(cpu_reg); setr8(cpu_reg, (uint8_t)(cpu_data & 0xff)); } - wait(3, 0); - access(12, bits); + cpu_wait(3, 0); + do_access(12, bits); if (opcode & 1) seteaw(cpu_src); else seteab((uint8_t)(cpu_src & 0xff)); break; - case 0x88: case 0x89: - /* MOV rm, reg */ + case 0x88: /* MOV rm, reg */ + case 0x89: bits = 8 << (opcode & 1); do_mod_rm(); - wait(1, 0); - access(13, bits); + cpu_wait(1, 0); + do_access(13, bits); if (opcode & 1) seteaw(cpu_state.regs[cpu_reg].w); else seteab(getr8(cpu_reg)); break; - case 0x8A: case 0x8B: - /* MOV reg, rm */ + + case 0x8a: /* MOV reg, rm */ + case 0x8b: bits = 8 << (opcode & 1); do_mod_rm(); - access(50, bits); + do_access(50, bits); if (opcode & 1) cpu_state.regs[cpu_reg].w = geteaw(); else setr8(cpu_reg, geteab()); - wait(1, 0); + cpu_wait(1, 0); if (cpu_mod != 3) - wait(2, 0); + cpu_wait(2, 0); break; - case 0x8C: /*MOV w,sreg*/ + case 0x8c: /*MOV w,sreg*/ do_mod_rm(); if (cpu_mod == 3) - wait(1, 0); - access(14, 16); + cpu_wait(1, 0); + do_access(14, 16); switch (rmdat & 0x38) { case 0x00: /*ES*/ seteaw(ES); break; + case 0x08: /*CS*/ seteaw(CS); break; + case 0x18: /*DS*/ seteaw(DS); break; + case 0x10: /*SS*/ seteaw(SS); break; } break; - case 0x8D: /*LEA*/ + case 0x8d: /*LEA*/ do_mod_rm(); cpu_state.regs[cpu_reg].w = (cpu_mod == 3) ? cpu_state.last_ea : cpu_state.eaaddr; - wait(1, 0); + cpu_wait(1, 0); if (cpu_mod != 3) - wait(2, 0); + cpu_wait(2, 0); break; - case 0x8E: /*MOV sreg,w*/ + case 0x8e: /*MOV sreg,w*/ do_mod_rm(); - access(51, 16); + do_access(51, 16); tempw = geteaw(); switch (rmdat & 0x38) { case 0x00: /*ES*/ loadseg(tempw, &_es); break; + case 0x08: /*CS - 8088/8086 only*/ loadcs(tempw); pfq_clear(); break; + case 0x18: /*DS*/ loadseg(tempw, &_ds); break; + case 0x10: /*SS*/ loadseg(tempw, &_ss); break; } - wait(1, 0); + cpu_wait(1, 0); if (cpu_mod != 3) - wait(2, 0); + cpu_wait(2, 0); noint = 1; break; - case 0x8F: /*POPW*/ + case 0x8f: /*POPW*/ do_mod_rm(); - wait(1, 0); + cpu_wait(1, 0); cpu_src = cpu_state.eaaddr; - access(24, 16); + do_access(24, 16); if (cpu_mod != 3) - wait(2, 0); - cpu_data = pop(); + cpu_wait(2, 0); + cpu_data = do_pop(); cpu_state.eaaddr = cpu_src; - wait(2, 0); - access(15, 16); + cpu_wait(2, 0); + do_access(15, 16); seteaw(cpu_data); break; case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: /* XCHG AX, rw */ - wait(1, 0); + cpu_wait(1, 0); cpu_data = cpu_state.regs[opcode & 7].w; cpu_state.regs[opcode & 7].w = AX; AX = cpu_data; - wait(1, 0); + cpu_wait(1, 0); break; case 0x98: /*CBW*/ - wait(1, 0); + cpu_wait(1, 0); AX = sign_extend(AL); break; + case 0x99: /*CWD*/ - wait(4, 0); + cpu_wait(4, 0); if (!top_bit(AX, 16)) DX = 0; else { - wait(1, 0); + cpu_wait(1, 0); DX = 0xffff; } break; - case 0x9A: /*CALL FAR*/ - wait(1, 0); + + case 0x9a: /*CALL FAR*/ + cpu_wait(1, 0); new_ip = pfq_fetchw(); - wait(1, 0); + cpu_wait(1, 0); new_cs = pfq_fetchw(); - access(31, 16); - push(CS); - access(60, 16); + do_access(31, 16); + do_push(CS); + do_access(60, 16); cpu_state.oldpc = cpu_state.pc; loadcs(new_cs); cpu_state.pc = new_ip; - access(32, 16); - push(cpu_state.oldpc); + do_access(32, 16); + do_push(cpu_state.oldpc); pfq_clear(); break; - case 0x9B: /*WAIT*/ - cycles -= 4; + + case 0x9b: /*WAIT*/ + cpu_wait(4, 0); break; - case 0x9C: /*PUSHF*/ - access(33, 16); - push((flags & 0x0fd7) | 0xf000); + + case 0x9c: /*PUSHF*/ + do_access(33, 16); + do_push((flags & 0x0fd7) | 0xf000); break; - case 0x9D: /*POPF*/ - access(25, 16); - flags = pop() | 2; - wait(1, 0); + + case 0x9d: /*POPF*/ + do_access(25, 16); + flags = do_pop() | 2; + cpu_wait(1, 0); break; - case 0x9E: /*SAHF*/ - wait(1, 0); + + case 0x9e: /*SAHF*/ + cpu_wait(1, 0); flags = (flags & 0xff02) | AH; - wait(2, 0); + cpu_wait(2, 0); break; - case 0x9F: /*LAHF*/ - wait(1, 0); + + case 0x9f: /*LAHF*/ + cpu_wait(1, 0); AH = flags & 0xd7; break; - case 0xA0: case 0xA1: - /* MOV A, [iw] */ + case 0xa0: /* MOV A, [iw] */ + case 0xa1: bits = 8 << (opcode & 1); - wait(1, 0); - addr = pfq_fetchw(); - access(1, bits); + cpu_wait(1, 0); + do_addr = pfq_fetchw(); + do_access(1, bits); if (opcode & 1) - AX = readmemw((ovr_seg ? *ovr_seg : ds), addr); + AX = readmemw((ovr_seg ? *ovr_seg : ds), do_addr); else - AL = readmemb((ovr_seg ? *ovr_seg : ds) + addr); - wait(1, 0); - break; - case 0xA2: case 0xA3: - /* MOV [iw], A */ - bits = 8 << (opcode & 1); - wait(1, 0); - addr = pfq_fetchw(); - access(7, bits); - if (opcode & 1) - writememw((ovr_seg ? *ovr_seg : ds), addr, AX); - else - writememb((ovr_seg ? *ovr_seg : ds) + addr, AL); + AL = readmemb((ovr_seg ? *ovr_seg : ds) + do_addr); + cpu_wait(1, 0); break; - case 0xA4: case 0xA5: /* MOVS */ - case 0xAC: case 0xAD: /* LODS */ + case 0xa2: /* MOV [iw], A */ + case 0xa3: + bits = 8 << (opcode & 1); + cpu_wait(1, 0); + do_addr = pfq_fetchw(); + do_access(7, bits); + if (opcode & 1) + writememw((ovr_seg ? *ovr_seg : ds), do_addr, AX); + else + writememb((ovr_seg ? *ovr_seg : ds) + do_addr, AL); + break; + + case 0xa4: /* MOVS */ + case 0xa5: + case 0xac: /* LODS */ + case 0xad: bits = 8 << (opcode & 1); if (!repeating) { - wait(1 /*2*/, 0); + cpu_wait(1 /*2*/, 0); if ((opcode & 8) == 0 && in_rep != 0) - wait(1, 0); + cpu_wait(1, 0); } if (rep_action(&completed, &repeating, in_rep, bits)) { - wait(1, 0); + cpu_wait(1, 0); if ((opcode & 8) != 0) - wait(1, 0); + cpu_wait(1, 0); break; } if (in_rep != 0 && (opcode & 8) != 0) - wait(1, 0); - access(20, bits); - lods(bits); + cpu_wait(1, 0); + do_access(20, bits); + do_lods(bits); if ((opcode & 8) == 0) { - access(27, bits); - stos(bits); + do_access(27, bits); + do_stos(bits); } else { if (opcode & 1) AX = cpu_data; else AL = (uint8_t)(cpu_data & 0xff); if (in_rep != 0) - wait(2, 0); + cpu_wait(2, 0); } if (in_rep == 0) { - wait(3, 0); + cpu_wait(3, 0); if ((opcode & 8) != 0) - wait(1, 0); + cpu_wait(1, 0); break; } repeating = 1; timer_end_period(cycles * xt_cpu_multi); goto opcodestart; - case 0xA6: case 0xA7: /* CMPS */ - case 0xAE: case 0xAF: /* SCAS */ + case 0xa6: /* CMPS */ + case 0xa7: + case 0xae: /* SCAS */ + case 0xaf: bits = 8 << (opcode & 1); if (!repeating) - wait(1, 0); + cpu_wait(1, 0); if (rep_action(&completed, &repeating, in_rep, bits)) { - wait(2, 0); + cpu_wait(2, 0); break; } if (in_rep != 0) - wait(1, 0); + cpu_wait(1, 0); if (opcode & 1) cpu_dest = AX; else cpu_dest = AL; if ((opcode & 8) == 0) { - access(21, bits); - lods(bits); - wait(1, 0); + do_access(21, bits); + do_lods(bits); + cpu_wait(1, 0); cpu_dest = cpu_data; } - access(2, bits); + do_access(2, bits); if (opcode & 1) cpu_data = readmemw(es, DI); else @@ -2073,188 +2106,210 @@ opcodestart: else DI += (bits >> 3); cpu_src = cpu_data; - sub(bits); - wait(2, 0); + do_sub(bits); + cpu_wait(2, 0); if (in_rep == 0) { - wait(3, 0); + cpu_wait(3, 0); break; } if ((!!(flags & Z_FLAG)) == (in_rep == 1)) { - wait(4, 0); + cpu_wait(4, 0); break; } repeating = 1; timer_end_period(cycles * xt_cpu_multi); goto opcodestart; - case 0xA8: case 0xA9: - /* TEST A, imm */ + case 0xa8: /* TEST A, imm */ + case 0xa9: bits = 8 << (opcode & 1); - wait(1, 0); + cpu_wait(1, 0); if (opcode & 1) { cpu_data = pfq_fetchw(); - test(bits, AX, cpu_data); + do_test(bits, AX, cpu_data); } else { cpu_data = pfq_fetchb(); - test(bits, AL, cpu_data); + do_test(bits, AL, cpu_data); } - wait(1, 0); + cpu_wait(1, 0); break; - case 0xAA: case 0xAB: /* STOS */ + case 0xaa: /* STOS */ + case 0xab: bits = 8 << (opcode & 1); if (!repeating) { if (opcode & 1) - wait(1, 0); + cpu_wait(1, 0); if (in_rep != 0) - wait(1, 0); + cpu_wait(1, 0); } if (rep_action(&completed, &repeating, in_rep, bits)) { - wait(1, 0); + cpu_wait(1, 0); break; } cpu_data = AX; - access(28, bits); - stos(bits); + do_access(28, bits); + do_stos(bits); if (in_rep == 0) { - wait(3, 0); + cpu_wait(3, 0); break; } repeating = 1; timer_end_period(cycles * xt_cpu_multi); goto opcodestart; - case 0xB0: case 0xB1: case 0xB2: case 0xB3: /*MOV cpu_reg,#8*/ - case 0xB4: case 0xB5: case 0xB6: case 0xB7: - wait(1, 0); + case 0xb0: /*MOV cpu_reg,#8*/ + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + cpu_wait(1, 0); if (opcode & 0x04) cpu_state.regs[opcode & 0x03].b.h = pfq_fetchb(); else cpu_state.regs[opcode & 0x03].b.l = pfq_fetchb(); - wait(1, 0); + cpu_wait(1, 0); break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - wait(1, 0); + case 0xb8: /*MOV cpu_reg,#16*/ + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + cpu_wait(1, 0); cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); - wait(1, 0); + cpu_wait(1, 0); break; - case 0xC0: case 0xC1: case 0xC2: case 0xC3: - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - /* RET */ + case 0xc0: /* RET */ + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: bits = 8 + (opcode & 0x08); if ((opcode & 9) != 1) - wait(1, 0); + cpu_wait(1, 0); if (!(opcode & 1)) { cpu_src = pfq_fetchw(); - wait(1, 0); + cpu_wait(1, 0); } if ((opcode & 9) == 9) - wait(1, 0); - access(26, bits); - new_ip = pop(); - wait(2, 0); + cpu_wait(1, 0); + do_access(26, bits); + new_ip = do_pop(); + cpu_wait(2, 0); if ((opcode & 8) == 0) new_cs = CS; else { - access(42, bits); - new_cs = pop(); + do_access(42, bits); + new_cs = do_pop(); if (opcode & 1) - wait(1, 0); + cpu_wait(1, 0); } if (!(opcode & 1)) { SP += cpu_src; - wait(1, 0); + cpu_wait(1, 0); } loadcs(new_cs); - access(72, bits); + do_access(72, bits); cpu_state.pc = new_ip; pfq_clear(); break; - case 0xC4: case 0xC5: - /* LsS rw, rmd */ + case 0xc4: /* LSS rw, rmd */ + case 0xc5: do_mod_rm(); bits = 16; - access(52, bits); + do_access(52, bits); cpu_state.regs[cpu_reg].w = readmemw(easeg, cpu_state.eaaddr); tempw = readmemw(easeg, (cpu_state.eaaddr + 2) & 0xFFFF); loadseg(tempw, (opcode & 0x01) ? &_ds : &_es); - wait(1, 0); + cpu_wait(1, 0); noint = 1; break; - case 0xC6: case 0xC7: - /* MOV rm, imm */ + case 0xc6: /* MOV rm, imm */ + case 0xc7: bits = 8 << (opcode & 1); do_mod_rm(); - wait(1, 0); + cpu_wait(1, 0); if (cpu_mod != 3) - wait(2, 0); + cpu_wait(2, 0); if (opcode & 1) cpu_data = pfq_fetchw(); else cpu_data = pfq_fetchb(); if (cpu_mod == 3) - wait(1, 0); - access(16, bits); + cpu_wait(1, 0); + do_access(16, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; - case 0xCC: /*INT 3*/ - interrupt(3, 1); + case 0xcc: /*INT 3*/ + do_intr(3, 1); break; - case 0xCD: /*INT*/ - wait(1, 0); - interrupt(pfq_fetchb(), 1); + + case 0xcd: /*INT*/ + cpu_wait(1, 0); + do_intr(pfq_fetchb(), 1); break; - case 0xCE: /*INTO*/ - wait(3, 0); + + case 0xce: /*INTO*/ + cpu_wait(3, 0); if (flags & V_FLAG) { - wait(2, 0); - interrupt(4, 1); + cpu_wait(2, 0); + do_intr(4, 1); } break; - case 0xCF: /*IRET*/ - access(43, 8); - new_ip = pop(); - wait(3, 0); - access(44, 8); - new_cs = pop(); + case 0xcf: /*IRET*/ + do_access(43, 8); + new_ip = do_pop(); + cpu_wait(3, 0); + do_access(44, 8); + new_cs = do_pop(); loadcs(new_cs); - access(62, 8); + do_access(62, 8); cpu_state.pc = new_ip; - access(45, 8); - flags = pop() | 2; - wait(5, 0); + do_access(45, 8); + flags = do_pop() | 2; + cpu_wait(5, 0); noint = 1; nmi_enable = 1; pfq_clear(); break; - case 0xD0: case 0xD1: case 0xD2: case 0xD3: - /* rot rm */ + case 0xd0: /* rot rm */ + case 0xd1: + case 0xd2: + case 0xd3: bits = 8 << (opcode & 1); do_mod_rm(); if (cpu_mod == 3) - wait(1, 0); - access(53, bits); + cpu_wait(1, 0); + do_access(53, bits); if (opcode & 1) cpu_data = geteaw(); else cpu_data = geteab(); if ((opcode & 2) == 0) { cpu_src = 1; - wait((cpu_mod != 3) ? 4 : 0, 0); + cpu_wait((cpu_mod != 3) ? 4 : 0, 0); } else { cpu_src = CL; - wait((cpu_mod != 3) ? 9 : 6, 0); + cpu_wait((cpu_mod != 3) ? 9 : 6, 0); } while (cpu_src != 0) { cpu_dest = cpu_data; @@ -2266,6 +2321,7 @@ opcodestart: cpu_data |= ((flags & C_FLAG) ? 1 : 0); set_of_rotate(bits); break; + case 0x08: /* ROR */ set_cf((cpu_data & 1) != 0); cpu_data >>= 1; @@ -2273,11 +2329,13 @@ opcodestart: cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); set_of_rotate(bits); break; + case 0x10: /* RCL */ set_cf(top_bit(cpu_data, bits)); cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); set_of_rotate(bits); break; + case 0x18: /* RCR */ set_cf((cpu_data & 1) != 0); cpu_data >>= 1; @@ -2286,12 +2344,14 @@ opcodestart: set_cf((cpu_dest & 1) != 0); set_of_rotate(bits); break; + case 0x20: /* SHL */ set_cf(top_bit(cpu_data, bits)); cpu_data <<= 1; set_of_rotate(bits); set_pzs(bits); break; + case 0x28: /* SHR */ set_cf((cpu_data & 1) != 0); cpu_data >>= 1; @@ -2299,6 +2359,7 @@ opcodestart: set_af(1); set_pzs(bits); break; + case 0x30: /* SETMO - undocumented? */ bitwise(bits, 0xffff); set_cf(0); @@ -2306,6 +2367,7 @@ opcodestart: set_af(0); set_pzs(bits); break; + case 0x38: /* SAR */ set_cf((cpu_data & 1) != 0); cpu_data >>= 1; @@ -2319,68 +2381,79 @@ opcodestart: break; } if ((opcode & 2) != 0) - wait(4, 0); + cpu_wait(4, 0); --cpu_src; } - access(17, bits); + do_access(17, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; - case 0xD4: /*AAM*/ - wait(1, 0); + case 0xd4: /*AAM*/ + cpu_wait(1, 0); cpu_src = pfq_fetchb(); - if (div(AL, 0)) + if (do_div(AL, 0)) set_pzs(16); break; - case 0xD5: /*AAD*/ - wait(1, 0); - mul(pfq_fetchb(), AH); + + case 0xd5: /*AAD*/ + cpu_wait(1, 0); + do_mul(pfq_fetchb(), AH); AL += cpu_data; AH = 0x00; set_pzs(16); break; - case 0xD6: /*SALC*/ - wait(1, 0); + + case 0xd6: /*SALC*/ + cpu_wait(1, 0); AL = (flags & C_FLAG) ? 0xff : 0x00; - wait(1, 0); - break; - case 0xD7: /*XLATB*/ - addr = BX + AL; - cpu_state.last_ea = addr; - access(4, 8); - AL = readmemb((ovr_seg ? *ovr_seg : ds) + addr); - wait(1, 0); + cpu_wait(1, 0); break; - case 0xD8: case 0xD9: case 0xDA: case 0xDB: - case 0xDD: case 0xDC: case 0xDE: case 0xDF: - /* esc i, r, rm */ + case 0xd7: /*XLATB*/ + do_addr = BX + AL; + cpu_state.last_ea = do_addr; + do_access(4, 8); + AL = readmemb((ovr_seg ? *ovr_seg : ds) + do_addr); + cpu_wait(1, 0); + break; + + case 0xd8: /* esc i, r, rm */ + case 0xd9: + case 0xda: + case 0xdb: + case 0xdd: + case 0xdc: + case 0xde: + case 0xdf: do_mod_rm(); - access(54, 16); + do_access(54, 16); geteaw(); - wait(1, 0); + cpu_wait(1, 0); if (cpu_mod != 3) - wait(2, 0); + cpu_wait(2, 0); break; - case 0xE0: case 0xE1: case 0xE2: case 0xE3: - /* LOOP */ - wait(3, 0); + case 0xe0: /* LOOP */ + case 0xe1: + case 0xe2: + case 0xe3: + cpu_wait(3, 0); cpu_data = pfq_fetchb(); if (opcode != 0xe2) - wait(1, 0); + cpu_wait(1, 0); if (opcode != 0xe3) { --CX; oldc = (CX != 0); switch (opcode) { - case 0xE0: + case 0xe0: if (flags & Z_FLAG) oldc = 0; break; - case 0xE1: + + case 0xe1: if (!(flags & Z_FLAG)) oldc = 0; break; @@ -2391,186 +2464,203 @@ opcodestart: jump_short(); break; - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - case 0xEC: case 0xED: case 0xEE: case 0xEF: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + case 0xec: + case 0xed: + case 0xee: + case 0xef: bits = 8 << (opcode & 1); if ((opcode & 0x0e) != 0x0c) - wait(1, 0); + cpu_wait(1, 0); if ((opcode & 8) == 0) cpu_data = pfq_fetchb(); else cpu_data = DX; if ((opcode & 2) == 0) { - access(3, bits); - if ((opcode & 1) && is8086) { + do_access(3, bits); + if ((opcode & 1) && is8086 && !(cpu_data & 1)) { AX = inw(cpu_data); - wait(4, 1); /* I/O access and wait state. */ + cpu_wait(4, 1); /* I/O do_access and wait state. */ } else { AL = inb(cpu_data); if (opcode & 1) AH = inb(temp + 1); - wait(bits >> 1, 1); /* I/O access. */ + cpu_wait(bits >> 1, 1); /* I/O do_access. */ } - wait(1, 0); + cpu_wait(1, 0); } else { if ((opcode & 8) == 0) - access(8, bits); + do_access(8, bits); else - access(9, bits); - if ((opcode & 1) && is8086) { + do_access(9, bits); + if ((opcode & 1) && is8086 && !(cpu_data & 1)) { outw(cpu_data, AX); - wait(4, 1); + cpu_wait(4, 1); } else { outb(cpu_data, AL); if (opcode & 1) outb(cpu_data + 1, AH); - wait(bits >> 1, 1); /* I/O access. */ + cpu_wait(bits >> 1, 1); /* I/O do_access. */ } } break; - case 0xE8: /*CALL rel 16*/ - wait(1, 0); + case 0xe8: /*CALL rel 16*/ + cpu_wait(1, 0); cpu_state.oldpc = jump_near(); - access(34, 8); - push(cpu_state.oldpc); + do_access(34, 8); + do_push(cpu_state.oldpc); pfq_clear(); break; - case 0xE9: /*JMP rel 16*/ - wait(1, 0); + + case 0xe9: /*JMP rel 16*/ + cpu_wait(1, 0); jump_near(); break; - case 0xEA: /*JMP far*/ - wait(1, 0); - addr = pfq_fetchw(); - wait(1, 0); + + case 0xea: /*JMP far*/ + cpu_wait(1, 0); + do_addr = pfq_fetchw(); + cpu_wait(1, 0); tempw = pfq_fetchw(); loadcs(tempw); - access(70, 8); - cpu_state.pc = addr; + do_access(70, 8); + cpu_state.pc = do_addr; pfq_clear(); break; - case 0xEB: /*JMP rel*/ - wait(1, 0); + + case 0xeb: /*JMP rel*/ + cpu_wait(1, 0); cpu_data = (int8_t) pfq_fetchb(); jump_short(); - wait(1, 0); + cpu_wait(1, 0); pfq_clear(); break; - case 0xF0: case 0xF1: /*LOCK - F1 is alias*/ + case 0xf0: /*LOCK - F1 is alias*/ + case 0xf1: in_lock = 1; - wait(1, 0); + cpu_wait(1, 0); goto opcodestart; - case 0xF2: /*REPNE*/ - case 0xF3: /*REPE*/ - wait(1, 0); + case 0xf2: /*REPNE*/ + case 0xf3: /*REPE*/ + cpu_wait(1, 0); in_rep = (opcode == 0xf2 ? 1 : 2); repeating = 0; completed = 0; goto opcodestart; - case 0xF4: /*HLT*/ + case 0xf4: /*HLT*/ halt = 1; pfq_clear(); - wait(2, 0); + cpu_wait(2, 0); break; - case 0xF5: /*CMC*/ - wait(1, 0); + + case 0xf5: /*CMC*/ + cpu_wait(1, 0); flags ^= C_FLAG; break; - case 0xF6: case 0xF7: + case 0xf6: + case 0xf7: bits = 8 << (opcode & 1); do_mod_rm(); - access(55, bits); + do_access(55, bits); if (opcode & 1) cpu_data = geteaw(); else cpu_data = geteab(); switch (rmdat & 0x38) { - case 0x00: case 0x08: - /* TEST */ - wait(2, 0); + case 0x00: /* TEST */ + case 0x08: + cpu_wait(2, 0); if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); if (opcode & 1) cpu_src = pfq_fetchw(); else cpu_src = pfq_fetchb(); - wait(1, 0); - test(bits, cpu_data, cpu_src); + cpu_wait(1, 0); + do_test(bits, cpu_data, cpu_src); if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); break; + case 0x10: /* NOT */ case 0x18: /* NEG */ - wait(2, 0); + cpu_wait(2, 0); if ((rmdat & 0x38) == 0x10) cpu_data = ~cpu_data; else { cpu_src = cpu_data; cpu_dest = 0; - sub(bits); + do_sub(bits); } - access(18, bits); + do_access(18, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; + case 0x20: /* MUL */ case 0x28: /* IMUL */ - wait(1, 0); + cpu_wait(1, 0); if (opcode & 1) { - mul(AX, cpu_data); + do_mul(AX, cpu_data); AX = cpu_data; DX = cpu_dest; cpu_data |= DX; set_co_mul((DX != ((AX & 0x8000) == 0) || ((rmdat & 0x38) == 0x20) ? 0 : 0xffff)); } else { - mul(AL, cpu_data); + do_mul(AL, cpu_data); AL = (uint8_t) cpu_data; AH = (uint8_t) cpu_dest; set_co_mul(AH != (((AL & 0x80) == 0) || ((rmdat & 0x38) == 0x20) ? 0 : 0xff)); } set_zf(bits); if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); break; + case 0x30: /* DIV */ case 0x38: /* IDIV */ if (cpu_mod != 3) - wait(1, 0); + cpu_wait(1, 0); cpu_src = cpu_data; - if (div(AL, AH)) - wait(1, 0); + if (do_div(AL, AH)) + cpu_wait(1, 0); break; } break; - case 0xF8: case 0xF9: - /* CLCSTC */ - wait(1, 0); + case 0xf8: /* CLCSTC */ + case 0xf9: + cpu_wait(1, 0); set_cf(opcode & 1); break; - case 0xFA: case 0xFB: - /* CLISTI */ - wait(1, 0); + + case 0xfa: /* CLISTI */ + case 0xfb: + cpu_wait(1, 0); set_if(opcode & 1); break; - case 0xFC: case 0xFD: - /* CLDSTD */ - wait(1, 0); + + case 0xfc: /* CLDSTD */ + case 0xfd: + cpu_wait(1, 0); set_df(opcode & 1); break; - case 0xFE: case 0xFF: - /* misc */ + case 0xfe: /* misc */ + case 0xff: bits = 8 << (opcode & 1); do_mod_rm(); - access(56, bits); + do_access(56, bits); read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); switch (rmdat & 0x38) { case 0x00: /* INC rm */ @@ -2586,13 +2676,14 @@ opcodestart: } do_af(); set_pzs(bits); - wait(2, 0); - access(19, bits); + cpu_wait(2, 0); + do_access(19, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; + case 0x10: /* CALL rm */ if (!(opcode & 1)) { if (cpu_mod != 3) @@ -2600,36 +2691,38 @@ opcodestart: else cpu_data = cpu_state.regs[cpu_rm].w; } - access(63, bits); - wait(5, 0); + do_access(63, bits); + cpu_wait(5, 0); if (cpu_mod != 3) - wait(1, 0); - wait(1, 0); /* Wait. */ + cpu_wait(1, 0); + cpu_wait(1, 0); /* Wait. */ cpu_state.oldpc = cpu_state.pc; cpu_state.pc = cpu_data; - wait(2, 0); - access(35, bits); - push(cpu_state.oldpc); + cpu_wait(2, 0); + do_access(35, bits); + do_push(cpu_state.oldpc); pfq_clear(); break; + case 0x18: /* CALL rmd */ new_ip = cpu_data; - access(58, bits); + do_access(58, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; - access(36, bits); - push(CS); - access(64, bits); - wait(4, 0); + do_access(36, bits); + do_push(CS); + do_access(64, bits); + cpu_wait(4, 0); cpu_state.oldpc = cpu_state.pc; loadcs(new_cs); cpu_state.pc = new_ip; - access(37, bits); - push(cpu_state.oldpc); + do_access(37, bits); + do_push(cpu_state.oldpc); pfq_clear(); break; + case 0x20: /* JMP rm */ if (!(opcode & 1)) { if (cpu_mod != 3) @@ -2637,31 +2730,33 @@ opcodestart: else cpu_data = cpu_state.regs[cpu_rm].w; } - access(65, bits); + do_access(65, bits); cpu_state.pc = cpu_data; pfq_clear(); break; + case 0x28: /* JMP rmd */ new_ip = cpu_data; - access(59, bits); + do_access(59, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; loadcs(new_cs); - access(66, bits); + do_access(66, bits); cpu_state.pc = new_ip; pfq_clear(); break; + case 0x30: /* PUSH rm */ case 0x38: if (cpu_mod != 3) - wait(1, 0); - access(38, bits); + cpu_wait(1, 0); + do_access(38, bits); if ((cpu_mod == 3) && (cpu_rm == 4)) - push(cpu_data - 2); + do_push(cpu_data - 2); else - push(cpu_data); + do_push(cpu_data); break; } break; @@ -2669,7 +2764,7 @@ opcodestart: default: ERRLOG("CPU: illegal opcode: %02X\n", opcode); pfq_fetchb(); - wait(8, 0); + cpu_wait(8, 0); break; } @@ -2695,16 +2790,16 @@ on_halt: if (trap && (flags & T_FLAG) && !noint) { halt = 0; - interrupt(1, 1); + do_intr(1, 1); } else if (nmi && nmi_enable && nmi_mask) { halt = 0; - interrupt(2, 1); + do_intr(2, 1); nmi_enable = 0; } else if (takeint && !noint) { temp = picinterrupt(); if (temp != 0xFF) { halt = 0; - interrupt(temp, 1); + do_intr(temp, 1); } } takeint = (flags & I_FLAG) && (pic.pend &~ pic.mask); @@ -2715,3 +2810,46 @@ on_halt: ins++; } } + + +/* Memory refresh read - called by reads and writes on DMA channel 0. */ +void +refreshread(void) +{ + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed > 4772728) + cpu_wait(8, 1); /* Insert extra wait states. */ + + /* Do the actual refresh stuff. */ + /* If there's no extra cycles left to consume, return. */ + if (!(fetchcycles & 3)) + return; + + /* If the prefetch queue is full, return. */ + if (pfq_pos >= pfq_size) + return; + + /* Subtract from 1 to 8 cycles. */ + cpu_wait(8 - (fetchcycles % 7), 1); + + /* Write to the prefetch queue. */ + pfq_write(); + + /* Add those cycles to fetchcycles. */ + fetchcycles += (4 - (fetchcycles & 3)); +} + + +/* Hard reset. */ +void +resetx86(void) +{ + reset_common(1); +} + + +/* Soft reset. */ +void +softresetx86(void) +{ + reset_common(0); +} diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index e8168c9..2c60074 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -8,15 +8,15 @@ * * CPU type handler. * - * Version: @(#)cpu.h 1.0.7 2018/09/19 + * Version: @(#)cpu.h 1.0.8 2019/02/11 * * Authors: Sarah Walker, * leilei, * Miran Grca, * + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. - * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -88,6 +88,7 @@ #define CPU_SUPPORTS_DYNAREC 1 #define CPU_REQUIRES_DYNAREC 2 +#define CPU_ALTERNATE_XTAL 4 typedef struct { diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 06c16ae..80fb164 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -8,11 +8,11 @@ * * Define all known processor types. * - * Version: @(#)cpu_table.c 1.0.6 2019/02/03 + * Version: @(#)cpu_table.c 1.0.7 2019/02/11 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, - * Fred N. van Kempen, + * Sarah Walker, * * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2019 Miran Grca. @@ -51,8 +51,9 @@ CPU cpus_8088[] = { {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/10", CPU_8088, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/12", CPU_8088, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/16", CPU_8088, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, #ifdef _DEBUG {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1}, #endif @@ -67,31 +68,29 @@ CPU cpus_pcjr[] = { CPU cpus_europc[] = { /*8088 EuroPC*/ - {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, {"", -1, 0, 0, 0, 0, 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, 0,0,0,0, 1}, + {"8086/7.16", CPU_8086, 1, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, + {"8086/9.54", CPU_8086, 1, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1}, + {"8086/10", CPU_8086, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/12", CPU_8086, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"8086/16", CPU_8086, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} }; CPU cpus_nec[] = { /*NEC V20/30 standard*/ - {"V20/7.16", CPU_NEC, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, {"V20/8", CPU_NEC, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/9.54", CPU_NEC, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/10", CPU_NEC, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/12", CPU_NEC, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"V20/16", CPU_NEC, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, + {"V20/10", CPU_NEC, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/12", CPU_NEC, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/16", CPU_NEC, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} }; diff --git a/src/devices/input/keyboard.h b/src/devices/input/keyboard.h index 1adf912..b222987 100644 --- a/src/devices/input/keyboard.h +++ b/src/devices/input/keyboard.h @@ -8,14 +8,14 @@ * * Definitions for the keyboard interface. * - * Version: @(#)keyboard.h 1.0.7 2018/09/28 + * Version: @(#)keyboard.h 1.0.8 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -82,12 +82,16 @@ extern const scancode scancode_xt[512]; #ifdef EMU_DEVICE_H extern const device_t keyboard_pc_device; +extern const device_t keyboard_pc82_device; extern const device_t keyboard_xt_device; -extern const device_t keyboard_xt_lxt3_device; +extern const device_t keyboard_xt86_device; extern const device_t keyboard_tandy_device; +extern const device_t keyboard_xt_lxt3_device; + extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; extern const device_t keyboard_at_toshiba_device; + extern const device_t keyboard_ps2_device; extern const device_t keyboard_ps2_xi8088_device; extern const device_t keyboard_ps2_ami_device; diff --git a/src/devices/input/keyboard_xt.c b/src/devices/input/keyboard_xt.c index a686ea9..41e6a79 100644 --- a/src/devices/input/keyboard_xt.c +++ b/src/devices/input/keyboard_xt.c @@ -8,7 +8,7 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.10 2019/02/10 + * Version: @(#)keyboard_xt.c 1.0.11 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,6 +50,7 @@ #include "../system/pic.h" #include "../system/pit.h" #include "../system/ppi.h" +#include "../floppy/fdd.h" #include "../sound/sound.h" #include "../sound/snd_speaker.h" #include "../video/video.h" @@ -70,8 +71,9 @@ typedef struct { uint8_t type; int8_t tandy; - uint8_t pa; - uint8_t pb; + uint8_t pa, + pb, + pd; int8_t want_irq; int8_t blocked; @@ -485,28 +487,14 @@ kbd_read(uint16_t port, void *priv) { xtkbd_t *kbd = (xtkbd_t *)priv; uint8_t ret = 0xff; - int vid; switch (port) { case 0x60: - if (kbd->pb & 0x80) switch(kbd->type) { - case 0: - vid = video_type(); - if (vid == VID_TYPE_SPEC) - ret = 0x4d; /* EGA/VGA */ - else if (vid == VID_TYPE_MDA) - ret = 0x7d; /* MDA/Herc */ - else - ret = 0x6d; /* CGA */ - break; - - case 1: - /* - * According to Ruud on the PCem forum, this - * is supposed to return 0xFF on the XT. - */ - ret = 0xff; - } else + if ((kbd->type <= 1) && (kbd->pb & 0x80)) + ret = kbd->pd; + else if (((kbd->type == 2) || (kbd->type == 3)) && (kbd->pb & 0x80)) + ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */ + else ret = kbd->pa; break; @@ -515,36 +503,39 @@ kbd_read(uint16_t port, void *priv) break; case 0x62: - if (kbd->type == 0) { + if (! kbd->type) + ret = 0x00; + else if (kbd->type == 1) { if (kbd->pb & 0x04) - ret = ((mem_size-64) / 32) & 0x0f; + ret = ((mem_size - 64) / 32) & 0x0f; else - ret = ((mem_size-64) / 32) >> 4; - } else if (kbd->pb & 0x08) { - vid = video_type(); - if (vid == VID_TYPE_SPEC) - ret = 0x4; /* EGA/VGA */ - else if (vid == VID_TYPE_MDA) - ret = 0x7; /* MDA/Hercules */ - else - ret = 0x6; /* CGA */ - } else { - /* LaserXT = Always 512k RAM; - LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ + ret = ((mem_size - 64) / 32) >> 4; + if (kbd->pb & 0x08) + ret = kbd->pd >> 4; + else { + /* LaserXT = Always 512k RAM; + * LaserXT/3 = Bit 0: 1=512K, 0=256K + */ #if defined(DEV_BRANCH) && defined(USE_LASERXT) - if (kbd->type == 3) - ret = (mem_size == 512) ? 0x0d : 0x0c; - else + if (kbd->type == 5) + ret = (mem_size == 512) ? 0x0d : 0x0c; + else #endif - ret = 0x0d; + ret = kbd->pd & 0x0f; + } } ret |= (ppispeakon ? 0x20 : 0); - if (kbd->type == 2) + if (kbd->type == 4) ret |= (tandy1k_eeprom_read() ? 0x10 : 0); break; + case 0x63: + if ((kbd->type == 2) || (kbd->type == 3)) + ret = kbd->pd; + break; + default: ERRLOG("XTkbd: bad read %04X\n", port); break; @@ -574,6 +565,7 @@ kbd_reset(void *priv) static void * kbd_init(const device_t *info) { + int i, fdd_count = 0; xtkbd_t *kbd; kbd = (xtkbd_t *)mem_alloc(sizeof(xtkbd_t)); @@ -586,6 +578,101 @@ kbd_init(const device_t *info) kbd_reset(kbd); kbd->type = info->local; + if (kbd->type <= 3) { + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + + /* + * DIP switch readout: bit set = OFF, clear = ON. + * + * Switches 7, 8 - floppy drives. + */ + if (fdd_count == 0) + kbd->pd = 0x00; + else + kbd->pd = ((fdd_count - 1) << 6); + + /* Switches 5, 6 - video. */ + i = video_type(); + if (i == VID_TYPE_MDA) + kbd->pd |= 0x30; /* MDA/Herc */ +#if 0 + else if (i == VID_TYPE_CGA40) + kbd->pd |= 0x10; /* CGA, 40 columns */ +#endif + else if (i == VID_TYPE_CGA) + kbd->pd |= 0x20; /* CGA, 80 colums */ + else if (i == VID_TYPE_SPEC) + kbd->pd |= 0x00; /* EGA/VGA */ + + /* Switches 3, 4 - memory size. */ + if (kbd->type == 3) { + switch (mem_size) { + case 256: + kbd->pd |= 0x00; + break; + + case 512: + kbd->pd |= 0x04; + break; + + case 576: + kbd->pd |= 0x08; + break; + + case 640: + default: + kbd->pd |= 0x0c; + break; + } + } else if (kbd->type == 2) { + switch (mem_size) { + case 64: + kbd->pd |= 0x00; + break; + + case 128: + kbd->pd |= 0x04; + break; + + case 192: + kbd->pd |= 0x08; + break; + case 256: + default: + + kbd->pd |= 0x0c; + break; + } + } else { + switch (mem_size) { + case 16: + kbd->pd |= 0x00; + break; + + case 32: + kbd->pd |= 0x04; + break; + + case 48: + kbd->pd |= 0x08; + break; + + case 64: + default: + kbd->pd |= 0x0c; + break; + } + } + + /* Switch 2 - return bit clear (switch ON) because no 8087 right now. */ + + /* Switch 1 - always off. */ + kbd->pd |= 0x01; + } + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, kbd); keyboard_set_table(scancode_xt); @@ -615,7 +702,7 @@ kbd_close(void *priv) const device_t keyboard_pc_device = { - "IBM PC Keyboard", + "IBM PC (1981) Keyboard", 0, 0, kbd_init, kbd_close, kbd_reset, @@ -623,8 +710,8 @@ const device_t keyboard_pc_device = { NULL }; -const device_t keyboard_xt_device = { - "IBM PC/XT Keyboard", +const device_t keyboard_pc82_device = { + "IBM PC (1982) Keyboard", 0, 1, kbd_init, kbd_close, kbd_reset, @@ -632,10 +719,28 @@ const device_t keyboard_xt_device = { NULL }; +const device_t keyboard_xt_device = { + "IBM PC/XT (1982) Keyboard", + 0, + 2, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t keyboard_xt86_device = { + "IBM PC/XT (1986) Keyboard", + 0, + 3, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; + const device_t keyboard_tandy_device = { "Tandy 1000 Keyboard", 0, - 2, + 4, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -644,7 +749,11 @@ const device_t keyboard_tandy_device = { const device_t keyboard_xt_lxt3_device = { "VTech Laser XT3 Keyboard", 0, +#if 1 3, +#else + 5, +#endif kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/sound/snd_opl.c b/src/devices/sound/snd_opl.c index 4dfbd33..00f09ac 100644 --- a/src/devices/sound/snd_opl.c +++ b/src/devices/sound/snd_opl.c @@ -8,15 +8,15 @@ * * Interface to the actual OPL emulator. * - * Version: @(#)snd_opl.c 1.0.4 2018/10/16 + * Version: @(#)snd_opl.c 1.0.5 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * TheCollector1995, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -56,7 +56,7 @@ uint8_t opl2_read(uint16_t a, void *priv) { opl_t *opl = (opl_t *)priv; - cycles -= (int)(isa_timing * 8); + cycles -= ISA_CYCLES(8); opl2_update2(opl); return opl_read(0, a); } @@ -73,7 +73,7 @@ uint8_t opl2_l_read(uint16_t a, void *priv) { opl_t *opl = (opl_t *)priv; - cycles -= (int)(isa_timing * 8); + cycles -= ISA_CYCLES(8); opl2_update2(opl); return opl_read(0, a); } @@ -89,7 +89,7 @@ uint8_t opl2_r_read(uint16_t a, void *priv) { opl_t *opl = (opl_t *)priv; - cycles -= (int)(isa_timing * 8); + cycles -= ISA_CYCLES(8); opl2_update2(opl); return opl_read(1, a); } @@ -105,7 +105,7 @@ uint8_t opl3_read(uint16_t a, void *priv) { opl_t *opl = (opl_t *)priv; - cycles -= (int)(isa_timing * 8); + cycles -= ISA_CYCLES(8); opl3_update2(opl); return opl_read(0, a); } diff --git a/src/devices/system/dma.c b/src/devices/system/dma.c index 17d2b5f..5bdf7ec 100644 --- a/src/devices/system/dma.c +++ b/src/devices/system/dma.c @@ -8,7 +8,7 @@ * * Implementation of the Intel DMA controllers. * - * Version: @(#)dma.c 1.0.7 2019/02/10 + * Version: @(#)dma.c 1.0.8 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -748,7 +748,7 @@ dma_channel_read(int channel) if ((dma_c->mode & 0xC) != 8) return(DMA_NODATA); - if (!AT && !channel) + if (! AT) refreshread(); if (! dma_c->size) { @@ -819,7 +819,7 @@ dma_channel_write(int channel, uint16_t val) if ((dma_c->mode & 0xC) != 4) return(DMA_NODATA); - if (!AT && !channel) + if (! AT) refreshread(); if (! dma_c->size) { diff --git a/src/devices/system/pit.c b/src/devices/system/pit.c index aa8a314..217187c 100644 --- a/src/devices/system/pit.c +++ b/src/devices/system/pit.c @@ -13,7 +13,7 @@ * B4 to 40, two writes to 43, then two reads * - value _does_ change! * - * Version: @(#)pit.c 1.0.8 2019/02/10 + * Version: @(#)pit.c 1.0.9 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -67,7 +67,7 @@ int firsttime = 1; PIT pit, pit2; float cpuclock; -float isa_timing, bus_timing; +float bus_timing; double PITCONST; float CGACONST; float MDACONST; @@ -636,60 +636,84 @@ pit_reset(PIT *dev) } +/* Set default CPU/crystal clock and xt_cpu_multi. */ void setrtcconst(float clock) { - RTCCONST = clock / (float)32768.0; + cpuclock = 14318184.0; - TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1LL << TIMER_SHIFT)); + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) { + cpuclock = clock; + PITCONST = cpuclock / 1193182.0; + CGACONST = (float) (cpuclock / (19687503.0 / 11.0)); + xt_cpu_multi = 1; + } else { + PITCONST = 12.0; + CGACONST = 8.0; + xt_cpu_multi = 3; + + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed) { + case 7159092: /* 7.16 MHz */ + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_flags & CPU_ALTERNATE_XTAL) { + cpuclock = 28636368.0; + xt_cpu_multi = 4; + } else + xt_cpu_multi = 2; + break; + + case 8000000: /* 8 MHz */ + cpuclock = 24000000.0; + break; + + case 9545456: /* 9.54 MHz */ + cpuclock = 28636368.0; + break; + + case 10000000: /* 10 MHz */ + cpuclock = 30000000.0; + break; + + case 12000000: /* 12 MHz */ + cpuclock = 36000000.0; + break; + + case 16000000: /* 16 MHz */ + cpuclock = 48000000.0; + break; + + default: + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_flags & CPU_ALTERNATE_XTAL) { + cpuclock = 28636368.0; + xt_cpu_multi = 6; + } + break; + } + + if (cpuclock == 28636368.0) { + PITCONST = 24.0; + CGACONST = 16.0; + } else if (cpuclock != 14318184.0) { + PITCONST = cpuclock / 1193182.0; + CGACONST = (float) (cpuclock / (19687503.0 / 11.0)); + } + } + + xt_cpu_multi <<= TIMER_SHIFT; + + MDACONST = (float) (cpuclock / 2032125.0); + VGACONST1 = (float) (cpuclock / 25175000.0); + VGACONST2 = (float) (cpuclock / 28322000.0); + RTCCONST = (float) (cpuclock / 32768.0); + TIMER_USEC = (int64_t)((cpuclock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); + bus_timing = (float) (cpuclock / (double)cpu_busspeed); } void setpitclock(float clock) { - /* - * Some calculations are done differently for 4.77 MHz, 7.16 MHz, - * and 9.54 MHz CPU's, so that loss of precision is avoided and - * the various component kept in better synchronization. - */ - cpuclock = clock; - - if (clock == 4772728.0) { - PITCONST = 4.0; - CGACONST = (float)(8.0 / 3.0); - } else if (clock == 7159092.0) { - /* 7.16 MHz - simplify the calculation to avoid loss of precision. */ - PITCONST = 6.0; - CGACONST = 4.0; - } else if (clock == 9545456.0) { - /* 9.54 MHz - simplify the calculation to avoid loss of precision. */ - PITCONST = 8.0; - CGACONST = (float)(8.0 / 1.5); - } else { - PITCONST = clock / 1193182.0; - CGACONST = (float)(clock / (19687503.0 / 11.0)); - } - - MDACONST = (clock / 2032125.0f); - VGACONST1 = (clock / 25175000.0f); - VGACONST2 = (clock / 28322000.0f); - - isa_timing = clock / 8000000.0f; - bus_timing = clock / (float)cpu_busspeed; - video_update_timing(); - if (clock == 4772728.0) { - xt_cpu_multi = (int) (3 * (1 << TIMER_SHIFT)); - } else if (clock == 7159092.0) { - xt_cpu_multi = (int) (2 * (1 << TIMER_SHIFT)); - } else if (clock == 9545456.0) { - xt_cpu_multi = (int) (1.5*(double)(1 << TIMER_SHIFT)); - } else { - xt_cpu_multi = (int) ((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - } - device_speed_changed(); } @@ -735,6 +759,39 @@ pit_set_gate(PIT *dev, int t, int gate) } +static int64_t +pit_read_timer_ex(PIT *pit, int t) +{ + int64_t r; + + timer_clock(); + + if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t])) { + r = (int)(pit->c[t] + ((1 << TIMER_SHIFT) - 1)); + if (pit->m[t] == 2) + r += (int64_t)((1LL << TIMER_SHIFT) * PITCONST); + if (r < 0) + r = 0; + if (r > ((0x10000LL << TIMER_SHIFT) * PITCONST)) + r = (int64_t)((0x10000LL << TIMER_SHIFT) * PITCONST); + if (pit->m[t] == 3) + r <<= 1; + + return r; + } + + if (pit->m[t] == 2) { + r = (int64_t) (((pit->count[t] + 1LL) << TIMER_SHIFT) * PITCONST); + + return r; + } + + r = (int64_t) ((pit->count[t] << TIMER_SHIFT) * PITCONST); + + return r; +} + + void pit_set_using_timer(PIT *dev, int t, int using_timer) { @@ -742,8 +799,9 @@ pit_set_using_timer(PIT *dev, int t, int using_timer) if (dev->using_timer[t] && !using_timer) dev->count[t] = pit_read_timer(dev, t); + if (!dev->using_timer[t] && using_timer) - dev->c[t] = (int64_t)((((int64_t) dev->count[t]) << TIMER_SHIFT) * PITCONST); + dev->c[t] = pit_read_timer_ex(dev, t); dev->using_timer[t] = using_timer; dev->running[t] = dev->enabled[t] && diff --git a/src/devices/video/vid_hercules.c b/src/devices/video/vid_hercules.c index 55a6a3f..da58be4 100644 --- a/src/devices/video/vid_hercules.c +++ b/src/devices/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.12 2019/02/10 + * Version: @(#)vid_hercules.c 1.0.13 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,6 +43,7 @@ #include #include "../../emu.h" #include "../../io.h" +#include "../../cpu/cpu.h" #include "../../mem.h" #include "../../rom.h" #include "../../timer.h" @@ -89,6 +90,9 @@ typedef struct { } hercules_t; +static const int ws_array[16] = {3,4,5,6,7,8,4,5,6,7,8,4,5,6,7,8}; + + static void recalc_timings(hercules_t *dev) { @@ -110,6 +114,7 @@ static void hercules_out(uint16_t addr, uint8_t val, void *priv) { hercules_t *dev = (hercules_t *)priv; + uint8_t old; switch (addr) { case 0x03b0: @@ -123,6 +128,7 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) case 0x03b3: case 0x03b5: case 0x03b7: + old = dev->crtc[dev->crtcreg]; dev->crtc[dev->crtcreg] = val; /* @@ -133,11 +139,16 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) dev->crtc[10] = 0xb; dev->crtc[11] = 0xc; } - recalc_timings(dev); + + if (old ^ val) + recalc_timings(dev); break; case 0x03b8: + old = dev->ctrl; dev->ctrl = val; + if (old ^ val) + recalc_timings(dev); break; case 0x03bf: @@ -176,7 +187,9 @@ hercules_in(uint16_t addr, void *priv) break; case 0x03ba: - ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4); + ret = 0x72; /* Hercules ident */ + if (dev->stat & 0x08) + ret |= 0x88; break; default: @@ -187,12 +200,24 @@ hercules_in(uint16_t addr, void *priv) } +static void +hercules_waitstates(void *p) +{ + int ws; + + ws = ws_array[cycles & 0xf]; + + cycles -= ws; +} + + static void hercules_write(uint32_t addr, uint8_t val, void *priv) { hercules_t *dev = (hercules_t *)priv; dev->vram[addr & 0xffff] = val; + hercules_waitstates(dev); } @@ -201,6 +226,8 @@ hercules_read(uint32_t addr, void *priv) { hercules_t *dev = (hercules_t *)priv; + hercules_waitstates(dev); + return(dev->vram[addr & 0xffff]); } @@ -239,7 +266,10 @@ hercules_poll(void *priv) ca += 0x8000; for (x = 0; x < dev->crtc[1]; x++) { - dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; + if (dev->ctrl & 8) + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; + else + dat = 0; dev->ma++; for (c = 0; c < 16; c++) { buffer->line[dev->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; @@ -253,8 +283,11 @@ hercules_poll(void *priv) } } else { for (x = 0; x < dev->crtc[1]; x++) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + if (dev->ctrl & 8) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + } else + chr = attr = 0; drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); @@ -289,9 +322,6 @@ hercules_poll(void *priv) } else { dev->vidtime += dev->dispontime; - if (dev->dispon) - dev->stat &= ~1; - dev->linepos = 0; if (dev->vsynctime) { dev->vsynctime--; @@ -349,7 +379,8 @@ hercules_poll(void *priv) x = dev->crtc[1] * 9; dev->lastline++; - if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + if ((dev->ctrl & 8) && + ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { xsize = x; ysize = dev->lastline - dev->firstline; if (xsize < 64) xsize = 656; @@ -382,6 +413,9 @@ hercules_poll(void *priv) dev->ma = dev->maback; } + if (dev->dispon) + dev->stat &= ~1; + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) dev->con = 1; diff --git a/src/devices/video/vid_herculesplus.c b/src/devices/video/vid_herculesplus.c index 72df006..e22e345 100644 --- a/src/devices/video/vid_herculesplus.c +++ b/src/devices/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_hercules_plus.c 1.0.13 2019/02/10 + * Version: @(#)vid_hercules_plus.c 1.0.14 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -131,20 +131,22 @@ static void herculesplus_out(uint16_t port, uint8_t val, void *priv) { herculesplus_t *dev = (herculesplus_t *)priv; + uint8_t old; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: dev->crtcreg = val & 31; return; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: if (dev->crtcreg > 22) return; + old = dev->crtc[dev->crtcreg]; dev->crtc[dev->crtcreg] = val; if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { /*Fix for Generic Turbo XT BIOS, @@ -152,21 +154,25 @@ herculesplus_out(uint16_t port, uint8_t val, void *priv) dev->crtc[10] = 0xb; dev->crtc[11] = 0xc; } - recalc_timings(dev); + if (old ^ val) + recalc_timings(dev); return; - case 0x3b8: + case 0x03b8: + old = dev->ctrl; dev->ctrl = val; + if (old ^ val) + recalc_timings(dev); return; - case 0x3bf: + case 0x03bf: dev->ctrl2 = val; if (val & 2) mem_map_set_addr(&dev->mapping, 0xb0000, 0x10000); else mem_map_set_addr(&dev->mapping, 0xb0000, 0x08000); return; - } + } } @@ -177,22 +183,22 @@ herculesplus_in(uint16_t port, void *priv) uint8_t ret = 0xff; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: ret = dev->crtcreg; break; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: if (dev->crtcreg <= 22) ret = dev->crtc[dev->crtcreg]; break; - case 0x3ba: + case 0x03ba: /* 0x50: InColor card identity */ ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; break; @@ -432,8 +438,11 @@ text_line(herculesplus_t *dev, uint16_t ca) uint32_t col; for (x = 0; x < dev->crtc[1]; x++) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + if (dev->ctrl & 8) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + } else + chr = attr = 0; drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); @@ -477,8 +486,11 @@ graphics_line(herculesplus_t *dev) ca += 0x8000; for (x = 0; x < dev->crtc[1]; x++) { - val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) - | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + if (dev->ctrl & 8) + val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) + | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + else + val = 0; dev->ma++; for (c = 0; c < 16; c++) { @@ -579,9 +591,10 @@ herculesplus_poll(void *priv) if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) x = dev->crtc[1] << 4; else - x = dev->crtc[1] * 9; + x = dev->crtc[1] * 9; dev->lastline++; - if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + if ((dev->ctrl & 8) && + ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { xsize = x; ysize = dev->lastline - dev->firstline; if (xsize < 64) xsize = 656; diff --git a/src/devices/video/vid_incolor.c b/src/devices/video/vid_incolor.c index 049bb34..835f5bc 100644 --- a/src/devices/video/vid_incolor.c +++ b/src/devices/video/vid_incolor.c @@ -8,14 +8,14 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.11 2018/11/11 + * Version: @(#)vid_incolor.c 1.0.12 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -227,22 +227,27 @@ static void incolor_out(uint16_t port, uint8_t val, void *priv) { incolor_t *dev = (incolor_t *)priv; + uint8_t old; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: dev->crtcreg = val & 31; return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: if (dev->crtcreg > 28) return; /* Palette load register */ if (dev->crtcreg == INCOLOR_CRTC_PALETTE) { dev->palette[dev->palette_idx % 16] = val; ++dev->palette_idx; } + old = dev->crtc[dev->crtcreg]; dev->crtc[dev->crtcreg] = val; if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { @@ -251,14 +256,18 @@ incolor_out(uint16_t port, uint8_t val, void *priv) dev->crtc[10] = 0xb; dev->crtc[11] = 0xc; } - recalc_timings(dev); + if (old ^ val) + recalc_timings(dev); return; - case 0x3b8: + case 0x03b8: + old = dev->ctrl; dev->ctrl = val; + if (old ^ val) + recalc_timings(dev); return; - case 0x3bf: + case 0x03bf: dev->ctrl2 = val; if (val & 2) mem_map_set_addr(&dev->mapping, 0xb0000, 0x10000); @@ -276,24 +285,24 @@ incolor_in(uint16_t port, void *priv) uint8_t ret = 0xff; switch (port) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: ret = dev->crtcreg; break; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: if (dev->crtcreg > 28) break; dev->palette_idx = 0; /* Read resets the palette index */ ret = dev->crtc[dev->crtcreg]; break; - case 0x3ba: + case 0x03ba: /* 0x50: InColor card identity */ ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50; break; @@ -812,8 +821,11 @@ text_line(incolor_t *dev, uint16_t ca) uint32_t col; for (x = 0; x < dev->crtc[1]; x++) { - chr = dev->vram[(dev->ma << 1) & 0xfff]; - attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + if (dev->ctrl & 8) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + } else + chr = attr = 0; drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); @@ -877,24 +889,26 @@ graphics_line(incolor_t *dev) for (x = 0; x < dev->crtc[1]; x++) { mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ - for (plane = 0; plane < 4; plane++, mask = mask >> 1) - { - if (mask & 1) - val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | - dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; - else val[plane] = 0; + for (plane = 0; plane < 4; plane++, mask = mask >> 1) { + if (dev->ctrl & 8) { + if (mask & 1) + val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + else val[plane] = 0; + } else + val[plane] = 0; } dev->ma++; - for (c = 0; c < 16; c++) - { + for (c = 0; c < 16; c++) { ink = 0; - for (plane = 0; plane < 4; plane++) - { + + for (plane = 0; plane < 4; plane++) { ink = ink >> 1; if (val[plane] & 0x8000) ink |= 8; val[plane] = val[plane] << 1; } + /* Is palette in use? */ if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) col = dev->palette[ink]; @@ -993,7 +1007,8 @@ incolor_poll(void *priv) else x = dev->crtc[1] * 9; dev->lastline++; - if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + if ((dev->ctrl & 8) && + ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) { xsize = x; ysize = dev->lastline - dev->firstline; if (xsize < 64) xsize = 656; diff --git a/src/machines/m_europc.c b/src/machines/m_europc.c index d2c167c..9c021e1 100644 --- a/src/machines/m_europc.c +++ b/src/machines/m_europc.c @@ -69,7 +69,7 @@ * FIXME: Find a new way to handle the switching of color/mono on * external cards. New video_get_type(int card) function? * - * Version: @(#)m_europc.c 1.0.17 2018/10/05 + * Version: @(#)m_europc.c 1.0.18 2019/02/11 * * Author: Fred N. van Kempen, * @@ -78,7 +78,7 @@ * Schneider's schematics and technical manuals, and the * input from people with real EuroPC hardware. * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -122,6 +122,7 @@ #include "../rom.h" #include "../device.h" #include "../nvr.h" +#include "../devices/system/pit.h" #include "../devices/system/nmi.h" #include "../devices/ports/parallel.h" #include "../devices/input/keyboard.h" @@ -779,6 +780,8 @@ machine_europc_init(const machine_t *model, void *arg) { machine_common_init(model, arg); + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + nmi_init(); /* Clear the machine state. */ diff --git a/src/machines/m_xt.c b/src/machines/m_xt.c index dd3cf49..2e7608f 100644 --- a/src/machines/m_xt.c +++ b/src/machines/m_xt.c @@ -8,14 +8,14 @@ * * Implementation of standard IBM PC/XT class machine. * - * Version: @(#)m_xt.c 1.0.11 2018/09/15 + * Version: @(#)m_xt.c 1.0.12 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -75,8 +75,9 @@ static const device_config_t pcxt_config[] = { }; +/* Generic PC/XT system board with just the basics. */ void -machine_pc_init(const machine_t *model, void *arg) +machine_pc_common_init(const machine_t *model, void *arg) { machine_common_init(model, arg); @@ -90,34 +91,49 @@ machine_pc_init(const machine_t *model, void *arg) pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_pc_device); - device_add(&fdc_xt_device); nmi_init(); } +/* The original IBM PC, 1981 model. */ +void +machine_pc_init(const machine_t *model, void *arg) +{ + machine_pc_common_init(model, arg); + + device_add(&keyboard_pc_device); +} + + +/* The later IBM PC from 1982. */ +void +machine_pc82_init(const machine_t *model, void *arg) +{ + machine_pc_common_init(model, arg); + + device_add(&keyboard_pc82_device); +} + + +/* The original IBM PC/XT, 1982 model. */ void machine_xt_init(const machine_t *model, void *arg) { - machine_common_init(model, arg); - - /* Check if we support a BASIC ROM. */ - if (model->device != NULL) { - DEBUG("This (%s) machine supports a BASIC ROM.\n", model->name); - - rom_basic = machine_get_config_int("rom_basic"); - DEBUG("ROM BASIC is currently %sabled.\n", (rom_basic)?"en":"dis"); - } - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + machine_pc_common_init(model, arg); device_add(&keyboard_xt_device); +} - device_add(&fdc_xt_device); - nmi_init(); +/* The later IBM PC/XT from 1986. */ +void +machine_xt86_init(const machine_t *model, void *arg) +{ + machine_pc_common_init(model, arg); + + device_add(&keyboard_xt86_device); } diff --git a/src/machines/m_xt_laserxt.c b/src/machines/m_xt_laserxt.c index f47c141..7cf9787 100644 --- a/src/machines/m_xt_laserxt.c +++ b/src/machines/m_xt_laserxt.c @@ -8,13 +8,13 @@ * * Emulation of the Laser XT series of machines. * - * Version: @(#)m_xt_laserxt.c 1.0.7 2018/09/19 + * Version: @(#)m_xt_laserxt.c 1.0.8 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -54,9 +54,6 @@ #include "machine.h" -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - - static int ems_page[4]; static int ems_control[4]; static mem_map_t ems_mapping[4]; @@ -223,6 +220,3 @@ machine_xt_lxt3_init(const machine_t *model, void *arg) laserxt_init(1); } - - -#endif /*defined(DEV_BRANCH) && defined(USE_LASERXT)*/ diff --git a/src/machines/machine.h b/src/machines/machine.h index f79b768..9839ddd 100644 --- a/src/machines/machine.h +++ b/src/machines/machine.h @@ -8,14 +8,14 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.25 2018/11/02 + * Version: @(#)machine.h 1.0.26 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -232,7 +232,9 @@ extern int tandy1k_eeprom_read(void); extern void machine_zenith_supersport_init(const machine_t *, void *); extern void machine_pc_init(const machine_t *, void *); +extern void machine_pc82_init(const machine_t *, void *); extern void machine_xt_init(const machine_t *, void *); +extern void machine_xt86_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_pc_device; extern const device_t m_xt_device; @@ -240,10 +242,8 @@ extern const device_t m_xt_device; extern void machine_xt_compaq_p1_init(const machine_t *, void *); -#if defined(DEV_BRANCH) && defined(USE_LASERXT) extern void machine_xt_laserxt_init(const machine_t *, void *); extern void machine_xt_lxt3_init(const machine_t *, void *); -#endif extern void machine_xt_t1000_init(const machine_t *, void *); #ifdef EMU_DEVICE_H diff --git a/src/machines/machine_table.c b/src/machines/machine_table.c index 13609d4..5d0771c 100644 --- a/src/machines/machine_table.c +++ b/src/machines/machine_table.c @@ -8,14 +8,14 @@ * * Handling of the emulated machines. * - * Version: @(#)machine_table.c 1.0.31 2019/01/13 + * Version: @(#)machine_table.c 1.0.32 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * * Copyright 2017,2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -63,9 +63,11 @@ const machine_t machines[] = { /* 8088 */ - { "[8088] IBM PC", "ibm_pc", L"ibm/pc", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_pc_init, &m_pc_device, NULL }, + { "[8088] IBM PC (1981)", "ibm_pc", L"ibm/pc", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 16, 256, 16, 0, machine_pc_init, &m_pc_device, NULL }, + { "[8088] IBM PC (1982)", "ibm_pc82", L"ibm/pc82", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_pc82_init, &m_pc_device, NULL }, { "[8088] IBM PCjr", "ibm_pcjr", L"ibm/pcjr", {{"Intel", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, &m_pcjr_device, NULL }, - { "[8088] IBM XT", "ibm_xt", L"ibm/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] IBM XT (1982)", "ibm_xt", L"ibm/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] IBM XT (1986)", "ibm_xt86", L"ibm/xt86", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt86_init, &m_xt_device, NULL }, { "[8088] AMI XT (generic)", "ami_xt", L"generic/xt/ami", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, { "[8088] Award XT (generic)", "awd_xt", L"generic/xt/award", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, @@ -77,12 +79,10 @@ const machine_t machines[] = { { "[8088] DTK XT", "dtk_xt", L"dtk/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, { "[8088] Juko XT", "juko_pc", L"juko/pc", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, { "[8088] Schneider EuroPC", "schneider_europc", L"schneider/europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 16, machine_europc_init, NULL, NULL }, - { "[8088] Tandy 1000", "tandy_1000", L"tandy/t1000", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_tandy1k_init, &m_tandy1k_device, NULL }, - { "[8088] Tandy 1000 HX", "tandy_1000hx", L"tandy/t1000hx", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 256, 640, 128, 0, machine_tandy1k_hx_init, &m_tandy1k_hx_device, NULL }, + { "[8088] Tandy 1000", "tandy_1000", L"tandy/t1000", {{"Intel", cpus_europc}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_tandy1k_init, &m_tandy1k_device, NULL }, + { "[8088] Tandy 1000 HX", "tandy_1000hx", L"tandy/t1000hx", {{"Intel", cpus_europc}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 256, 640, 128, 0, machine_tandy1k_hx_init, &m_tandy1k_hx_device, NULL }, { "[8088] Toshiba T1000", "toshiba_t1000", L"toshiba/t1000", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 64, machine_xt_t1000_init, &m_xt_t1000_device, machine_xt_t1x00_close }, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8088] VTech Laser Turbo XT", "vtech_ltxt", L"vtech/ltxt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, -#endif + { "[8088] VTech Laser Turbo XT", "vtech_ltxt", L"vtech/ltxt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 256, 0, machine_xt_laserxt_init, NULL, NULL }, { "[8088] Xi8088", "malinov_xi8088", L"malinov/xi8088", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA /*| MACDHINE_AT*/ | MACHINE_PS2, 64, 1024, 128, 128, machine_xt_xi8088_init, NULL, NULL }, { "[8088] Zenith Data SupersPORT", "zenith_supersport", L"zenith/supersport", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 128, 640, 128, 0, machine_zenith_supersport_init, NULL, NULL }, @@ -95,9 +95,7 @@ const machine_t machines[] = { { "[8086] Olivetti M24", "olivetti_m24", L"olivetti/m24", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL, NULL }, { "[8086] Tandy 1000 SL/2", "tandy_1000sl2", L"tandy/t1000sl2", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_sl2_init, &m_tandy1k_sl2_device, NULL }, { "[8086] Toshiba T1200", "toshiba_t1200", L"toshiba/t1200", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_HDC, 1024, 2048,1024, 64, machine_xt_t1200_init, &t1200_video_device, machine_xt_t1x00_close }, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8086] VTech Laser XT3", "vtech_lxt3", L"vtech/lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_lxt3_init, NULL, NULL }, -#endif + { "[8086] VTech Laser XT3", "vtech_lxt3", L"vtech/lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 256, 0, machine_xt_lxt3_init, NULL, NULL }, /* 80286 */ { "[286 ISA] IBM AT", "ibm_at", L"ibm/at", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 64, machine_at_ibm_init, NULL, NULL }, diff --git a/src/pc.c b/src/pc.c index c49f82a..2dc91bb 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,14 +8,14 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.63 2019/01/27 + * Version: @(#)pc.c 1.0.64 2019/02/11 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -738,10 +738,7 @@ usage: void pc_set_speed(void) { - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) - setpitclock((float)machine_speed()); - else - setpitclock(14318184.0); + setpitclock((float)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); } diff --git a/src/ui/lang/VARCem.str b/src/ui/lang/VARCem.str index 660020a..229e991 100644 --- a/src/ui/lang/VARCem.str +++ b/src/ui/lang/VARCem.str @@ -13,11 +13,11 @@ * it as the line-by-line base for the translated version, and * update fields as needed. * - * Version: @(#)VARCem.str 1.0.13 2018/10/18 + * Version: @(#)VARCem.str 1.0.14 2019/02/11 * * Author: Fred N. van Kempen, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -307,10 +307,10 @@ #define STR_3908 "&Notify disk change" #define STR_3910 "Floppy %i (%s): %ls" -#define STR_3911 "All images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0All files\0*.*\0" -#define STR_3912 "All images\0*.86f;*.ddi;*.dsk;*.flp;*.im?;*.*fd?\0Basic sector images\0*.ddi;*.dsk;*.flp;*.im?;*.img;*.*fd?\0Surface images\0*.86f\0" -#define STR_3913 "Surface images\0*.86f\0" -#define STR_3914 "E&xport to 86F..." +#define STR_3911 "All images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.json;*.mfm;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.mfm;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f;*.mfm\0All files\0*.*\0" +#define STR_3912 "All images\0*.86f;*.ddi;*.dsk;*.flp;*.im?;*.mfm;*.*fd?\0Basic sector images\0*.ddi;*.dsk;*.flp;*.im?;*.img;*.*fd?\0Surface images\0*.86f;*.mfm\0" +#define STR_3913 "Surface images\0*.86f;*.mfm\0" +#define STR_3914 "E&xport to ..." #define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Host CD/DVD Drive (%c:)" diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index db8c061..691f491 100644 --- a/src/win/mingw/Makefile.MinGW +++ b/src/win/mingw/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.74 2019/02/10 +# Version: @(#)Makefile.mingw 1.0.75 2019/02/11 # # Author: Fred N. van Kempen, # @@ -119,9 +119,6 @@ endif ifndef AMD_K AMD_K := n endif -ifndef LASERXT - LASERXT := n -endif ifndef PORTABLE3 PORTABLE3 := n endif @@ -182,7 +179,6 @@ ifeq ($(DEV_BUILD), y) CRASHDUMP := y DEV_BRANCH := y AMD_K := y - LASERXT := y PORTABLE3 := y I686 := y PAS16 := y @@ -540,11 +536,6 @@ ifeq ($(DEV_BRANCH), y) OPTS += -DUSE_AMD_K endif - ifeq ($(LASERXT), y) - OPTS += -DUSE_LASERXT - DEVBROBJ += m_xt_laserxt.o - endif - ifeq ($(PORTABLE3), y) OPTS += -DUSE_PORTABLE3 endif @@ -616,7 +607,7 @@ CPUOBJ := cpu.o cpu_table.o \ MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ m_xt_t1000.o m_xt_t1000_vid.o \ - m_xt_xi8088.o \ + m_xt_laserxt.o m_xt_xi8088.o \ m_zenith.o \ m_pcjr.o \ m_amstrad.o m_europc.o \ diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index b35c7a9..236fd77 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.60 2019/02/10 +# Version: @(#)Makefile.VC 1.0.61 2019/02/11 # # Author: Fred N. van Kempen, # @@ -120,9 +120,6 @@ endif ifndef AMD_K AMD_K := n endif -ifndef LASERXT - LASERXT := n -endif ifndef PORTABLE3 PORTABLE3 := n endif @@ -182,7 +179,6 @@ ifeq ($(DEV_BUILD), y) CRASHDUMP := y DEV_BRANCH := y AMD_K := y - LASERXT := y PORTABLE3 := y I686 := y PAS16 := y @@ -520,11 +516,6 @@ ifeq ($(DEV_BRANCH), y) OPTS += -DUSE_AMD_K endif - ifeq ($(LASERXT), y) - OPTS += -DUSE_LASERXT - DEVBROBJ += m_xt_laserxt.obj - endif - ifeq ($(PORTABLE3), y) OPTS += -DUSE_PORTABLE3 endif @@ -590,7 +581,7 @@ CPUOBJ := cpu.obj cpu_table.obj \ MCHOBJ := machine.obj machine_table.obj \ m_xt.obj m_xt_compaq.obj \ m_xt_t1000.obj m_xt_t1000_vid.obj \ - m_xt_xi8088.obj \ + m_xt_laserxt.obj m_xt_xi8088.obj \ m_zenith.obj \ m_pcjr.obj \ m_amstrad.obj m_europc.obj \