From b2d7b102c8e843c8076cfb56078c51904da726d5 Mon Sep 17 00:00:00 2001 From: waltje Date: Wed, 13 Feb 2019 01:43:28 -0500 Subject: [PATCH] Went back to #330 tree, and manually applied patches to #331 until it breaks. Fixed several issues with the code. Fixed Hercules to be detected again - still no graphics. Fixed several issues in the PC/XT keyboard driver to be correct. .. and while at that, added support for the IBM-PC Cassette Interface! (eat THAT, Sarah!) --- src/config.c | 6 +- src/cpu/808x.c | 1473 ++++++++++----------- src/devices/input/keyboard_xt.c | 115 +- src/devices/system/dma.c | 1828 +++++++++++++------------- src/devices/system/pit.c | 148 +-- src/devices/system/pit.h | 8 +- src/devices/video/vid_cga.c | 6 +- src/devices/video/vid_hercules.c | 7 +- src/devices/video/vid_herculesplus.c | 10 +- src/devices/video/vid_incolor.c | 6 +- src/devices/video/video.c | 7 +- src/machines/m_xt.c | 7 +- src/machines/machine.c | 17 +- src/machines/machine_table.c | 6 +- src/pc.c | 9 +- src/ui/ui_resource.h | 5 +- src/win/mingw/Makefile.MinGW | 2 +- src/win/msvc/Makefile.VC | 3 +- src/win/win.c | 7 +- 19 files changed, 1759 insertions(+), 1911 deletions(-) diff --git a/src/config.c b/src/config.c index cdd3af3..e584dd3 100644 --- a/src/config.c +++ b/src/config.c @@ -12,7 +12,7 @@ * it on Windows XP, and possibly also Vista. Use the * -DANSI_CFG for use on these systems. * - * Version: @(#)config.c 1.0.41 2019/02/10 + * Version: @(#)config.c 1.0.42 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1540,7 +1540,7 @@ config_read(const wchar_t *fn) d = 0; while (buff[c] && (buff[c] != L']')) wctomb(&(sname[d++]), buff[c++]); - sname[d] = L'\0'; + sname[d] = '\0'; /* Is the section name properly terminated? */ if (buff[c] != L']') continue; @@ -1947,7 +1947,7 @@ config_set_string(const char *cat, const char *name, const char *val) if (ent == NULL) ent = create_entry(section, name); - strncpy(ent->data, val, strlen(ent->data)); + strncpy(ent->data, val, sizeof(ent->data)); mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); } diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 0cfd5db..c85a75b 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -8,7 +8,7 @@ * * 808x CPU emulation. * - * Version: @(#)808x.c 1.0.10 2019/02/11 + * Version: @(#)808x.c 1.0.10 2019/02/12 * * Authors: Miran Grca, * Andrew Jenner, @@ -56,74 +56,78 @@ /* 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; -/* Number of instructions executed - used to calculate the % shown in the title bar. */ -int ins = 0; +/* Amount 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, - pfq_pos = 0; +static int fetchcycles = 0; +static int fetchclocks, 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; @@ -194,7 +198,7 @@ irq_pending(void) static void -cpu_wait(int c, int bus) +wait(int c, int bus) { cycles -= c; if (!bus) @@ -205,26 +209,6 @@ cpu_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 @@ -232,8 +216,16 @@ readmemb(uint32_t a) { uint8_t ret; - cpu_wait(4, 1); - ret = readmemb_common(a); + 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)); + } return ret; } @@ -249,7 +241,14 @@ readmembf(uint32_t a) a = cs + (a & 0xffff); - ret = readmemb_common(a); + if (readlookup2 == NULL) + ret = readmembl(a); + else { + if (readlookup2[(a) >> 12] == -1) + ret = readmembl(a); + else + ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a)); + } return ret; } @@ -257,39 +256,26 @@ 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)) - cpu_wait(4, 1); - else - cpu_wait(8, 1); - ret = readmemw_common(s, a); + if (!is8086 || (a & 1)) { + ret = readmemb(s + a); + ret |= readmemb(s + ((a + 1) & 0xffff)) << 8; + } else { + wait(4, 1); - return ret; -} - - -static uint16_t -readmemwf(uint16_t a) -{ - uint16_t ret; - - ret = readmemw_common(cs, a & 0xffff); + 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; } @@ -298,12 +284,14 @@ readmemwf(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_common(uint32_t a, uint8_t v) +writememb(uint32_t a, uint8_t v) { + wait(4, 1); + if (writelookup2 == NULL) writemembl(a, v); else { - if (writelookup2[(a) >> 12] == ((uintptr_t) -1)) + if (writelookup2[(a) >> 12] == -1) writemembl(a, v); else *(uint8_t *)(writelookup2[a >> 12] + a) = v; @@ -311,92 +299,56 @@ writememb_common(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)) - cpu_wait(4, 1); - else - cpu_wait(8, 1); + if (!is8086 || (a & 1)) { + writememb(s + a, v & 0xff); + writememb(s + ((a + 1) & 0xffff), v >> 8); + } else { + wait(4, 1); - 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++; - } + 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; + } } } -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; + uint8_t temp, i; if (pfq_pos == 0) { - /* Extra cycles due to having to fetch on read. */ - cpu_wait(4 - (fetchcycles & 3), 1); + cycles -= (4 - (fetchcycles & 3)); + fetchclocks += (4 - (fetchcycles & 3)); fetchcycles = 4; - /* Reset prefetch queue internal position. */ - pfq_ip = cpu_state.pc; - /* Fill the queue. */ - pfq_write(); - } else + 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--; fetchcycles -= 4; - - /* Fetch. */ - temp = pfq_read(); - cpu_wait(1, 0); - + cpu_state.pc++; + } + wait(1, 0); return temp; } @@ -423,7 +375,16 @@ pfq_add(int c) d = c + (fetchcycles & 3); while ((d > 3) && (pfq_pos < pfq_size)) { d -= 4; - pfq_write(); + 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 += c; if (fetchcycles > 16) @@ -431,12 +392,46 @@ 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(void) +pfq_clear() { 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(); } @@ -491,22 +486,22 @@ do_mod_rm(void) if (cpu_mod == 3) return; - cpu_wait(3, 0); + wait(3, 0); if (!cpu_mod && (cpu_rm == 6)) { - cpu_wait(2, 0); + wait(2, 0); cpu_state.eaaddr = pfq_fetchw(); easeg = ds; - cpu_wait(1, 0); + wait(1, 0); } else { switch (cpu_rm) { case 0: case 3: - cpu_wait(2, 0); + wait(2, 0); break; case 1: case 2: - cpu_wait(3, 0); + wait(3, 0); break; } @@ -515,15 +510,15 @@ do_mod_rm(void) switch (cpu_mod) { case 1: - cpu_wait(4, 0); + wait(4, 0); cpu_state.eaaddr += (uint16_t) (int8_t) pfq_fetchb(); break; case 2: - cpu_wait(4, 0); + wait(4, 0); cpu_state.eaaddr += pfq_fetchw(); break; } - cpu_wait(2, 0); + wait(2, 0); } cpu_state.eaaddr &= 0xffff; @@ -560,7 +555,6 @@ geteaw(void) { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; - return readmemw(easeg, cpu_state.eaaddr); } @@ -575,8 +569,7 @@ 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 @@ -616,7 +609,6 @@ 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) @@ -646,8 +638,6 @@ 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) @@ -749,27 +739,42 @@ 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 -do_push_ex(uint16_t val) +push_ex(uint16_t val) { - writememw(ss, (SP & 0xffff), val); + writememw(ss, (SP & 0xFFFF), val); cpu_state.last_ea = SP; } static void -do_push(uint16_t val) +push(uint16_t val) { SP -= 2; - - do_push_ex(val); + push_ex(val); } /* Pops a word from the stack. */ static uint16_t -do_pop(void) +pop(void) { uint16_t tempw; @@ -781,7 +786,7 @@ do_pop(void) static void -do_access(int num, int bits) +access(int num, int bits) { switch (num) { case 0: case 61: case 63: case 64: @@ -791,92 +796,92 @@ do_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: - cpu_wait(1 + (cycles % 3), 0); + wait(1 + (cycles % 3), 0); break; case 2: case 15: case 22: case 23: case 25: case 26: case 46: case 53: - cpu_wait(2 + (cycles % 3), 0); + wait(2 + (cycles % 3), 0); break; case 3: case 44: case 45: case 52: case 54: - cpu_wait(2 + (cycles & 1), 0); + wait(2 + (cycles & 1), 0); break; case 4: - cpu_wait(5 + (cycles & 1), 0); + wait(5 + (cycles & 1), 0); break; case 5: if (opcode == 0xcc) - cpu_wait(7 + (cycles % 3), 0); + wait(7 + (cycles % 3), 0); else - cpu_wait(4 + (cycles & 1), 0); + wait(4 + (cycles & 1), 0); break; case 7: case 47: case 48: case 49: case 50: case 51: - cpu_wait(1 + (cycles % 4), 0); + wait(1 + (cycles % 4), 0); break; case 10: case 11: case 18: case 19: case 43: - cpu_wait(3 + (cycles % 3), 0); + wait(3 + (cycles % 3), 0); break; case 12: case 13: case 14: case 29: case 30: case 33: - cpu_wait(4 + (cycles % 3), 0); + wait(4 + (cycles % 3), 0); break; case 16: if (!(opcode & 1) && (cycles & 1)) - cpu_wait(1, 0); + wait(1, 0); /* Fall through. */ case 42: - cpu_wait(3 + (cycles & 1), 0); + wait(3 + (cycles & 1), 0); break; case 27: case 32: case 37: - cpu_wait(3, 0); + wait(3, 0); break; case 31: - cpu_wait(6 + (cycles % 3), 0); + wait(6 + (cycles % 3), 0); break; case 34: case 39: case 41: case 60: - cpu_wait(4, 0); + wait(4, 0); break; case 35: - cpu_wait(2, 0); + wait(2, 0); break; case 36: - cpu_wait(5 + (cycles & 1), 0); + wait(5 + (cycles & 1), 0); if (cpu_mod != 3) - cpu_wait(1, 0); + wait(1, 0); break; case 38: - cpu_wait(5 + (cycles % 3), 0); + wait(5 + (cycles % 3), 0); break; case 40: - cpu_wait(6, 0); + wait(6, 0); break; case 57: if (cpu_mod != 3) - cpu_wait(2, 0); - cpu_wait(4 + (cycles & 1), 0); + wait(2, 0); + wait(4 + (cycles & 1), 0); break; case 58: if (cpu_mod != 3) - cpu_wait(1, 0); - cpu_wait(4 + (cycles & 1), 0); + wait(1, 0); + wait(4 + (cycles & 1), 0); break; case 59: if (cpu_mod != 3) - cpu_wait(1, 0); - cpu_wait(5 + (cycles & 1), 0); + wait(1, 0); + wait(5 + (cycles & 1), 0); break; case 62: - cpu_wait(1, 0); + wait(1, 0); break; case 65: - cpu_wait(3 + (cycles & 1), 0); + wait(3 + (cycles & 1), 0); if (cpu_mod != 3) - cpu_wait(1, 0); + wait(1, 0); break; case 70: - cpu_wait(5, 0); + wait(5, 0); break; } } @@ -884,31 +889,31 @@ do_access(int num, int bits) /* Calls an interrupt. */ static void -do_intr(uint16_t addr, int cli) +interrupt(uint16_t addr, int cli) { uint16_t old_cs, old_ip; uint16_t new_cs, new_ip; addr <<= 2; old_cs = CS; - do_access(5, 16); + access(5, 16); new_ip = readmemw(0, addr); - cpu_wait(1, 0); - do_access(6, 16); + wait(1, 0); + access(6, 16); new_cs = readmemw(0, (addr + 2) & 0xffff); - do_access(39, 16); - do_push(flags & 0x0fd7); + access(39, 16); + push(flags & 0x0fd7); if (cli) flags &= ~I_FLAG; flags &= ~T_FLAG; - do_access(40, 16); - do_push(old_cs); + access(40, 16); + push(old_cs); old_ip = cpu_state.pc; loadcs(new_cs); - do_access(68, 16); + access(68, 16); cpu_state.pc = new_ip; - do_access(41, 16); - do_push(old_ip); + access(41, 16); + push(old_ip); pfq_clear(); } @@ -920,35 +925,35 @@ rep_action(int *completed, int *repeating, int in_rep, int bits) if (in_rep == 0) return 0; - cpu_wait(2, 0); + wait(2, 0); t = CX; if (irq_pending()) { - do_access(71, bits); + access(71, bits); pfq_clear(); cpu_state.pc = cpu_state.pc - 2; t = 0; } if (t == 0) { - cpu_wait(1, 0); + wait(1, 0); *completed = 1; *repeating = 0; return 1; } --CX; *completed = 0; - cpu_wait(2, 0); + wait(2, 0); if (!*repeating) - cpu_wait(2, 0); + wait(2, 0); return 0; } static uint16_t -do_jump(uint16_t delta) +jump(uint16_t delta) { uint16_t old_ip; - do_access(67, 8); - cpu_wait(5, 0); + access(67, 8); + wait(5, 0); old_ip = cpu_state.pc; cpu_state.pc = (cpu_state.pc + delta) & 0xffff; pfq_clear(); @@ -966,26 +971,26 @@ sign_extend(uint8_t data) static void jump_short(void) { - do_jump(sign_extend((uint8_t) cpu_data)); + jump(sign_extend((uint8_t) cpu_data)); } static uint16_t jump_near(void) { - return do_jump(pfq_fetchw()); + return jump(pfq_fetchw()); } /* Performs a conditional jump. */ static void -do_jcc(uint8_t opcode, int cond) +jcc(uint8_t opcode, int cond) { /* int8_t offset; */ - cpu_wait(1, 0); + wait(1, 0); cpu_data = pfq_fetchb(); - cpu_wait(1, 0); + wait(1, 0); if ((!cond) == (opcode & 0x01)) jump_short(); } @@ -1022,7 +1027,7 @@ bitwise(int bits, uint16_t data) static void -do_test(int bits, uint16_t dest, uint16_t src) +test(int bits, uint16_t dest, uint16_t src) { cpu_dest = dest; cpu_src = src; @@ -1084,7 +1089,7 @@ set_apzs(int bits) static void -do_add(int bits) +add(int bits) { int size_mask = (1 << bits) - 1; @@ -1102,7 +1107,7 @@ do_add(int bits) static void -do_sub(int bits) +sub(int bits) { int size_mask = (1 << bits) - 1; @@ -1131,17 +1136,17 @@ alu_op(int bits) cpu_src++; /* Fall through. */ case 0: - do_add(bits); + add(bits); break; case 3: if (flags & C_FLAG) cpu_src++; /* Fall through. */ case 5: case 7: - do_sub(bits); + sub(bits); break; case 4: - do_test(bits, cpu_dest, cpu_src); + test(bits, cpu_dest, cpu_src); break; case 6: bitwise(bits, (cpu_dest ^ cpu_src)); @@ -1183,7 +1188,7 @@ set_pf(void) static void -do_mul(uint16_t a, uint16_t b) +mul(uint16_t a, uint16_t b) { int negate = 0; int bit_count = 8; @@ -1199,32 +1204,32 @@ do_mul(uint16_t a, uint16_t b) bit_count = 16; high_bit = 0x8000; } else - cpu_wait(8, 0); + 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)) { - cpu_wait(1, 0); + wait(1, 0); if ((b & size_mask) != ((opcode & 1) ? 0x8000 : 0x80)) - cpu_wait(1, 0); + wait(1, 0); b = ~b + 1; negate = 1; } } else { - cpu_wait(1, 0); + wait(1, 0); a = ~a + 1; negate = 1; if (top_bit(b, bit_count)) { b = ~b + 1; negate = 0; } else - cpu_wait(4, 0); + wait(4, 0); } - cpu_wait(10, 0); + wait(10, 0); } - cpu_wait(3, 0); + wait(3, 0); } c = 0; @@ -1232,13 +1237,13 @@ do_mul(uint16_t a, uint16_t b) carry = (a & 1) != 0; a >>= 1; for (i = 0; i < bit_count; ++i) { - cpu_wait(7, 0); + wait(7, 0); if (carry) { cpu_src = c; cpu_dest = b; - do_add(bit_count); + add(bit_count); c = cpu_data & size_mask; - cpu_wait(1, 0); + wait(1, 0); carry = !!(flags & C_FLAG); } r = (c >> 1) + (carry ? high_bit : 0); @@ -1253,7 +1258,7 @@ do_mul(uint16_t a, uint16_t b) a = (~a + 1) & size_mask; if (a == 0) ++c; - cpu_wait(9, 0); + wait(9, 0); } cpu_data = a; cpu_dest = c; @@ -1294,12 +1299,12 @@ set_co_mul(int carry) set_cf(carry); set_of(carry); if (!carry) - cpu_wait(1, 0); + wait(1, 0); } static int -do_div(uint16_t l, uint16_t h) +div(uint16_t l, uint16_t h) { int b, bit_count = 8; int negative = 0; @@ -1325,28 +1330,28 @@ do_div(uint16_t l, uint16_t h) h &= size_mask; negative = 1; dividend_negative = 1; - cpu_wait(4, 0); + wait(4, 0); } if (top_bit(cpu_src, bit_count)) { cpu_src = ~cpu_src + 1; negative = !negative; } else - cpu_wait(1, 0); - cpu_wait(9, 0); + wait(1, 0); + wait(9, 0); } - cpu_wait(3, 0); + wait(3, 0); } - cpu_wait(8, 0); + cycles -= 8; cpu_src &= size_mask; if (h >= cpu_src) { if (opcode != 0xd4) - cpu_wait(1, 0); - do_intr(0, 1); + wait(1, 0); + interrupt(0, 1); return 0; } if (opcode != 0xd4) - cpu_wait(1, 0); - cpu_wait(2, 0); + wait(1, 0); + wait(2, 0); carry = 1; for (b = 0; b < bit_count; ++b) { r = (l << 1) + (carry ? 1 : 0); @@ -1355,32 +1360,32 @@ do_div(uint16_t l, uint16_t h) r = (h << 1) + (carry ? 1 : 0); carry = top_bit(h, bit_count); h = r; - cpu_wait(8, 0); + wait(8, 0); if (carry) { carry = 0; h -= cpu_src; if (b == bit_count - 1) - cpu_wait(2, 0); + wait(2, 0); } else { carry = cpu_src > h; if (!carry) { h -= cpu_src; - cpu_wait(1, 0); + wait(1, 0); if (b == bit_count - 1) - cpu_wait(2, 0); + wait(2, 0); } } } l = ~((l << 1) + (carry ? 1 : 0)); if (opcode != 0xd4 && (rmdat & 0x38) == 0x38) { - cpu_wait(4, 0); + wait(4, 0); if (top_bit(l, bit_count)) { if (cpu_mod == 3) - cpu_wait(1, 0); - do_intr(0, 1); + wait(1, 0); + interrupt(0, 1); return 0; } - cpu_wait(7, 0); + wait(7, 0); if (negative) l = ~l + 1; if (dividend_negative) @@ -1402,7 +1407,7 @@ do_div(uint16_t l, uint16_t h) static void -do_lods(int bits) +lods(int bits) { if (bits == 16) cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), SI); @@ -1416,7 +1421,7 @@ do_lods(int bits) static void -do_stos(int bits) +stos(int bits) { if (bits == 16) writememw(es, DI, cpu_data); @@ -1430,19 +1435,19 @@ do_stos(int bits) static void -do_da(void) +da(void) { set_pzs(8); - cpu_wait(2, 0); + wait(2, 0); } static void -do_aa(void) +aa(void) { set_of(0); AL &= 0x0f; - cpu_wait(6, 0); + wait(6, 0); } @@ -1467,7 +1472,7 @@ void execx86(int cycs) { uint8_t temp = 0, temp2; - uint16_t do_addr, tempw; + uint16_t addr, tempw; uint16_t new_cs, new_ip; int bits, completed; int in_rep, repeating; @@ -1477,57 +1482,50 @@ 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) { - cpu_wait(2, 0); + wait(2, 0); goto on_halt; } - if (! repeating) { + if (!repeating) { opcode = pfq_fetchb(); oldc = flags & C_FLAG; trap = flags & T_FLAG; - cpu_wait(1, 0); + wait(1, 0); -#if 0 - if (!in_rep && !ovr_seg && (CS < 0xf000)) - DEBUG("%04X:%04X %02X\n", - CS, (cpu_state.pc - 1) & 0xffff, opcode); -#endif + /* if (!in_rep && !ovr_seg && (CS < 0xf000)) + pclog("%04X:%04X %02X\n", CS, (cpu_state.pc - 1) & 0xFFFF, opcode); */ } switch (opcode) { - case 0x06: /* PUSH seg */ - case 0x0e: - case 0x16: - case 0x1e: - do_access(29, 16); - do_push(_opseg[(opcode >> 3) & 0x03]->seg); + case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ + access(29, 16); + push(_opseg[(opcode >> 3) & 0x03]->seg); break; - - case 0x07: /* POP seg */ - case 0x0f: - case 0x17: - case 0x1f: - do_access(22, 16); - if (opcode == 0x0f) { - loadcs(do_pop()); + case 0x07: case 0x0F: case 0x17: case 0x1F: /* POP seg */ + access(22, 16); + if (opcode == 0x0F) { + loadcs(pop()); pfq_clear(); } else - loadseg(do_pop(), _opseg[(opcode >> 3) & 0x03]); - cpu_wait(1, 0); + loadseg(pop(), _opseg[(opcode >> 3) & 0x03]); + wait(1, 0); noint = 1; break; case 0x26: /*ES:*/ - case 0x2e: /*CS:*/ + case 0x2E: /*CS:*/ case 0x36: /*SS:*/ - case 0x3e: /*DS:*/ - cpu_wait(1, 0); + case 0x3E: /*DS:*/ + wait(1, 0); ovr_seg = opseg[(opcode >> 3) & 0x03]; goto opcodestart; @@ -1542,7 +1540,7 @@ opcodestart: /* alu rm, r / r, rm */ bits = 8 << (opcode & 1); do_mod_rm(); - do_access(46, bits); + access(46, bits); if (opcode & 1) tempw = geteaw(); else @@ -1556,27 +1554,27 @@ opcodestart: cpu_src = tempw; } if (cpu_mod != 3) - cpu_wait(2, 0); - cpu_wait(1, 0); + wait(2, 0); + wait(1, 0); alu_op(bits); if (cpu_alu_op != 7) { if ((opcode & 2) == 0) { - do_access(10, bits); + access(10, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t) (cpu_data & 0xff)); if (cpu_mod == 3) - cpu_wait(1, 0); + wait(1, 0); } else { if (opcode & 1) cpu_state.regs[cpu_reg].w = cpu_data; else setr8(cpu_reg, (uint8_t)(cpu_data & 0xff)); - cpu_wait(1, 0); + wait(1, 0); } } else - cpu_wait(1, 0); + wait(1, 0); break; case 0x04: case 0x05: case 0x0c: case 0x0d: @@ -1585,7 +1583,7 @@ opcodestart: case 0x34: case 0x35: case 0x3c: case 0x3d: /* alu A, imm */ bits = 8 << (opcode & 1); - cpu_wait(1, 0); + wait(1, 0); if (opcode & 1) { cpu_data = pfq_fetchw(); cpu_dest = AX; @@ -1602,74 +1600,71 @@ opcodestart: else AL = cpu_data & 0xff; } - cpu_wait(1, 0); + wait(1, 0); break; case 0x27: /*DAA*/ - cpu_wait(1, 0); + 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 & 0x0100) != 0) + if ((cpu_data & 0x100) != 0) set_cf(1); } if ((flags & C_FLAG) || AL > 0x9f) { AL += 0x60; set_cf(1); } - do_da(); + da(); break; - - case 0x2f: /*DAS*/ - cpu_wait(1, 0); + case 0x2F: /*DAS*/ + wait(1, 0); temp = AL; - if ((flags & A_FLAG) || ((AL & 0x0f) > 9)) { + if ((flags & A_FLAG) || ((AL & 0xf) > 9)) { cpu_data = AL - 6; AL = (uint8_t) cpu_data; set_af(1); - if ((cpu_data & 0x0100) != 0) + if ((cpu_data & 0x100) != 0) set_cf(1); } if ((flags & C_FLAG) || temp > 0x9f) { AL -= 0x60; set_cf(1); } - do_da(); + da(); break; - case 0x37: /*AAA*/ - cpu_wait(1, 0); - if ((flags & A_FLAG) || ((AL & 0x0f) > 9)) { + wait(1, 0); + if ((flags & A_FLAG) || ((AL & 0xf) > 9)) { AL += 6; ++AH; set_ca(); } else { clear_ca(); - cpu_wait(1, 0); + wait(1, 0); } - do_aa(); + aa(); break; - - case 0x3f: /*AAS*/ - cpu_wait(1, 0); - if ((flags & A_FLAG) || ((AL & 0x0f) > 9)) { + case 0x3F: /*AAS*/ + wait(1, 0); + if ((flags & A_FLAG) || ((AL & 0xf) > 9)) { AL -= 6; --AH; set_ca(); } else { clear_ca(); - cpu_wait(1, 0); + wait(1, 0); } - do_aa(); + 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 */ - cpu_wait(1, 0); + wait(1, 0); cpu_dest = cpu_state.regs[opcode & 7].w; cpu_src = 1; bits = 16; @@ -1687,117 +1682,109 @@ opcodestart: case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ case 0x54: case 0x55: case 0x56: case 0x57: - do_access(30, 16); + access(30, 16); if (opcode == 0x54) { SP -= 2; - do_push_ex(cpu_state.regs[opcode & 0x07].w); + push_ex(cpu_state.regs[opcode & 0x07].w); } else - do_push(cpu_state.regs[opcode & 0x07].w); + 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: - do_access(23, 16); - cpu_state.regs[opcode & 0x07].w = do_pop(); - cpu_wait(1, 0); + 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); break; case 0x60: /*JO alias*/ case 0x70: /*JO*/ case 0x61: /*JNO alias*/ case 0x71: /*JNO*/ - do_jcc(opcode, flags & V_FLAG); + jcc(opcode, flags & V_FLAG); break; - case 0x62: /*JB alias*/ case 0x72: /*JB*/ case 0x63: /*JNB alias*/ case 0x73: /*JNB*/ - do_jcc(opcode, flags & C_FLAG); + jcc(opcode, flags & C_FLAG); break; - case 0x64: /*JE alias*/ case 0x74: /*JE*/ case 0x65: /*JNE alias*/ case 0x75: /*JNE*/ - do_jcc(opcode, flags & Z_FLAG); + jcc(opcode, flags & Z_FLAG); break; - case 0x66: /*JBE alias*/ case 0x76: /*JBE*/ case 0x67: /*JNBE alias*/ case 0x77: /*JNBE*/ - do_jcc(opcode, flags & (C_FLAG | Z_FLAG)); + jcc(opcode, flags & (C_FLAG | Z_FLAG)); break; - case 0x68: /*JS alias*/ case 0x78: /*JS*/ case 0x69: /*JNS alias*/ case 0x79: /*JNS*/ - do_jcc(opcode, flags & N_FLAG); + jcc(opcode, flags & N_FLAG); break; - - case 0x6a: /*JP alias*/ - case 0x7a: /*JP*/ - case 0x6b: /*JNP alias*/ - case 0x7b: /*JNP*/ - do_jcc(opcode, flags & P_FLAG); + case 0x6A: /*JP alias*/ + case 0x7A: /*JP*/ + case 0x6B: /*JNP alias*/ + case 0x7B: /*JNP*/ + 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; - do_jcc(opcode, temp ^ temp2); + 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; - do_jcc(opcode, (flags & Z_FLAG) || (temp != temp2)); + 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(); - do_access(47, bits); + access(47, bits); if (opcode & 1) cpu_data = geteaw(); else cpu_data = geteab(); cpu_dest = cpu_data; if (cpu_mod != 3) - cpu_wait(3, 0); + wait(3, 0); if (opcode == 0x81) { if (cpu_mod == 3) - cpu_wait(1, 0); + wait(1, 0); cpu_src = pfq_fetchw(); } else { if (cpu_mod == 3) - cpu_wait(1, 0); + wait(1, 0); if (opcode == 0x83) cpu_src = sign_extend(pfq_fetchb()); else cpu_src = pfq_fetchb() | 0xff00; } - cpu_wait(1, 0); + wait(1, 0); cpu_alu_op = (rmdat & 0x38) >> 3; alu_op(bits); if (cpu_alu_op != 7) { - do_access(11, bits); + access(11, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); } else { if (cpu_mod != 3) - cpu_wait(1, 0); + wait(1, 0); } break; @@ -1805,24 +1792,23 @@ opcodestart: /* TEST rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); - do_access(48, bits); + access(48, bits); if (opcode & 1) { cpu_data = geteaw(); - do_test(bits, cpu_data, cpu_state.regs[cpu_reg].w); + test(bits, cpu_data, cpu_state.regs[cpu_reg].w); } else { cpu_data = geteab(); - do_test(bits, cpu_data, getr8(cpu_reg)); + test(bits, cpu_data, getr8(cpu_reg)); } if (cpu_mod == 3) - cpu_wait(2, 0); - cpu_wait(2, 0); + wait(2, 0); + wait(2, 0); break; - case 0x86: case 0x87: /* XCHG rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); - do_access(49, bits); + access(49, bits); if (opcode & 1) { cpu_data = geteaw(); cpu_src = cpu_state.regs[cpu_reg].w; @@ -1832,271 +1818,252 @@ opcodestart: cpu_src = getr8(cpu_reg); setr8(cpu_reg, (uint8_t)(cpu_data & 0xff)); } - cpu_wait(3, 0); - do_access(12, bits); + wait(3, 0); + access(12, bits); if (opcode & 1) seteaw(cpu_src); else seteab((uint8_t)(cpu_src & 0xff)); break; - case 0x88: /* MOV rm, reg */ - case 0x89: + case 0x88: case 0x89: + /* MOV rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); - cpu_wait(1, 0); - do_access(13, bits); + wait(1, 0); + access(13, bits); if (opcode & 1) seteaw(cpu_state.regs[cpu_reg].w); else seteab(getr8(cpu_reg)); break; - - case 0x8a: /* MOV reg, rm */ - case 0x8b: + case 0x8A: case 0x8B: + /* MOV reg, rm */ bits = 8 << (opcode & 1); do_mod_rm(); - do_access(50, bits); + access(50, bits); if (opcode & 1) cpu_state.regs[cpu_reg].w = geteaw(); else setr8(cpu_reg, geteab()); - cpu_wait(1, 0); + wait(1, 0); if (cpu_mod != 3) - cpu_wait(2, 0); + wait(2, 0); break; - case 0x8c: /*MOV w,sreg*/ + case 0x8C: /*MOV w,sreg*/ do_mod_rm(); if (cpu_mod == 3) - cpu_wait(1, 0); - do_access(14, 16); + wait(1, 0); + 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; - cpu_wait(1, 0); + wait(1, 0); if (cpu_mod != 3) - cpu_wait(2, 0); + wait(2, 0); break; - case 0x8e: /*MOV sreg,w*/ + case 0x8E: /*MOV sreg,w*/ do_mod_rm(); - do_access(51, 16); + 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; } - cpu_wait(1, 0); + wait(1, 0); if (cpu_mod != 3) - cpu_wait(2, 0); + wait(2, 0); noint = 1; break; - case 0x8f: /*POPW*/ + case 0x8F: /*POPW*/ do_mod_rm(); - cpu_wait(1, 0); + wait(1, 0); cpu_src = cpu_state.eaaddr; - do_access(24, 16); + access(24, 16); if (cpu_mod != 3) - cpu_wait(2, 0); - cpu_data = do_pop(); + wait(2, 0); + cpu_data = pop(); cpu_state.eaaddr = cpu_src; - cpu_wait(2, 0); - do_access(15, 16); + wait(2, 0); + 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 */ - cpu_wait(1, 0); + wait(1, 0); cpu_data = cpu_state.regs[opcode & 7].w; cpu_state.regs[opcode & 7].w = AX; AX = cpu_data; - cpu_wait(1, 0); + wait(1, 0); break; case 0x98: /*CBW*/ - cpu_wait(1, 0); + wait(1, 0); AX = sign_extend(AL); break; - case 0x99: /*CWD*/ - cpu_wait(4, 0); + wait(4, 0); if (!top_bit(AX, 16)) DX = 0; else { - cpu_wait(1, 0); + wait(1, 0); DX = 0xffff; } break; - - case 0x9a: /*CALL FAR*/ - cpu_wait(1, 0); + case 0x9A: /*CALL FAR*/ + wait(1, 0); new_ip = pfq_fetchw(); - cpu_wait(1, 0); + wait(1, 0); new_cs = pfq_fetchw(); - do_access(31, 16); - do_push(CS); - do_access(60, 16); + access(31, 16); + push(CS); + access(60, 16); cpu_state.oldpc = cpu_state.pc; loadcs(new_cs); cpu_state.pc = new_ip; - do_access(32, 16); - do_push(cpu_state.oldpc); + access(32, 16); + push(cpu_state.oldpc); pfq_clear(); break; - - case 0x9b: /*WAIT*/ - cpu_wait(4, 0); + case 0x9B: /*WAIT*/ + cycles -= 4; break; - - case 0x9c: /*PUSHF*/ - do_access(33, 16); - do_push((flags & 0x0fd7) | 0xf000); + case 0x9C: /*PUSHF*/ + access(33, 16); + push((flags & 0x0fd7) | 0xf000); break; - - case 0x9d: /*POPF*/ - do_access(25, 16); - flags = do_pop() | 2; - cpu_wait(1, 0); + case 0x9D: /*POPF*/ + access(25, 16); + flags = pop() | 2; + wait(1, 0); break; - - case 0x9e: /*SAHF*/ - cpu_wait(1, 0); + case 0x9E: /*SAHF*/ + wait(1, 0); flags = (flags & 0xff02) | AH; - cpu_wait(2, 0); + wait(2, 0); break; - - case 0x9f: /*LAHF*/ - cpu_wait(1, 0); + case 0x9F: /*LAHF*/ + wait(1, 0); AH = flags & 0xd7; break; - case 0xa0: /* MOV A, [iw] */ - case 0xa1: + case 0xA0: case 0xA1: + /* MOV A, [iw] */ bits = 8 << (opcode & 1); - cpu_wait(1, 0); - do_addr = pfq_fetchw(); - do_access(1, bits); + wait(1, 0); + addr = pfq_fetchw(); + access(1, bits); if (opcode & 1) - AX = readmemw((ovr_seg ? *ovr_seg : ds), do_addr); + AX = readmemw((ovr_seg ? *ovr_seg : ds), addr); else - AL = readmemb((ovr_seg ? *ovr_seg : ds) + do_addr); - cpu_wait(1, 0); + 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); break; - 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: + case 0xA4: case 0xA5: /* MOVS */ + case 0xAC: case 0xAD: /* LODS */ bits = 8 << (opcode & 1); if (!repeating) { - cpu_wait(1 /*2*/, 0); + wait(1 /*2*/, 0); if ((opcode & 8) == 0 && in_rep != 0) - cpu_wait(1, 0); + wait(1, 0); } if (rep_action(&completed, &repeating, in_rep, bits)) { - cpu_wait(1, 0); + wait(1, 0); if ((opcode & 8) != 0) - cpu_wait(1, 0); + wait(1, 0); break; } if (in_rep != 0 && (opcode & 8) != 0) - cpu_wait(1, 0); - do_access(20, bits); - do_lods(bits); + wait(1, 0); + access(20, bits); + lods(bits); if ((opcode & 8) == 0) { - do_access(27, bits); - do_stos(bits); + access(27, bits); + stos(bits); } else { if (opcode & 1) AX = cpu_data; else AL = (uint8_t)(cpu_data & 0xff); if (in_rep != 0) - cpu_wait(2, 0); + wait(2, 0); } if (in_rep == 0) { - cpu_wait(3, 0); + wait(3, 0); if ((opcode & 8) != 0) - cpu_wait(1, 0); + wait(1, 0); break; } repeating = 1; timer_end_period(cycles * xt_cpu_multi); goto opcodestart; - case 0xa6: /* CMPS */ - case 0xa7: - case 0xae: /* SCAS */ - case 0xaf: + case 0xA6: case 0xA7: /* CMPS */ + case 0xAE: case 0xAF: /* SCAS */ bits = 8 << (opcode & 1); if (!repeating) - cpu_wait(1, 0); + wait(1, 0); if (rep_action(&completed, &repeating, in_rep, bits)) { - cpu_wait(2, 0); + wait(2, 0); break; } if (in_rep != 0) - cpu_wait(1, 0); + wait(1, 0); if (opcode & 1) cpu_dest = AX; else cpu_dest = AL; if ((opcode & 8) == 0) { - do_access(21, bits); - do_lods(bits); - cpu_wait(1, 0); + access(21, bits); + lods(bits); + wait(1, 0); cpu_dest = cpu_data; } - do_access(2, bits); + access(2, bits); if (opcode & 1) cpu_data = readmemw(es, DI); else @@ -2106,210 +2073,188 @@ opcodestart: else DI += (bits >> 3); cpu_src = cpu_data; - do_sub(bits); - cpu_wait(2, 0); + sub(bits); + wait(2, 0); if (in_rep == 0) { - cpu_wait(3, 0); + wait(3, 0); break; } if ((!!(flags & Z_FLAG)) == (in_rep == 1)) { - cpu_wait(4, 0); + wait(4, 0); break; } repeating = 1; timer_end_period(cycles * xt_cpu_multi); goto opcodestart; - case 0xa8: /* TEST A, imm */ - case 0xa9: + case 0xA8: case 0xA9: + /* TEST A, imm */ bits = 8 << (opcode & 1); - cpu_wait(1, 0); + wait(1, 0); if (opcode & 1) { cpu_data = pfq_fetchw(); - do_test(bits, AX, cpu_data); + test(bits, AX, cpu_data); } else { cpu_data = pfq_fetchb(); - do_test(bits, AL, cpu_data); + test(bits, AL, cpu_data); } - cpu_wait(1, 0); + wait(1, 0); break; - case 0xaa: /* STOS */ - case 0xab: + case 0xAA: case 0xAB: /* STOS */ bits = 8 << (opcode & 1); if (!repeating) { if (opcode & 1) - cpu_wait(1, 0); + wait(1, 0); if (in_rep != 0) - cpu_wait(1, 0); + wait(1, 0); } if (rep_action(&completed, &repeating, in_rep, bits)) { - cpu_wait(1, 0); + wait(1, 0); break; } cpu_data = AX; - do_access(28, bits); - do_stos(bits); + access(28, bits); + stos(bits); if (in_rep == 0) { - cpu_wait(3, 0); + wait(3, 0); break; } repeating = 1; timer_end_period(cycles * xt_cpu_multi); goto opcodestart; - case 0xb0: /*MOV cpu_reg,#8*/ - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - cpu_wait(1, 0); + case 0xB0: case 0xB1: case 0xB2: case 0xB3: /*MOV cpu_reg,#8*/ + case 0xB4: case 0xB5: case 0xB6: case 0xB7: + 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(); - cpu_wait(1, 0); + wait(1, 0); break; - case 0xb8: /*MOV cpu_reg,#16*/ - case 0xb9: - case 0xba: - case 0xbb: - case 0xbc: - case 0xbd: - case 0xbe: - case 0xbf: - cpu_wait(1, 0); + case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ + case 0xBC: case 0xBD: case 0xBE: case 0xBF: + wait(1, 0); cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); - cpu_wait(1, 0); + wait(1, 0); break; - case 0xc0: /* RET */ - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc8: - case 0xc9: - case 0xca: - case 0xcb: + case 0xC0: case 0xC1: case 0xC2: case 0xC3: + case 0xC8: case 0xC9: case 0xCA: case 0xCB: + /* RET */ bits = 8 + (opcode & 0x08); if ((opcode & 9) != 1) - cpu_wait(1, 0); + wait(1, 0); if (!(opcode & 1)) { cpu_src = pfq_fetchw(); - cpu_wait(1, 0); + wait(1, 0); } if ((opcode & 9) == 9) - cpu_wait(1, 0); - do_access(26, bits); - new_ip = do_pop(); - cpu_wait(2, 0); + wait(1, 0); + access(26, bits); + new_ip = pop(); + wait(2, 0); if ((opcode & 8) == 0) new_cs = CS; else { - do_access(42, bits); - new_cs = do_pop(); + access(42, bits); + new_cs = pop(); if (opcode & 1) - cpu_wait(1, 0); + wait(1, 0); } if (!(opcode & 1)) { SP += cpu_src; - cpu_wait(1, 0); + wait(1, 0); } loadcs(new_cs); - do_access(72, bits); + access(72, bits); cpu_state.pc = new_ip; pfq_clear(); break; - case 0xc4: /* LSS rw, rmd */ - case 0xc5: + case 0xC4: case 0xC5: + /* LsS rw, rmd */ do_mod_rm(); bits = 16; - do_access(52, bits); + 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); - cpu_wait(1, 0); + wait(1, 0); noint = 1; break; - case 0xc6: /* MOV rm, imm */ - case 0xc7: + case 0xC6: case 0xC7: + /* MOV rm, imm */ bits = 8 << (opcode & 1); do_mod_rm(); - cpu_wait(1, 0); + wait(1, 0); if (cpu_mod != 3) - cpu_wait(2, 0); + wait(2, 0); if (opcode & 1) cpu_data = pfq_fetchw(); else cpu_data = pfq_fetchb(); if (cpu_mod == 3) - cpu_wait(1, 0); - do_access(16, bits); + wait(1, 0); + access(16, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; - case 0xcc: /*INT 3*/ - do_intr(3, 1); + case 0xCC: /*INT 3*/ + interrupt(3, 1); break; - - case 0xcd: /*INT*/ - cpu_wait(1, 0); - do_intr(pfq_fetchb(), 1); + case 0xCD: /*INT*/ + wait(1, 0); + interrupt(pfq_fetchb(), 1); break; - - case 0xce: /*INTO*/ - cpu_wait(3, 0); + case 0xCE: /*INTO*/ + wait(3, 0); if (flags & V_FLAG) { - cpu_wait(2, 0); - do_intr(4, 1); + wait(2, 0); + interrupt(4, 1); } break; - case 0xcf: /*IRET*/ - do_access(43, 8); - new_ip = do_pop(); - cpu_wait(3, 0); - do_access(44, 8); - new_cs = do_pop(); + case 0xCF: /*IRET*/ + access(43, 8); + new_ip = pop(); + wait(3, 0); + access(44, 8); + new_cs = pop(); loadcs(new_cs); - do_access(62, 8); + access(62, 8); cpu_state.pc = new_ip; - do_access(45, 8); - flags = do_pop() | 2; - cpu_wait(5, 0); + access(45, 8); + flags = pop() | 2; + wait(5, 0); noint = 1; nmi_enable = 1; pfq_clear(); break; - case 0xd0: /* rot rm */ - case 0xd1: - case 0xd2: - case 0xd3: + case 0xD0: case 0xD1: case 0xD2: case 0xD3: + /* rot rm */ bits = 8 << (opcode & 1); do_mod_rm(); if (cpu_mod == 3) - cpu_wait(1, 0); - do_access(53, bits); + wait(1, 0); + access(53, bits); if (opcode & 1) cpu_data = geteaw(); else cpu_data = geteab(); if ((opcode & 2) == 0) { cpu_src = 1; - cpu_wait((cpu_mod != 3) ? 4 : 0, 0); + wait((cpu_mod != 3) ? 4 : 0, 0); } else { cpu_src = CL; - cpu_wait((cpu_mod != 3) ? 9 : 6, 0); + wait((cpu_mod != 3) ? 9 : 6, 0); } while (cpu_src != 0) { cpu_dest = cpu_data; @@ -2321,7 +2266,6 @@ 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; @@ -2329,13 +2273,11 @@ 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; @@ -2344,14 +2286,12 @@ 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; @@ -2359,7 +2299,6 @@ opcodestart: set_af(1); set_pzs(bits); break; - case 0x30: /* SETMO - undocumented? */ bitwise(bits, 0xffff); set_cf(0); @@ -2367,7 +2306,6 @@ opcodestart: set_af(0); set_pzs(bits); break; - case 0x38: /* SAR */ set_cf((cpu_data & 1) != 0); cpu_data >>= 1; @@ -2381,79 +2319,68 @@ opcodestart: break; } if ((opcode & 2) != 0) - cpu_wait(4, 0); + wait(4, 0); --cpu_src; } - do_access(17, bits); + access(17, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; - case 0xd4: /*AAM*/ - cpu_wait(1, 0); + case 0xD4: /*AAM*/ + wait(1, 0); cpu_src = pfq_fetchb(); - if (do_div(AL, 0)) + if (div(AL, 0)) set_pzs(16); break; - - case 0xd5: /*AAD*/ - cpu_wait(1, 0); - do_mul(pfq_fetchb(), AH); + case 0xD5: /*AAD*/ + wait(1, 0); + mul(pfq_fetchb(), AH); AL += cpu_data; AH = 0x00; set_pzs(16); break; - - case 0xd6: /*SALC*/ - cpu_wait(1, 0); + case 0xD6: /*SALC*/ + wait(1, 0); AL = (flags & C_FLAG) ? 0xff : 0x00; - cpu_wait(1, 0); + 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); break; - 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: + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDD: case 0xDC: case 0xDE: case 0xDF: + /* esc i, r, rm */ do_mod_rm(); - do_access(54, 16); + access(54, 16); geteaw(); - cpu_wait(1, 0); + wait(1, 0); if (cpu_mod != 3) - cpu_wait(2, 0); + wait(2, 0); break; - case 0xe0: /* LOOP */ - case 0xe1: - case 0xe2: - case 0xe3: - cpu_wait(3, 0); + case 0xE0: case 0xE1: case 0xE2: case 0xE3: + /* LOOP */ + wait(3, 0); cpu_data = pfq_fetchb(); if (opcode != 0xe2) - cpu_wait(1, 0); + 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; @@ -2464,203 +2391,186 @@ 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) - cpu_wait(1, 0); + wait(1, 0); if ((opcode & 8) == 0) cpu_data = pfq_fetchb(); else cpu_data = DX; if ((opcode & 2) == 0) { - do_access(3, bits); - if ((opcode & 1) && is8086 && !(cpu_data & 1)) { + access(3, bits); + if ((opcode & 1) && is8086) { AX = inw(cpu_data); - cpu_wait(4, 1); /* I/O do_access and wait state. */ + wait(4, 1); /* I/O access and wait state. */ } else { AL = inb(cpu_data); if (opcode & 1) AH = inb(temp + 1); - cpu_wait(bits >> 1, 1); /* I/O do_access. */ + wait(bits >> 1, 1); /* I/O access. */ } - cpu_wait(1, 0); + wait(1, 0); } else { if ((opcode & 8) == 0) - do_access(8, bits); + access(8, bits); else - do_access(9, bits); - if ((opcode & 1) && is8086 && !(cpu_data & 1)) { + access(9, bits); + if ((opcode & 1) && is8086) { outw(cpu_data, AX); - cpu_wait(4, 1); + wait(4, 1); } else { outb(cpu_data, AL); if (opcode & 1) outb(cpu_data + 1, AH); - cpu_wait(bits >> 1, 1); /* I/O do_access. */ + wait(bits >> 1, 1); /* I/O access. */ } } break; - case 0xe8: /*CALL rel 16*/ - cpu_wait(1, 0); + case 0xE8: /*CALL rel 16*/ + wait(1, 0); cpu_state.oldpc = jump_near(); - do_access(34, 8); - do_push(cpu_state.oldpc); + access(34, 8); + push(cpu_state.oldpc); pfq_clear(); break; - - case 0xe9: /*JMP rel 16*/ - cpu_wait(1, 0); + case 0xE9: /*JMP rel 16*/ + wait(1, 0); jump_near(); break; - - case 0xea: /*JMP far*/ - cpu_wait(1, 0); - do_addr = pfq_fetchw(); - cpu_wait(1, 0); + case 0xEA: /*JMP far*/ + wait(1, 0); + addr = pfq_fetchw(); + wait(1, 0); tempw = pfq_fetchw(); loadcs(tempw); - do_access(70, 8); - cpu_state.pc = do_addr; + access(70, 8); + cpu_state.pc = addr; pfq_clear(); break; - - case 0xeb: /*JMP rel*/ - cpu_wait(1, 0); + case 0xEB: /*JMP rel*/ + wait(1, 0); cpu_data = (int8_t) pfq_fetchb(); jump_short(); - cpu_wait(1, 0); + wait(1, 0); pfq_clear(); break; - case 0xf0: /*LOCK - F1 is alias*/ - case 0xf1: + case 0xF0: case 0xF1: /*LOCK - F1 is alias*/ in_lock = 1; - cpu_wait(1, 0); + wait(1, 0); goto opcodestart; - case 0xf2: /*REPNE*/ - case 0xf3: /*REPE*/ - cpu_wait(1, 0); + case 0xF2: /*REPNE*/ + case 0xF3: /*REPE*/ + 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(); - cpu_wait(2, 0); + wait(2, 0); break; - - case 0xf5: /*CMC*/ - cpu_wait(1, 0); + case 0xF5: /*CMC*/ + wait(1, 0); flags ^= C_FLAG; break; - case 0xf6: - case 0xf7: + case 0xF6: case 0xF7: bits = 8 << (opcode & 1); do_mod_rm(); - do_access(55, bits); + access(55, bits); if (opcode & 1) cpu_data = geteaw(); else cpu_data = geteab(); switch (rmdat & 0x38) { - case 0x00: /* TEST */ - case 0x08: - cpu_wait(2, 0); + case 0x00: case 0x08: + /* TEST */ + wait(2, 0); if (cpu_mod != 3) - cpu_wait(1, 0); + wait(1, 0); if (opcode & 1) cpu_src = pfq_fetchw(); else cpu_src = pfq_fetchb(); - cpu_wait(1, 0); - do_test(bits, cpu_data, cpu_src); + wait(1, 0); + test(bits, cpu_data, cpu_src); if (cpu_mod != 3) - cpu_wait(1, 0); + wait(1, 0); break; - case 0x10: /* NOT */ case 0x18: /* NEG */ - cpu_wait(2, 0); + wait(2, 0); if ((rmdat & 0x38) == 0x10) cpu_data = ~cpu_data; else { cpu_src = cpu_data; cpu_dest = 0; - do_sub(bits); + sub(bits); } - do_access(18, bits); + access(18, bits); if (opcode & 1) seteaw(cpu_data); else seteab((uint8_t)(cpu_data & 0xff)); break; - case 0x20: /* MUL */ case 0x28: /* IMUL */ - cpu_wait(1, 0); + wait(1, 0); if (opcode & 1) { - do_mul(AX, cpu_data); + 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 { - do_mul(AL, cpu_data); + 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) - cpu_wait(1, 0); + wait(1, 0); break; - case 0x30: /* DIV */ case 0x38: /* IDIV */ if (cpu_mod != 3) - cpu_wait(1, 0); + wait(1, 0); cpu_src = cpu_data; - if (do_div(AL, AH)) - cpu_wait(1, 0); + if (div(AL, AH)) + wait(1, 0); break; } break; - case 0xf8: /* CLCSTC */ - case 0xf9: - cpu_wait(1, 0); + case 0xF8: case 0xF9: + /* CLCSTC */ + wait(1, 0); set_cf(opcode & 1); break; - - case 0xfa: /* CLISTI */ - case 0xfb: - cpu_wait(1, 0); + case 0xFA: case 0xFB: + /* CLISTI */ + wait(1, 0); set_if(opcode & 1); break; - - case 0xfc: /* CLDSTD */ - case 0xfd: - cpu_wait(1, 0); + case 0xFC: case 0xFD: + /* CLDSTD */ + wait(1, 0); set_df(opcode & 1); break; - case 0xfe: /* misc */ - case 0xff: + case 0xFE: case 0xFF: + /* misc */ bits = 8 << (opcode & 1); do_mod_rm(); - do_access(56, bits); + access(56, bits); read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); switch (rmdat & 0x38) { case 0x00: /* INC rm */ @@ -2676,14 +2586,13 @@ opcodestart: } do_af(); set_pzs(bits); - cpu_wait(2, 0); - do_access(19, bits); + wait(2, 0); + 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) @@ -2691,38 +2600,36 @@ opcodestart: else cpu_data = cpu_state.regs[cpu_rm].w; } - do_access(63, bits); - cpu_wait(5, 0); + access(63, bits); + wait(5, 0); if (cpu_mod != 3) - cpu_wait(1, 0); - cpu_wait(1, 0); /* Wait. */ + wait(1, 0); + wait(1, 0); /* Wait. */ cpu_state.oldpc = cpu_state.pc; cpu_state.pc = cpu_data; - cpu_wait(2, 0); - do_access(35, bits); - do_push(cpu_state.oldpc); + wait(2, 0); + access(35, bits); + push(cpu_state.oldpc); pfq_clear(); break; - case 0x18: /* CALL rmd */ new_ip = cpu_data; - do_access(58, bits); + access(58, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; - do_access(36, bits); - do_push(CS); - do_access(64, bits); - cpu_wait(4, 0); + access(36, bits); + push(CS); + access(64, bits); + wait(4, 0); cpu_state.oldpc = cpu_state.pc; loadcs(new_cs); cpu_state.pc = new_ip; - do_access(37, bits); - do_push(cpu_state.oldpc); + access(37, bits); + push(cpu_state.oldpc); pfq_clear(); break; - case 0x20: /* JMP rm */ if (!(opcode & 1)) { if (cpu_mod != 3) @@ -2730,33 +2637,31 @@ opcodestart: else cpu_data = cpu_state.regs[cpu_rm].w; } - do_access(65, bits); + access(65, bits); cpu_state.pc = cpu_data; pfq_clear(); break; - case 0x28: /* JMP rmd */ new_ip = cpu_data; - do_access(59, bits); + access(59, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; loadcs(new_cs); - do_access(66, bits); + access(66, bits); cpu_state.pc = new_ip; pfq_clear(); break; - case 0x30: /* PUSH rm */ case 0x38: if (cpu_mod != 3) - cpu_wait(1, 0); - do_access(38, bits); + wait(1, 0); + access(38, bits); if ((cpu_mod == 3) && (cpu_rm == 4)) - do_push(cpu_data - 2); + push(cpu_data - 2); else - do_push(cpu_data); + push(cpu_data); break; } break; @@ -2764,7 +2669,7 @@ opcodestart: default: ERRLOG("CPU: illegal opcode: %02X\n", opcode); pfq_fetchb(); - cpu_wait(8, 0); + wait(8, 0); break; } @@ -2777,29 +2682,20 @@ on_halt: if (in_lock) in_lock = 0; -#if 0 - /* FIXME: Find out why this is needed. */ - if ((romset == ROM_IBMPC) && ((cs + cpu_state.pc) == 0xFE4A7)) { - /* You didn't seriously think I was going to emulate the cassette, did you? */ - CX = 1; - BX = 0x500; - } -#endif - timer_end_period(cycles * xt_cpu_multi); if (trap && (flags & T_FLAG) && !noint) { halt = 0; - do_intr(1, 1); + interrupt(1, 1); } else if (nmi && nmi_enable && nmi_mask) { halt = 0; - do_intr(2, 1); + interrupt(2, 1); nmi_enable = 0; } else if (takeint && !noint) { temp = picinterrupt(); if (temp != 0xFF) { halt = 0; - do_intr(temp, 1); + interrupt(temp, 1); } } takeint = (flags & I_FLAG) && (pic.pend &~ pic.mask); @@ -2810,46 +2706,3 @@ 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/devices/input/keyboard_xt.c b/src/devices/input/keyboard_xt.c index 41e6a79..6fb1c09 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.11 2019/02/11 + * Version: @(#)keyboard_xt.c 1.0.12 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -67,6 +67,16 @@ #define STAT_OFULL 0x01 +enum { + KBC_PC = 0, /* IBM PC, 1981 */ + KBC_PC82, /* IBM PC, 1982 */ + KBC_XT, /* IBM PC/XT, 1982 */ + KBC_XT86, /* IBM PC/XT, 1986, and most clones */ + KBC_TANDY, /* Tandy XT */ + KBC_LASER /* VTech LaserXT */ +}; + + typedef struct { uint8_t type; int8_t tandy; @@ -466,8 +476,29 @@ kbd_write(uint16_t port, uint8_t val, void *priv) timer_update_outstanding(); speaker_update(); + + /* Enable or disable the PC Speaker. */ speaker_gated = val & 1; speaker_enable = val & 2; + + if (kbd->type <= KBC_PC82) { + /* + * Cassette Port present. + * + * Normally, the PC BIOS will disable the + * PC Speaker when doing cassette I/O, as + * they share the same hardware. + * + * For us, it is more fun to actually have + * that audio, so we do some tricks here. + */ + if (! (val & 0x08)) { + /* PB3, MotorOn - enable audio */ + speaker_gated = 1; + speaker_enable = 1; + } + } + if (speaker_enable) was_speaker_enable = 1; pit_set_gate(&pit, 2, val & 1); @@ -490,9 +521,10 @@ kbd_read(uint16_t port, void *priv) switch (port) { case 0x60: - if ((kbd->type <= 1) && (kbd->pb & 0x80)) + if ((kbd->type <= KBC_PC82) && (kbd->pb & 0x80)) ret = kbd->pd; - else if (((kbd->type == 2) || (kbd->type == 3)) && (kbd->pb & 0x80)) + else if (((kbd->type == KBC_XT) || (kbd->type == KBC_XT86)) && + (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; @@ -503,36 +535,41 @@ kbd_read(uint16_t port, void *priv) break; case 0x62: - if (! kbd->type) + if (kbd->type == KBC_PC) ret = 0x00; - else if (kbd->type == 1) { + else if (kbd->type == KBC_PC82) { if (kbd->pb & 0x04) ret = ((mem_size - 64) / 32) & 0x0f; else ret = ((mem_size - 64) / 32) >> 4; + } else { 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 == 5) + if (kbd->type == KBC_LASER) + /* LaserXT = Always 512k RAM; + * LaserXT/3 = Bit 0: 1=512K, 0=256K + */ ret = (mem_size == 512) ? 0x0d : 0x0c; else -#endif ret = kbd->pd & 0x0f; } + + if (kbd->type == KBC_TANDY) + ret |= (tandy1k_eeprom_read() ? 0x10 : 0); } + /* Indicate the PC SPEAKER state. */ ret |= (ppispeakon ? 0x20 : 0); - if (kbd->type == 4) - ret |= (tandy1k_eeprom_read() ? 0x10 : 0); + /* Make the IBM PC BIOS happy (Cassette Interface.) */ + if (kbd->type <= KBC_PC82) + ret |= (ppispeakon ? 0x10 : 0); + break; case 0x63: - if ((kbd->type == 2) || (kbd->type == 3)) + if ((kbd->type == KBC_XT) || (kbd->type == KBC_XT86)) ret = kbd->pd; break; @@ -570,19 +607,15 @@ kbd_init(const device_t *info) kbd = (xtkbd_t *)mem_alloc(sizeof(xtkbd_t)); memset(kbd, 0x00, sizeof(xtkbd_t)); - - io_sethandler(0x0060, 4, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); - - keyboard_send = kbd_adddata_ex; - 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++; - } + /* See how many diskette drives we have. */ + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + + if (kbd->type <= KBC_XT86) { /* * DIP switch readout: bit set = OFF, clear = ON. @@ -608,7 +641,8 @@ kbd_init(const device_t *info) kbd->pd |= 0x00; /* EGA/VGA */ /* Switches 3, 4 - memory size. */ - if (kbd->type == 3) { + if (kbd->type == KBC_XT86) { + /* PC/XT (1986) and up. */ switch (mem_size) { case 256: kbd->pd |= 0x00; @@ -627,7 +661,8 @@ kbd_init(const device_t *info) kbd->pd |= 0x0c; break; } - } else if (kbd->type == 2) { + } else if (kbd->type >= KBC_PC82) { + /* PC (1982) and PC/XT (1982.) */ switch (mem_size) { case 64: kbd->pd |= 0x00; @@ -647,6 +682,7 @@ kbd_init(const device_t *info) break; } } else { + /* PC (1981.) */ switch (mem_size) { case 16: kbd->pd |= 0x00; @@ -669,10 +705,17 @@ kbd_init(const device_t *info) /* Switch 2 - return bit clear (switch ON) because no 8087 right now. */ - /* Switch 1 - always off. */ + /* Switch 1 - diskette drives available? */ + if (fdd_count > 0) kbd->pd |= 0x01; } + keyboard_send = kbd_adddata_ex; + kbd_reset(kbd); + + io_sethandler(0x0060, 4, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, kbd); keyboard_set_table(scancode_xt); @@ -704,7 +747,7 @@ kbd_close(void *priv) const device_t keyboard_pc_device = { "IBM PC (1981) Keyboard", 0, - 0, + KBC_PC, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -713,7 +756,7 @@ const device_t keyboard_pc_device = { const device_t keyboard_pc82_device = { "IBM PC (1982) Keyboard", 0, - 1, + KBC_PC82, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -722,7 +765,7 @@ const device_t keyboard_pc82_device = { const device_t keyboard_xt_device = { "IBM PC/XT (1982) Keyboard", 0, - 2, + KBC_XT, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -731,7 +774,7 @@ const device_t keyboard_xt_device = { const device_t keyboard_xt86_device = { "IBM PC/XT (1986) Keyboard", 0, - 3, + KBC_XT86, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -740,7 +783,7 @@ const device_t keyboard_xt86_device = { const device_t keyboard_tandy_device = { "Tandy 1000 Keyboard", 0, - 4, + KBC_TANDY, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL @@ -749,11 +792,7 @@ const device_t keyboard_tandy_device = { const device_t keyboard_xt_lxt3_device = { "VTech Laser XT3 Keyboard", 0, -#if 1 - 3, -#else - 5, -#endif + KBC_LASER, kbd_init, kbd_close, kbd_reset, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/system/dma.c b/src/devices/system/dma.c index 5bdf7ec..424537a 100644 --- a/src/devices/system/dma.c +++ b/src/devices/system/dma.c @@ -1,915 +1,915 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel DMA controllers. - * - * Version: @(#)dma.c 1.0.8 2019/02/11 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * 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 - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../../emu.h" -#include "../../cpu/cpu.h" -#include "../../cpu/x86.h" -#include "../../machines/machine.h" -#include "../../mem.h" -#include "../../io.h" -#include "../../plat.h" -#include "mca.h" -#include "dma.h" - - -dma_t dma[8]; - - -static uint8_t dmaregs[16]; -static uint8_t dma16regs[16]; -static uint8_t dmapages[16]; -static int dma_wp, - dma16_wp; -static uint8_t dma_m; -static uint8_t dma_stat; -static uint8_t dma_stat_rq; -static uint8_t dma_command, - dma16_command; -static struct { - int xfr_command, - xfr_channel; - int byte_ptr; - - int is_ps2; -} dma_ps2; - - -#define DMA_PS2_IOA (1 << 0) -#define DMA_PS2_XFER_MEM_TO_IO (1 << 2) -#define DMA_PS2_XFER_IO_TO_MEM (3 << 2) -#define DMA_PS2_XFER_MASK (3 << 2) -#define DMA_PS2_DEC2 (1 << 4) -#define DMA_PS2_SIZE16 (1 << 6) - - -static uint8_t -_dma_read(int32_t addr) -{ - uint8_t temp = mem_readb_phys(addr); - - return(temp); -} - - -static void -_dma_write(uint32_t addr, uint8_t val) -{ - mem_writeb_phys(addr, val); - mem_invalidate_range(addr, addr); -} - - -static void -dma_ps2_run(int channel) -{ - dma_t *dma_c = &dma[channel]; - - switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK) { - case DMA_PS2_XFER_MEM_TO_IO: - do { - if (! dma_c->size) { - uint8_t temp = _dma_read(dma_c->ac); - - outb(dma_c->io_addr, temp); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } else { - uint16_t temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); - - outw(dma_c->io_addr, temp); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } - - dma_stat_rq |= (1 << channel); - dma_c->cc--; - } while (dma_c->cc > 0); - - dma_stat |= (1 << channel); - break; - - case DMA_PS2_XFER_IO_TO_MEM: - do { - if (! dma_c->size) { - uint8_t temp = inb(dma_c->io_addr); - - _dma_write(dma_c->ac, temp); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } else { - uint16_t temp = inw(dma_c->io_addr); - - _dma_write(dma_c->ac, temp & 0xff); - _dma_write(dma_c->ac + 1, temp >> 8); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } - - dma_stat_rq |= (1 << channel); - dma_c->cc--; - } while (dma_c->cc > 0); - - ps2_cache_clean(); - dma_stat |= (1 << channel); - break; - - default: /*Memory verify*/ - do { - if (! dma_c->size) { - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } else { - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } - - dma_stat_rq |= (1 << channel); - dma->cc--; - } while (dma->cc > 0); - - dma_stat |= (1 << channel); - break; - - } -} - - -static uint8_t -dma_ps2_read(uint16_t addr, UNUSED(void *priv)) -{ - dma_t *dma_c = &dma[dma_ps2.xfr_channel]; - uint8_t temp = 0xff; - - switch (addr) { - case 0x1a: - switch (dma_ps2.xfr_command) { - case 2: /*Address*/ - case 3: - switch (dma_ps2.byte_ptr) { - case 0: - temp = dma_c->ac & 0xff; - dma_ps2.byte_ptr = 1; - break; - case 1: - temp = (dma_c->ac >> 8) & 0xff; - dma_ps2.byte_ptr = 2; - break; - case 2: - temp = (dma_c->ac >> 16) & 0xff; - dma_ps2.byte_ptr = 0; - break; - } - break; - - case 4: /*Count*/ - case 5: - if (dma_ps2.byte_ptr) - temp = dma_c->cc >> 8; - else - temp = dma_c->cc & 0xff; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; - - case 6: /*Read DMA status*/ - if (dma_ps2.byte_ptr) { - temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0); - dma_stat &= ~0xf0; - dma_stat_rq &= ~0xf0; - } else { - temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4); - dma_stat &= ~0xf; - dma_stat_rq &= ~0xf; - } - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; - - case 7: /*Mode*/ - temp = dma_c->ps2_mode; - break; - - case 8: /*Arbitration Level*/ - temp = dma_c->arb_level; - break; - - default: - fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); - } - break; - } - - return(temp); -} - - -static void -dma_ps2_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) -{ - dma_t *dma_c = &dma[dma_ps2.xfr_channel]; - uint8_t mode; - - switch (addr) { - case 0x18: - dma_ps2.xfr_channel = val & 0x7; - dma_ps2.xfr_command = val >> 4; - dma_ps2.byte_ptr = 0; - switch (dma_ps2.xfr_command) { - case 9: /*Set DMA mask*/ - dma_m |= (1 << dma_ps2.xfr_channel); - break; - - case 0xa: /*Reset DMA mask*/ - dma_m &= ~(1 << dma_ps2.xfr_channel); - break; - - case 0xb: - if (!(dma_m & (1 << dma_ps2.xfr_channel))) - dma_ps2_run(dma_ps2.xfr_channel); - break; - } - break; - - case 0x1a: - switch (dma_ps2.xfr_command) { - case 0: /*I/O address*/ - if (dma_ps2.byte_ptr) - dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8); - else - dma_c->io_addr = (dma_c->io_addr & 0xff00) | val; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; - - case 2: /*Address*/ - switch (dma_ps2.byte_ptr) { - case 0: - dma_c->ac = (dma_c->ac & 0xffff00) | val; - dma_ps2.byte_ptr = 1; - break; - - case 1: - dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8); - dma_ps2.byte_ptr = 2; - break; - - case 2: - dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16); - dma_ps2.byte_ptr = 0; - break; - } - dma_c->ab = dma_c->ac; - break; - - case 4: /*Count*/ - if (dma_ps2.byte_ptr) - dma_c->cc = (dma_c->cc & 0xff) | (val << 8); - else - dma_c->cc = (dma_c->cc & 0xff00) | val; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - dma_c->cb = dma_c->cc; - break; - - case 7: /*Mode register*/ - mode = 0; - if (val & DMA_PS2_DEC2) - mode |= 0x20; - if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO) - mode |= 8; - else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) - mode |= 4; - dma_c->mode = (dma_c->mode & ~0x2c) | mode; - dma_c->ps2_mode = val; - dma_c->size = val & DMA_PS2_SIZE16; - break; - - case 8: /*Arbitration Level*/ - dma_c->arb_level = val; - break; - - default: - fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); - } - break; - } -} - - -static uint8_t -dma_read(uint16_t addr, UNUSED(void *priv)) -{ - int channel = (addr >> 1) & 3; - uint8_t temp; - - switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma_wp ^= 1; - if (dma_wp) - return(dma[channel].ac & 0xff); - return((dma[channel].ac >> 8) & 0xff); - - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma_wp ^= 1; - if (dma_wp) - temp = dma[channel].cc & 0xff; - else - temp = dma[channel].cc >> 8; - return(temp); - - case 8: /*Status register*/ - temp = dma_stat & 0xf; - dma_stat &= ~0xf; - return(temp); - - case 0xd: - return(0); - } - - return(dmaregs[addr & 0xf]); -} - - -static void -dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) -{ - int channel = (addr >> 1) & 3; - - dmaregs[addr & 0xf] = val; - switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma_wp ^= 1; - if (dma_wp) - dma[channel].ab = (dma[channel].ab & 0xffff00) | val; - else - dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); - dma[channel].ac = dma[channel].ab; - return; - - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma_wp ^= 1; - if (dma_wp) - dma[channel].cb = (dma[channel].cb & 0xff00) | val; - else - dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); - dma[channel].cc = dma[channel].cb; - return; - - case 8: /*Control register*/ - dma_command = val; - return; - - case 0xa: /*Mask*/ - if (val & 4) - dma_m |= (1 << (val & 3)); - else - dma_m &= ~(1 << (val & 3)); - return; - - case 0xb: /*Mode*/ - channel = (val & 3); - dma[channel].mode = val; - if (dma_ps2.is_ps2) { - dma[channel].ps2_mode &= ~0x1c; - if (val & 0x20) - dma[channel].ps2_mode |= 0x10; - if ((val & 0xc) == 8) - dma[channel].ps2_mode |= 4; - else if ((val & 0xc) == 4) - dma[channel].ps2_mode |= 0xc; - } - return; - - case 0xc: /*Clear FF*/ - dma_wp = 0; - return; - - case 0xd: /*Master clear*/ - dma_wp = 0; - dma_m |= 0xf; - return; - - case 0xf: /*Mask write*/ - dma_m = (dma_m & 0xf0) | (val & 0xf); - return; - } -} - - -static uint8_t -dma16_read(uint16_t addr, UNUSED(void *priv)) -{ - int channel = ((addr >> 2) & 3) + 4; - uint8_t temp; - - addr >>= 1; - switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma16_wp ^= 1; - if (dma_ps2.is_ps2) { - if (dma16_wp) - return(dma[channel].ac); - return((dma[channel].ac >> 8) & 0xff); - } - if (dma16_wp) - return((dma[channel].ac >> 1) & 0xff); - return((dma[channel].ac >> 9) & 0xff); - - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma16_wp ^= 1; - if (dma16_wp) - temp = dma[channel].cc & 0xff; - else - temp = dma[channel].cc >> 8; - return(temp); - - case 8: /*Status register*/ - temp = dma_stat >> 4; - dma_stat &= ~0xf0; - return(temp); - } - - return(dma16regs[addr & 0xf]); -} - - -static void -dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) -{ - int channel = ((addr >> 2) & 3) + 4; - addr >>= 1; - - dma16regs[addr & 0xf] = val; - switch (addr & 0xf) { - case 0: - case 2: - case 4: - case 6: /*Address registers*/ - dma16_wp ^= 1; - if (dma_ps2.is_ps2) { - if (dma16_wp) - dma[channel].ab = (dma[channel].ab & 0xffff00) | val; - else - dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); - } else { - if (dma16_wp) - dma[channel].ab = (dma[channel].ab & 0xfffe00) | (val << 1); - else - dma[channel].ab = (dma[channel].ab & 0xfe01ff) | (val << 9); - } - dma[channel].ac = dma[channel].ab; - return; - - case 1: - case 3: - case 5: - case 7: /*Count registers*/ - dma16_wp ^= 1; - if (dma16_wp) - dma[channel].cb = (dma[channel].cb & 0xff00) | val; - else - dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); - dma[channel].cc = dma[channel].cb; - return; - - case 8: /*Control register*/ - return; - - case 0xa: /*Mask*/ - if (val & 4) - dma_m |= (0x10 << (val & 3)); - else - dma_m &= ~(0x10 << (val & 3)); - return; - - case 0xb: /*Mode*/ - channel = (val & 3) + 4; - dma[channel].mode = val; - if (dma_ps2.is_ps2) { - dma[channel].ps2_mode &= ~0x1c; - if (val & 0x20) - dma[channel].ps2_mode |= 0x10; - if ((val & 0xc) == 8) - dma[channel].ps2_mode |= 4; - else if ((val & 0xc) == 4) - dma[channel].ps2_mode |= 0xc; - } - return; - - case 0xc: /*Clear FF*/ - dma16_wp = 0; - return; - - case 0xd: /*Master clear*/ - dma16_wp = 0; - dma_m |= 0xf0; - return; - - case 0xf: /*Mask write*/ - dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4); - return; - } -} - - -static uint8_t -dma_page_read(uint16_t addr, UNUSED(void *priv)) -{ - return(dmapages[addr & 0xf]); -} - - -static void -dma_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) -{ - dmapages[addr & 0xf] = val; - - switch (addr & 0xf) { - case 1: - dma[2].page = (AT) ? val : val & 0xf; - dma[2].ab = (dma[2].ab & 0xffff) | (dma[2].page << 16); - dma[2].ac = (dma[2].ac & 0xffff) | (dma[2].page << 16); - break; - - case 2: - dma[3].page = (AT) ? val : val & 0xf; - dma[3].ab = (dma[3].ab & 0xffff) | (dma[3].page << 16); - dma[3].ac = (dma[3].ac & 0xffff) | (dma[3].page << 16); - break; - - case 3: - dma[1].page = (AT) ? val : val & 0xf; - dma[1].ab = (dma[1].ab & 0xffff) | (dma[1].page << 16); - dma[1].ac = (dma[1].ac & 0xffff) | (dma[1].page << 16); - break; - - case 7: - dma[0].page = (AT) ? val : val & 0xf; - dma[0].ab = (dma[0].ab & 0xffff) | (dma[0].page << 16); - dma[0].ac = (dma[0].ac & 0xffff) | (dma[0].page << 16); - break; - - case 0x9: - dma[6].page = val & 0xfe; - dma[6].ab = (dma[6].ab & 0x1ffff) | (dma[6].page << 16); - dma[6].ac = (dma[6].ac & 0x1ffff) | (dma[6].page << 16); - break; - - case 0xa: - dma[7].page = val & 0xfe; - dma[7].ab = (dma[7].ab & 0x1ffff) | (dma[7].page << 16); - dma[7].ac = (dma[7].ac & 0x1ffff) | (dma[7].page << 16); - break; - - case 0xb: - dma[5].page = val & 0xfe; - dma[5].ab = (dma[5].ab & 0x1ffff) | (dma[5].page << 16); - dma[5].ac = (dma[5].ac & 0x1ffff) | (dma[5].page << 16); - break; - - case 0xf: - dma[4].page = val & 0xfe; - dma[4].ab = (dma[4].ab & 0x1ffff) | (dma[4].page << 16); - dma[4].ac = (dma[4].ac & 0x1ffff) | (dma[4].page << 16); - break; - } -} - - -void -dma_reset(void) -{ - int c; - - dma_wp = dma16_wp = 0; - dma_m = 0; - - for (c = 0; c < 16; c++) - dmaregs[c] = 0; - for (c = 0; c < 8; c++) { - dma[c].mode = 0; - dma[c].ac = 0; - dma[c].cc = 0; - dma[c].ab = 0; - dma[c].cb = 0; - dma[c].size = (c & 4) ? 1 : 0; - } -} - - -void -dma_init(void) -{ - io_sethandler(0x0000, 16, - dma_read,NULL,NULL, dma_write,NULL,NULL, NULL); - io_sethandler(0x0080, 8, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); - dma_ps2.is_ps2 = 0; -} - - -void -dma16_init(void) -{ - io_sethandler(0x00C0, 32, - dma16_read,NULL,NULL, dma16_write,NULL,NULL, NULL); - io_sethandler(0x0088, 8, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); -} - - -void -dma_alias_set(void) -{ - io_sethandler(0x0090, 16, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); -} - - -void -dma_alias_remove(void) -{ - io_removehandler(0x0090, 16, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); -} - - -void -dma_alias_remove_piix(void) -{ - io_removehandler(0x0090, 1, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); - io_removehandler(0x0094, 3, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); - io_removehandler(0x0098, 1, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); - io_removehandler(0x009C, 3, - dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); -} - - -void -ps2_dma_init(void) -{ - io_sethandler(0x0018, 1, - dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); - io_sethandler(0x001a, 1, - dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); - dma_ps2.is_ps2 = 1; -} - - -int -dma_channel_read(int channel) -{ - dma_t *dma_c = &dma[channel]; - uint16_t temp; - int tc = 0; - - if (channel < 4) { - if (dma_command & 0x04) - return(DMA_NODATA); - } else { - if (dma16_command & 0x04) - return(DMA_NODATA); - } - - if (dma_m & (1 << channel)) - return(DMA_NODATA); - if ((dma_c->mode & 0xC) != 8) - return(DMA_NODATA); - - if (! AT) - refreshread(); - - if (! dma_c->size) { - temp = _dma_read(dma_c->ac); - - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac--; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac++; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); - } - } else { - temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); - - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac -= 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac += 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); - } - } - - dma_stat_rq |= (1 << channel); - - dma_c->cc--; - if (dma_c->cc < 0) { - tc = 1; - if (dma_c->mode & 0x10) { /*Auto-init*/ - dma_c->cc = dma_c->cb; - dma_c->ac = dma_c->ab; - } else - dma_m |= (1 << channel); - dma_stat |= (1 << channel); - } - - if (tc) - return(temp | DMA_OVER); - - return(temp); -} - - -int -dma_channel_write(int channel, uint16_t val) -{ - dma_t *dma_c = &dma[channel]; - - if (channel < 4) { - if (dma_command & 0x04) - return(DMA_NODATA); - } else { - if (dma16_command & 0x04) - return(DMA_NODATA); - } - - if (dma_m & (1 << channel)) - return(DMA_NODATA); - if ((dma_c->mode & 0xC) != 4) - return(DMA_NODATA); - - if (! AT) - refreshread(); - - if (! dma_c->size) { - _dma_write(dma_c->ac, val & 0xff); - - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac--; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac++; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); - } - } else { - _dma_write(dma_c->ac, val & 0xff); - _dma_write(dma_c->ac + 1, val >> 8); - - if (dma_c->mode & 0x20) { - if (dma_ps2.is_ps2) - dma_c->ac -= 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); - } else { - if (dma_ps2.is_ps2) - dma_c->ac += 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Intel DMA controllers. + * + * Version: @(#)dma.c 1.0.8 2019/02/11 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * 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 + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../cpu/x86.h" +#include "../../machines/machine.h" +#include "../../mem.h" +#include "../../io.h" +#include "../../plat.h" +#include "mca.h" +#include "dma.h" + + +dma_t dma[8]; + + +static uint8_t dmaregs[16]; +static uint8_t dma16regs[16]; +static uint8_t dmapages[16]; +static int dma_wp, + dma16_wp; +static uint8_t dma_m; +static uint8_t dma_stat; +static uint8_t dma_stat_rq; +static uint8_t dma_command, + dma16_command; +static struct { + int xfr_command, + xfr_channel; + int byte_ptr; + + int is_ps2; +} dma_ps2; + + +#define DMA_PS2_IOA (1 << 0) +#define DMA_PS2_XFER_MEM_TO_IO (1 << 2) +#define DMA_PS2_XFER_IO_TO_MEM (3 << 2) +#define DMA_PS2_XFER_MASK (3 << 2) +#define DMA_PS2_DEC2 (1 << 4) +#define DMA_PS2_SIZE16 (1 << 6) + + +static uint8_t +_dma_read(int32_t addr) +{ + uint8_t temp = mem_readb_phys(addr); + + return(temp); +} + + +static void +_dma_write(uint32_t addr, uint8_t val) +{ + mem_writeb_phys(addr, val); + mem_invalidate_range(addr, addr); +} + + +static void +dma_ps2_run(int channel) +{ + dma_t *dma_c = &dma[channel]; + + switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK) { + case DMA_PS2_XFER_MEM_TO_IO: + do { + if (! dma_c->size) { + uint8_t temp = _dma_read(dma_c->ac); + + outb(dma_c->io_addr, temp); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + uint16_t temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); + + outw(dma_c->io_addr, temp); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } + + dma_stat_rq |= (1 << channel); + dma_c->cc--; + } while (dma_c->cc > 0); + + dma_stat |= (1 << channel); + break; + + case DMA_PS2_XFER_IO_TO_MEM: + do { + if (! dma_c->size) { + uint8_t temp = inb(dma_c->io_addr); + + _dma_write(dma_c->ac, temp); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + uint16_t temp = inw(dma_c->io_addr); + + _dma_write(dma_c->ac, temp & 0xff); + _dma_write(dma_c->ac + 1, temp >> 8); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } + + dma_stat_rq |= (1 << channel); + dma_c->cc--; + } while (dma_c->cc > 0); + + ps2_cache_clean(); + dma_stat |= (1 << channel); + break; + + default: /*Memory verify*/ + do { + if (! dma_c->size) { + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } + + dma_stat_rq |= (1 << channel); + dma->cc--; + } while (dma->cc > 0); + + dma_stat |= (1 << channel); + break; + + } +} + + +static uint8_t +dma_ps2_read(uint16_t addr, UNUSED(void *priv)) +{ + dma_t *dma_c = &dma[dma_ps2.xfr_channel]; + uint8_t temp = 0xff; + + switch (addr) { + case 0x1a: + switch (dma_ps2.xfr_command) { + case 2: /*Address*/ + case 3: + switch (dma_ps2.byte_ptr) { + case 0: + temp = dma_c->ac & 0xff; + dma_ps2.byte_ptr = 1; + break; + case 1: + temp = (dma_c->ac >> 8) & 0xff; + dma_ps2.byte_ptr = 2; + break; + case 2: + temp = (dma_c->ac >> 16) & 0xff; + dma_ps2.byte_ptr = 0; + break; + } + break; + + case 4: /*Count*/ + case 5: + if (dma_ps2.byte_ptr) + temp = dma_c->cc >> 8; + else + temp = dma_c->cc & 0xff; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; + + case 6: /*Read DMA status*/ + if (dma_ps2.byte_ptr) { + temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0); + dma_stat &= ~0xf0; + dma_stat_rq &= ~0xf0; + } else { + temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4); + dma_stat &= ~0xf; + dma_stat_rq &= ~0xf; + } + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; + + case 7: /*Mode*/ + temp = dma_c->ps2_mode; + break; + + case 8: /*Arbitration Level*/ + temp = dma_c->arb_level; + break; + + default: + fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); + } + break; + } + + return(temp); +} + + +static void +dma_ps2_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + dma_t *dma_c = &dma[dma_ps2.xfr_channel]; + uint8_t mode; + + switch (addr) { + case 0x18: + dma_ps2.xfr_channel = val & 0x7; + dma_ps2.xfr_command = val >> 4; + dma_ps2.byte_ptr = 0; + switch (dma_ps2.xfr_command) { + case 9: /*Set DMA mask*/ + dma_m |= (1 << dma_ps2.xfr_channel); + break; + + case 0xa: /*Reset DMA mask*/ + dma_m &= ~(1 << dma_ps2.xfr_channel); + break; + + case 0xb: + if (!(dma_m & (1 << dma_ps2.xfr_channel))) + dma_ps2_run(dma_ps2.xfr_channel); + break; + } + break; + + case 0x1a: + switch (dma_ps2.xfr_command) { + case 0: /*I/O address*/ + if (dma_ps2.byte_ptr) + dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8); + else + dma_c->io_addr = (dma_c->io_addr & 0xff00) | val; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; + + case 2: /*Address*/ + switch (dma_ps2.byte_ptr) { + case 0: + dma_c->ac = (dma_c->ac & 0xffff00) | val; + dma_ps2.byte_ptr = 1; + break; + + case 1: + dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8); + dma_ps2.byte_ptr = 2; + break; + + case 2: + dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16); + dma_ps2.byte_ptr = 0; + break; + } + dma_c->ab = dma_c->ac; + break; + + case 4: /*Count*/ + if (dma_ps2.byte_ptr) + dma_c->cc = (dma_c->cc & 0xff) | (val << 8); + else + dma_c->cc = (dma_c->cc & 0xff00) | val; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + dma_c->cb = dma_c->cc; + break; + + case 7: /*Mode register*/ + mode = 0; + if (val & DMA_PS2_DEC2) + mode |= 0x20; + if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO) + mode |= 8; + else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) + mode |= 4; + dma_c->mode = (dma_c->mode & ~0x2c) | mode; + dma_c->ps2_mode = val; + dma_c->size = val & DMA_PS2_SIZE16; + break; + + case 8: /*Arbitration Level*/ + dma_c->arb_level = val; + break; + + default: + fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); + } + break; + } +} + + +static uint8_t +dma_read(uint16_t addr, UNUSED(void *priv)) +{ + int channel = (addr >> 1) & 3; + uint8_t temp; + + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp ^= 1; + if (dma_wp) + return(dma[channel].ac & 0xff); + return((dma[channel].ac >> 8) & 0xff); + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp ^= 1; + if (dma_wp) + temp = dma[channel].cc & 0xff; + else + temp = dma[channel].cc >> 8; + return(temp); + + case 8: /*Status register*/ + temp = dma_stat & 0xf; + dma_stat &= ~0xf; + return(temp); + + case 0xd: + return(0); + } + + return(dmaregs[addr & 0xf]); +} + + +static void +dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + int channel = (addr >> 1) & 3; + + dmaregs[addr & 0xf] = val; + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp ^= 1; + if (dma_wp) + dma[channel].ab = (dma[channel].ab & 0xffff00) | val; + else + dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); + dma[channel].ac = dma[channel].ab; + return; + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp ^= 1; + if (dma_wp) + dma[channel].cb = (dma[channel].cb & 0xff00) | val; + else + dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); + dma[channel].cc = dma[channel].cb; + return; + + case 8: /*Control register*/ + dma_command = val; + return; + + case 0xa: /*Mask*/ + if (val & 4) + dma_m |= (1 << (val & 3)); + else + dma_m &= ~(1 << (val & 3)); + return; + + case 0xb: /*Mode*/ + channel = (val & 3); + dma[channel].mode = val; + if (dma_ps2.is_ps2) { + dma[channel].ps2_mode &= ~0x1c; + if (val & 0x20) + dma[channel].ps2_mode |= 0x10; + if ((val & 0xc) == 8) + dma[channel].ps2_mode |= 4; + else if ((val & 0xc) == 4) + dma[channel].ps2_mode |= 0xc; + } + return; + + case 0xc: /*Clear FF*/ + dma_wp = 0; + return; + + case 0xd: /*Master clear*/ + dma_wp = 0; + dma_m |= 0xf; + return; + + case 0xf: /*Mask write*/ + dma_m = (dma_m & 0xf0) | (val & 0xf); + return; + } +} + + +static uint8_t +dma16_read(uint16_t addr, UNUSED(void *priv)) +{ + int channel = ((addr >> 2) & 3) + 4; + uint8_t temp; + + addr >>= 1; + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma16_wp ^= 1; + if (dma_ps2.is_ps2) { + if (dma16_wp) + return(dma[channel].ac); + return((dma[channel].ac >> 8) & 0xff); + } + if (dma16_wp) + return((dma[channel].ac >> 1) & 0xff); + return((dma[channel].ac >> 9) & 0xff); + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma16_wp ^= 1; + if (dma16_wp) + temp = dma[channel].cc & 0xff; + else + temp = dma[channel].cc >> 8; + return(temp); + + case 8: /*Status register*/ + temp = dma_stat >> 4; + dma_stat &= ~0xf0; + return(temp); + } + + return(dma16regs[addr & 0xf]); +} + + +static void +dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + int channel = ((addr >> 2) & 3) + 4; + addr >>= 1; + + dma16regs[addr & 0xf] = val; + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma16_wp ^= 1; + if (dma_ps2.is_ps2) { + if (dma16_wp) + dma[channel].ab = (dma[channel].ab & 0xffff00) | val; + else + dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); + } else { + if (dma16_wp) + dma[channel].ab = (dma[channel].ab & 0xfffe00) | (val << 1); + else + dma[channel].ab = (dma[channel].ab & 0xfe01ff) | (val << 9); + } + dma[channel].ac = dma[channel].ab; + return; + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma16_wp ^= 1; + if (dma16_wp) + dma[channel].cb = (dma[channel].cb & 0xff00) | val; + else + dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); + dma[channel].cc = dma[channel].cb; + return; + + case 8: /*Control register*/ + return; + + case 0xa: /*Mask*/ + if (val & 4) + dma_m |= (0x10 << (val & 3)); + else + dma_m &= ~(0x10 << (val & 3)); + return; + + case 0xb: /*Mode*/ + channel = (val & 3) + 4; + dma[channel].mode = val; + if (dma_ps2.is_ps2) { + dma[channel].ps2_mode &= ~0x1c; + if (val & 0x20) + dma[channel].ps2_mode |= 0x10; + if ((val & 0xc) == 8) + dma[channel].ps2_mode |= 4; + else if ((val & 0xc) == 4) + dma[channel].ps2_mode |= 0xc; + } + return; + + case 0xc: /*Clear FF*/ + dma16_wp = 0; + return; + + case 0xd: /*Master clear*/ + dma16_wp = 0; + dma_m |= 0xf0; + return; + + case 0xf: /*Mask write*/ + dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4); + return; + } +} + + +static uint8_t +dma_page_read(uint16_t addr, UNUSED(void *priv)) +{ + return(dmapages[addr & 0xf]); +} + + +static void +dma_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + dmapages[addr & 0xf] = val; + + switch (addr & 0xf) { + case 1: + dma[2].page = (AT) ? val : val & 0xf; + dma[2].ab = (dma[2].ab & 0xffff) | (dma[2].page << 16); + dma[2].ac = (dma[2].ac & 0xffff) | (dma[2].page << 16); + break; + + case 2: + dma[3].page = (AT) ? val : val & 0xf; + dma[3].ab = (dma[3].ab & 0xffff) | (dma[3].page << 16); + dma[3].ac = (dma[3].ac & 0xffff) | (dma[3].page << 16); + break; + + case 3: + dma[1].page = (AT) ? val : val & 0xf; + dma[1].ab = (dma[1].ab & 0xffff) | (dma[1].page << 16); + dma[1].ac = (dma[1].ac & 0xffff) | (dma[1].page << 16); + break; + + case 7: + dma[0].page = (AT) ? val : val & 0xf; + dma[0].ab = (dma[0].ab & 0xffff) | (dma[0].page << 16); + dma[0].ac = (dma[0].ac & 0xffff) | (dma[0].page << 16); + break; + + case 0x9: + dma[6].page = val & 0xfe; + dma[6].ab = (dma[6].ab & 0x1ffff) | (dma[6].page << 16); + dma[6].ac = (dma[6].ac & 0x1ffff) | (dma[6].page << 16); + break; + + case 0xa: + dma[7].page = val & 0xfe; + dma[7].ab = (dma[7].ab & 0x1ffff) | (dma[7].page << 16); + dma[7].ac = (dma[7].ac & 0x1ffff) | (dma[7].page << 16); + break; + + case 0xb: + dma[5].page = val & 0xfe; + dma[5].ab = (dma[5].ab & 0x1ffff) | (dma[5].page << 16); + dma[5].ac = (dma[5].ac & 0x1ffff) | (dma[5].page << 16); + break; + + case 0xf: + dma[4].page = val & 0xfe; + dma[4].ab = (dma[4].ab & 0x1ffff) | (dma[4].page << 16); + dma[4].ac = (dma[4].ac & 0x1ffff) | (dma[4].page << 16); + break; + } +} + + +void +dma_reset(void) +{ + int c; + + dma_wp = dma16_wp = 0; + dma_m = 0; + + for (c = 0; c < 16; c++) + dmaregs[c] = 0; + for (c = 0; c < 8; c++) { + dma[c].mode = 0; + dma[c].ac = 0; + dma[c].cc = 0; + dma[c].ab = 0; + dma[c].cb = 0; + dma[c].size = (c & 4) ? 1 : 0; + } +} + + +void +dma_init(void) +{ + io_sethandler(0x0000, 16, + dma_read,NULL,NULL, dma_write,NULL,NULL, NULL); + io_sethandler(0x0080, 8, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_ps2.is_ps2 = 0; +} + + +void +dma16_init(void) +{ + io_sethandler(0x00C0, 32, + dma16_read,NULL,NULL, dma16_write,NULL,NULL, NULL); + io_sethandler(0x0088, 8, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +dma_alias_set(void) +{ + io_sethandler(0x0090, 16, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +dma_alias_remove(void) +{ + io_removehandler(0x0090, 16, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +dma_alias_remove_piix(void) +{ + io_removehandler(0x0090, 1, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_removehandler(0x0094, 3, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_removehandler(0x0098, 1, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_removehandler(0x009C, 3, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +ps2_dma_init(void) +{ + io_sethandler(0x0018, 1, + dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); + io_sethandler(0x001a, 1, + dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); + dma_ps2.is_ps2 = 1; +} + + +int +dma_channel_read(int channel) +{ + dma_t *dma_c = &dma[channel]; + uint16_t temp; + int tc = 0; + + if (channel < 4) { + if (dma_command & 0x04) + return(DMA_NODATA); + } else { + if (dma16_command & 0x04) + return(DMA_NODATA); + } + + if (dma_m & (1 << channel)) + return(DMA_NODATA); + if ((dma_c->mode & 0xC) != 8) + return(DMA_NODATA); + + if (! AT) + refreshread(); + + if (! dma_c->size) { + temp = _dma_read(dma_c->ac); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); } - } - - dma_stat_rq |= (1 << channel); - - dma_c->cc--; - if (dma_c->cc < 0) { - if (dma_c->mode & 0x10) { /*Auto-init*/ - dma_c->cc = dma_c->cb; - dma_c->ac = dma_c->ab; - } else - dma_m |= (1 << channel); - dma_stat |= (1 << channel); - } - - if (dma_m & (1 << channel)) - return(DMA_OVER); - - return(0); -} - - -int -dma_mode(int channel) -{ - if (channel < 4) - return(dma[channel].mode); - else - return(dma[channel & 3].mode); -} - - -/* DMA Bus Master Page Read/Write */ -void -DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize) -{ - uint32_t i = 0; - -#if 0 - memcpy(DataRead, &ram[PhysAddress], TotalSize); -#else - for (i = 0; i < TotalSize; i++) - DataRead[i] = mem_readb_phys(PhysAddress + i); -#endif -} - - -void -DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize) -{ - uint32_t i = 0; - -#if 0 - mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); - memcpy(&ram[PhysAddress], DataWrite, TotalSize); -#else - for (i = 0; i < TotalSize; i++) - mem_writeb_phys(PhysAddress + i, DataWrite[i]); - - mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); -#endif -} + } else { + temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); + } + } + + dma_stat_rq |= (1 << channel); + + dma_c->cc--; + if (dma_c->cc < 0) { + tc = 1; + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } + + if (tc) + return(temp | DMA_OVER); + + return(temp); +} + + +int +dma_channel_write(int channel, uint16_t val) +{ + dma_t *dma_c = &dma[channel]; + + if (channel < 4) { + if (dma_command & 0x04) + return(DMA_NODATA); + } else { + if (dma16_command & 0x04) + return(DMA_NODATA); + } + + if (dma_m & (1 << channel)) + return(DMA_NODATA); + if ((dma_c->mode & 0xC) != 4) + return(DMA_NODATA); + + if (! AT) + refreshread(); + + if (! dma_c->size) { + _dma_write(dma_c->ac, val & 0xff); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); + } + } else { + _dma_write(dma_c->ac, val & 0xff); + _dma_write(dma_c->ac + 1, val >> 8); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); + } + } + + dma_stat_rq |= (1 << channel); + + dma_c->cc--; + if (dma_c->cc < 0) { + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } + + if (dma_m & (1 << channel)) + return(DMA_OVER); + + return(0); +} + + +int +dma_mode(int channel) +{ + if (channel < 4) + return(dma[channel].mode); + else + return(dma[channel & 3].mode); +} + + +/* DMA Bus Master Page Read/Write */ +void +DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize) +{ + uint32_t i = 0; + +#if 0 + memcpy(DataRead, &ram[PhysAddress], TotalSize); +#else + for (i = 0; i < TotalSize; i++) + DataRead[i] = mem_readb_phys(PhysAddress + i); +#endif +} + + +void +DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize) +{ + uint32_t i = 0; + +#if 0 + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); + memcpy(&ram[PhysAddress], DataWrite, TotalSize); +#else + for (i = 0; i < TotalSize; i++) + mem_writeb_phys(PhysAddress + i, DataWrite[i]); + + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); +#endif +} diff --git a/src/devices/system/pit.c b/src/devices/system/pit.c index 217187c..aa8a314 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.9 2019/02/11 + * Version: @(#)pit.c 1.0.8 2019/02/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -67,7 +67,7 @@ int firsttime = 1; PIT pit, pit2; float cpuclock; -float bus_timing; +float isa_timing, bus_timing; double PITCONST; float CGACONST; float MDACONST; @@ -636,84 +636,60 @@ pit_reset(PIT *dev) } -/* Set default CPU/crystal clock and xt_cpu_multi. */ void setrtcconst(float clock) { - cpuclock = 14318184.0; + RTCCONST = clock / (float)32768.0; - 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); + TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1LL << TIMER_SHIFT)); } 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(); } @@ -759,39 +735,6 @@ 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) { @@ -799,9 +742,8 @@ 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] = pit_read_timer_ex(dev, t); + dev->c[t] = (int64_t)((((int64_t) dev->count[t]) << TIMER_SHIFT) * PITCONST); dev->using_timer[t] = using_timer; dev->running[t] = dev->enabled[t] && diff --git a/src/devices/system/pit.h b/src/devices/system/pit.h index 9f9f9ee..a926c4c 100644 --- a/src/devices/system/pit.h +++ b/src/devices/system/pit.h @@ -8,14 +8,14 @@ * * Definitions for Intel 8253 timer module. * - * Version: @(#)pit.h 1.0.4 2018/09/05 + * Version: @(#)pit.h 1.0.5 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 @@ -80,7 +80,9 @@ typedef struct PIT { extern PIT pit, pit2; + extern double PITCONST; + extern float CGACONST, MDACONST, VGACONST1, diff --git a/src/devices/video/vid_cga.c b/src/devices/video/vid_cga.c index 9073327..db70ffd 100644 --- a/src/devices/video/vid_cga.c +++ b/src/devices/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.9 2019/02/10 + * Version: @(#)vid_cga.c 1.0.10 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -74,7 +74,7 @@ static const int ws_array[16] = {3,4,5,6,7,8,4,5,6,7,8,4,5,6,7,8}; static const video_timings_t cga_timing = { VID_ISA,8,16,32,8,16,32 }; -#ifdef _DEBUG +#if defined(_DEBUG) && defined(CGA_DEBUG) void cga_print(cga_t *dev) { @@ -545,7 +545,7 @@ cga_poll(void *priv) else x = (dev->crtc[1] << 4) + 16; dev->lastline++; -#ifdef _DEBUG +#if defined(_DEBUG) && defined(CGA_DEBUG) cga_print(dev); #endif if ((dev->cgamode & 8) && x && (dev->lastline - dev->firstline) && diff --git a/src/devices/video/vid_hercules.c b/src/devices/video/vid_hercules.c index da58be4..f656afa 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.13 2019/02/11 + * Version: @(#)vid_hercules.c 1.0.14 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -140,14 +140,14 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) dev->crtc[11] = 0xc; } - if (old ^ val) + if (old != val) recalc_timings(dev); break; case 0x03b8: old = dev->ctrl; dev->ctrl = val; - if (old ^ val) + if (old != val) recalc_timings(dev); break; @@ -190,6 +190,7 @@ hercules_in(uint16_t addr, void *priv) ret = 0x72; /* Hercules ident */ if (dev->stat & 0x08) ret |= 0x88; + ret |= (dev->stat & 0x01); break; default: diff --git a/src/devices/video/vid_herculesplus.c b/src/devices/video/vid_herculesplus.c index e22e345..ce3562f 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.14 2019/02/11 + * Version: @(#)vid_hercules_plus.c 1.0.15 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -154,14 +154,14 @@ herculesplus_out(uint16_t port, uint8_t val, void *priv) dev->crtc[10] = 0xb; dev->crtc[11] = 0xc; } - if (old ^ val) + if (old != val) recalc_timings(dev); return; case 0x03b8: old = dev->ctrl; dev->ctrl = val; - if (old ^ val) + if (old != val) recalc_timings(dev); return; @@ -199,8 +199,8 @@ herculesplus_in(uint16_t port, void *priv) break; case 0x03ba: - /* 0x50: InColor card identity */ - ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; + /* 0x10: HerculesPlus card identity */ + ret = (dev->stat & 0x0f) | ((dev->stat & 8) << 4) | 0x10; break; } diff --git a/src/devices/video/vid_incolor.c b/src/devices/video/vid_incolor.c index 835f5bc..2964c74 100644 --- a/src/devices/video/vid_incolor.c +++ b/src/devices/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.12 2019/02/11 + * Version: @(#)vid_incolor.c 1.0.13 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -256,14 +256,14 @@ incolor_out(uint16_t port, uint8_t val, void *priv) dev->crtc[10] = 0xb; dev->crtc[11] = 0xc; } - if (old ^ val) + if (old != val) recalc_timings(dev); return; case 0x03b8: old = dev->ctrl; dev->ctrl = val; - if (old ^ val) + if (old != val) recalc_timings(dev); return; diff --git a/src/devices/video/video.c b/src/devices/video/video.c index fd618a0..9fa49ed 100644 --- a/src/devices/video/video.c +++ b/src/devices/video/video.c @@ -40,14 +40,14 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.23 2018/11/03 + * Version: @(#)video.c 1.0.24 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 @@ -110,6 +110,7 @@ int changeframecount = 2; uint8_t rotatevga[8][256]; int frames = 0; int fullchange = 0; +int displine = 0; uint8_t edatlookup[4][4]; int update_overscan = 0; int overscan_x = 0, diff --git a/src/machines/m_xt.c b/src/machines/m_xt.c index 2e7608f..2242afd 100644 --- a/src/machines/m_xt.c +++ b/src/machines/m_xt.c @@ -8,7 +8,7 @@ * * Implementation of standard IBM PC/XT class machine. * - * Version: @(#)m_xt.c 1.0.12 2019/02/11 + * Version: @(#)m_xt.c 1.0.13 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,9 +51,6 @@ #include "machine.h" -static int rom_basic = 0; /* is ROM BASIC enabled? */ - - static const device_config_t pcxt_config[] = { { "rom_basic", "ROM BASIC", CONFIG_SELECTION, "", 0, @@ -79,6 +76,8 @@ static const device_config_t pcxt_config[] = { void machine_pc_common_init(const machine_t *model, void *arg) { + int rom_basic; + machine_common_init(model, arg); /* Check if we support a BASIC ROM. */ diff --git a/src/machines/machine.c b/src/machines/machine.c index dcf3216..8613a56 100644 --- a/src/machines/machine.c +++ b/src/machines/machine.c @@ -8,13 +8,13 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.16 2018/09/22 + * Version: @(#)machine.c 1.0.17 2019/02/12 * * 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. * @@ -53,6 +53,7 @@ #include "../devices/ports/parallel.h" #include "../devices/video/video.h" #include "../plat.h" +#include "../ui/ui.h" #include "machine.h" @@ -79,7 +80,17 @@ machine_reset(void) wcscpy(temp, MACHINES_PATH); plat_append_slash(temp); wcscat(temp, machines[machine].bios_path); - if (! rom_load_bios(&r, temp, 0)) return; + if (! rom_load_bios(&r, temp, 0)) { + /* + * The machine's ROM BIOS could not be loaded. + * + * Since this is kinda fatal, we inform the user + * and bail out, since continuing is pointless. + */ + ui_msgbox(MBX_ERROR|MBX_FATAL, get_string(IDS_ERR_NOBIOS)); + + return; + } /* Activate the ROM BIOS. */ mem_add_bios(); diff --git a/src/machines/machine_table.c b/src/machines/machine_table.c index 5d0771c..d3b6b19 100644 --- a/src/machines/machine_table.c +++ b/src/machines/machine_table.c @@ -8,13 +8,13 @@ * * Handling of the emulated machines. * - * Version: @(#)machine_table.c 1.0.32 2019/02/11 + * Version: @(#)machine_table.c 1.0.33 2019/02/12 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2019 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2019 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -64,7 +64,7 @@ const machine_t machines[] = { /* 8088 */ { "[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 PC (1982)", "ibm_pc82", L"ibm/pc82", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 256, 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 (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 }, diff --git a/src/pc.c b/src/pc.c index 2dc91bb..c49f82a 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.64 2019/02/11 + * Version: @(#)pc.c 1.0.63 2019/01/27 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify @@ -738,7 +738,10 @@ usage: void pc_set_speed(void) { - setpitclock((float)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) + setpitclock((float)machine_speed()); + else + setpitclock(14318184.0); } diff --git a/src/ui/ui_resource.h b/src/ui/ui_resource.h index fd113f1..61152d8 100644 --- a/src/ui/ui_resource.h +++ b/src/ui/ui_resource.h @@ -12,11 +12,11 @@ * those are not used by the platform code. This is easier to * maintain. * - * Version: @(#)ui_resource.h 1.0.19 2018/11/12 + * Version: @(#)ui_resource.h 1.0.20 2019/02/12 * * Author: Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -276,6 +276,7 @@ #define IDS_ERR_SAVEIT 2305 /* "Must save settings first.." */ #define IDS_ERR_SCRSHOT 2306 /* "Unable to create bitmap file" */ #define IDS_ERR_NO_USB 2307 /* "USB is not yet supported" */ +#define IDS_ERR_NOBIOS IDS_ERR_NOCONF /* "No BIOS found.." */ /* Application messages (2400.) */ #define IDS_MSG_SAVE 2400 /* "Are you sure you want to save.." */ diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index 691f491..eaa9159 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.75 2019/02/11 +# Version: @(#)Makefile.mingw 1.0.75 2019/02/12 # # Author: Fred N. van Kempen, # diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index 236fd77..a76b41a 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.61 2019/02/11 +# Version: @(#)Makefile.VC 1.0.61 2019/02/12 # # Author: Fred N. van Kempen, # @@ -186,7 +186,6 @@ ifeq ($(DEV_BUILD), y) XL24 := y WONDER := y HOSTCD := y - PRINTER := y endif diff --git a/src/win/win.c b/src/win/win.c index 8f6a986..328b212 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,13 +8,13 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.25 2018/11/20 + * Version: @(#)win.c 1.0.26 2019/02/12 * * 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. * @@ -216,7 +216,6 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) /* First, set our (default) language. */ lang = (int)GetUserDefaultUILanguage(); -INFO("WIN: uilang = %04x\n", lang); /* * Set the initial active language for this application. @@ -231,7 +230,6 @@ INFO("WIN: uilang = %04x\n", lang); lang = 0x0409; (void)ui_lang_set(lang); } -INFO("WIN: initial lang = %04x\n", lang); #ifdef USE_CRASHDUMP /* Enable crash dump services. */ @@ -259,7 +257,6 @@ INFO("WIN: initial lang = %04x\n", lang); lang = emu_lang_id; (void)ui_lang_set(lang); } -INFO("WIN: lang = %04x / %04x\n", language, lang); #ifdef USE_HOST_CDROM cdrom_host_init();