More 808x fixed - fixed (kind of) the 8086 lock ups and the DRAM refresh wait states, also further fixed (and cleaned up) prefetch queue operation, applied a few warning fixes, and fixed the behavior of PUSH SP - anything that uses it to tell 808x apart from 286 is now fixed;
Re-added the higher-clocked 8088's; Fixed PIT timings for 808x CPU's that don't run off an 14.3 MHz crystal; Fixed CGA cursor half blink rate setting - fixes insane cursor blinking speed in several cases; DMA now issues DMA refresh DRAM states on every channel; Gave the 1982 years to the previously emulated PC and XT's names, and added the 1981 IBM PC and 1986 IBM XT; Redid the PPI DIP switch redout for the PC/XT keyboard controller; Fixed a segmentation fault in hdc_ide.c that tended to occur on hard reset after switching machines; Implemented the port 3B8 color disable on the Hercules, Hercules Plus, and Hercules InColor cards; Fixed the joystick configuration dialog strings; Fixed a problem that would have prevented win_sdl.c from compiling with logging enabled.
This commit is contained in:
348
src/cpu/808x.c
348
src/cpu/808x.c
@@ -80,15 +80,11 @@ uint32_t easeg;
|
||||
static uint8_t pfq[6];
|
||||
|
||||
/* Variables to aid with the prefetch queue operation. */
|
||||
static int fetchcycles = 0;
|
||||
static int fetchclocks, pfq_pos = 0;
|
||||
static int fetchcycles = 0, pfq_pos = 0;
|
||||
|
||||
/* The IP equivalent of the current prefetch queue position. */
|
||||
static uint16_t pfq_ip;
|
||||
|
||||
/* Where is this even used?! */
|
||||
static int nextcyc = 0;
|
||||
|
||||
/* Pointer tables needed for segment overrides. */
|
||||
static uint32_t *opseg[4];
|
||||
static x86seg *_opseg[4];
|
||||
@@ -196,6 +192,24 @@ 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
|
||||
@@ -204,15 +218,7 @@ readmemb(uint32_t a)
|
||||
uint8_t ret;
|
||||
|
||||
wait(4, 1);
|
||||
|
||||
if (readlookup2 == NULL)
|
||||
ret = readmembl(a);
|
||||
else {
|
||||
if (readlookup2[(a) >> 12] == -1)
|
||||
ret = readmembl(a);
|
||||
else
|
||||
ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a));
|
||||
}
|
||||
ret = readmemb_common(a);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -227,15 +233,7 @@ readmembf(uint32_t a)
|
||||
uint8_t ret;
|
||||
|
||||
a = cs + (a & 0xffff);
|
||||
|
||||
if (readlookup2 == NULL)
|
||||
ret = readmembl(a);
|
||||
else {
|
||||
if (readlookup2[(a) >> 12] == -1)
|
||||
ret = readmembl(a);
|
||||
else
|
||||
ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a));
|
||||
}
|
||||
ret = readmemb_common(a);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -244,41 +242,53 @@ 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(uint32_t s, uint16_t a)
|
||||
readmemw_common(uint32_t s, uint16_t a)
|
||||
{
|
||||
uint16_t ret;
|
||||
|
||||
if (!is8086 || (a & 1)) {
|
||||
ret = readmemb(s + a);
|
||||
ret |= readmemb(s + ((a + 1) & 0xffff)) << 8;
|
||||
} else {
|
||||
wait(4, 1);
|
||||
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
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))
|
||||
wait(4, 1);
|
||||
else
|
||||
wait(8, 1);
|
||||
ret = readmemw_common(s, a);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
readmemwf(uint16_t a)
|
||||
{
|
||||
uint16_t ret;
|
||||
|
||||
ret = readmemw_common(cs, a & 0xffff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Writes a byte from the memory and accounts for memory transfer cycles to
|
||||
subtract from the cycles to use for adding to the prefetch queue. */
|
||||
static void
|
||||
writememb(uint32_t a, uint8_t v)
|
||||
writememb_common(uint32_t a, uint8_t v)
|
||||
{
|
||||
wait(4, 1);
|
||||
|
||||
if (writelookup2 == NULL)
|
||||
writemembl(a, v);
|
||||
else {
|
||||
if (writelookup2[(a) >> 12] == -1)
|
||||
if (writelookup2[(a) >> 12] == ((uintptr_t) -1))
|
||||
writemembl(a, v);
|
||||
else
|
||||
*(uint8_t *)(writelookup2[a >> 12] + a) = v;
|
||||
@@ -286,55 +296,85 @@ writememb(uint32_t a, uint8_t v)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
writememb(uint32_t a, uint8_t v)
|
||||
{
|
||||
wait(4, 1);
|
||||
writememb_common(a, v);
|
||||
}
|
||||
|
||||
|
||||
/* Writes a word from the memory and accounts for memory transfer cycles to
|
||||
subtract from the cycles to use for adding to the prefetch queue. */
|
||||
static void
|
||||
writememw(uint32_t s, uint32_t a, uint16_t v)
|
||||
{
|
||||
if (!is8086 || (a & 1)) {
|
||||
writememb(s + a, v & 0xff);
|
||||
writememb(s + ((a + 1) & 0xffff), v >> 8);
|
||||
} else {
|
||||
wait(4, 1);
|
||||
if (is8086 && !(a & 1))
|
||||
wait(4, 1);
|
||||
else
|
||||
wait(8, 1);
|
||||
writememb_common(s + a, v & 0xff);
|
||||
writememb_common(s + ((a + 1) & 0xffff), v >> 8);
|
||||
}
|
||||
|
||||
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 void
|
||||
pfq_write(void)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
/* On 8086 and even IP, fetch *TWO* bytes at once. */
|
||||
if (pfq_pos < pfq_size) {
|
||||
/* If we're filling the last byte of the prefetch queue, do *NOT*
|
||||
read more than one byte even on the 8086. */
|
||||
if (is8086 && !(pfq_ip & 1) && !(pfq_pos & 1)) {
|
||||
tempw = readmemwf(pfq_ip);
|
||||
*(uint16_t *) &(pfq[pfq_pos]) = tempw;
|
||||
pfq_ip += 2;
|
||||
pfq_pos += 2;
|
||||
} else {
|
||||
pfq[pfq_pos] = readmembf(pfq_ip);
|
||||
pfq_ip++;
|
||||
pfq_pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
pfq_read(void)
|
||||
{
|
||||
uint8_t temp, i;
|
||||
|
||||
temp = pfq[0];
|
||||
for (i = 0; i < (pfq_size - 1); i++)
|
||||
pfq[i] = pfq[i + 1];
|
||||
pfq_pos--;
|
||||
cpu_state.pc++;
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
/* Fetches a byte from the prefetch queue, or from memory if the queue has
|
||||
been drained. */
|
||||
static uint8_t
|
||||
pfq_fetchb(void)
|
||||
{
|
||||
uint8_t temp, i;
|
||||
uint8_t temp;
|
||||
|
||||
if (pfq_pos == 0) {
|
||||
cycles -= (4 - (fetchcycles & 3));
|
||||
fetchclocks += (4 - (fetchcycles & 3));
|
||||
/* Extra cycles due to having to fetch on read. */
|
||||
wait(4 - (fetchcycles & 3), 1);
|
||||
fetchcycles = 4;
|
||||
temp = readmembf(cpu_state.pc);
|
||||
pfq_ip = cpu_state.pc = cpu_state.pc + 1;
|
||||
if (is8086 && (cpu_state.pc & 1)) {
|
||||
pfq[0] = readmembf(cpu_state.pc);
|
||||
pfq_ip++;
|
||||
pfq_pos++;
|
||||
}
|
||||
} else {
|
||||
temp = pfq[0];
|
||||
for (i = 0; i < (pfq_size - 1); i++)
|
||||
pfq[i] = pfq[i + 1];
|
||||
pfq_pos--;
|
||||
/* Reset prefetch queue internal position. */
|
||||
pfq_ip = cpu_state.pc;
|
||||
/* Fill the queue. */
|
||||
pfq_write();
|
||||
} else
|
||||
fetchcycles -= 4;
|
||||
cpu_state.pc++;
|
||||
}
|
||||
|
||||
/* Fetch. */
|
||||
temp = pfq_read();
|
||||
wait(1, 0);
|
||||
return temp;
|
||||
}
|
||||
@@ -362,16 +402,7 @@ pfq_add(int c)
|
||||
d = c + (fetchcycles & 3);
|
||||
while ((d > 3) && (pfq_pos < pfq_size)) {
|
||||
d -= 4;
|
||||
if (is8086 && !(pfq_ip & 1)) {
|
||||
pfq[pfq_pos] = readmembf(pfq_ip);
|
||||
pfq_ip++;
|
||||
pfq_pos++;
|
||||
}
|
||||
if (pfq_pos < pfq_size) {
|
||||
pfq[pfq_pos] = readmembf(pfq_ip);
|
||||
pfq_ip++;
|
||||
pfq_pos++;
|
||||
}
|
||||
pfq_write();
|
||||
}
|
||||
fetchcycles += c;
|
||||
if (fetchcycles > 16)
|
||||
@@ -379,46 +410,34 @@ pfq_add(int c)
|
||||
}
|
||||
|
||||
|
||||
/* Completes a fetch (called by refreshread()). */
|
||||
static void
|
||||
pfq_complete(void)
|
||||
{
|
||||
if (!(fetchcycles & 3))
|
||||
return;
|
||||
if (pfq_pos >= pfq_size)
|
||||
return;
|
||||
if (!pfq_pos)
|
||||
nextcyc = (4 - (fetchcycles & 3));
|
||||
cycles -= (4 - (fetchcycles & 3));
|
||||
fetchclocks += (4 - (fetchcycles & 3));
|
||||
if (is8086 && !(pfq_ip & 1)) {
|
||||
pfq[pfq_pos] = readmembf(pfq_ip);
|
||||
pfq_ip++;
|
||||
pfq_pos++;
|
||||
}
|
||||
if (pfq_pos < pfq_size) {
|
||||
pfq[pfq_pos] = readmembf(pfq_ip);
|
||||
pfq_ip++;
|
||||
pfq_pos++;
|
||||
}
|
||||
fetchcycles += (4 - (fetchcycles & 3));
|
||||
}
|
||||
|
||||
|
||||
/* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */
|
||||
static void
|
||||
pfq_clear()
|
||||
{
|
||||
pfq_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();
|
||||
if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed > 4772728)
|
||||
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. */
|
||||
wait(8 - (fetchcycles % 7), 1);
|
||||
/* Write to the prefetch queue. */
|
||||
pfq_write();
|
||||
/* Add those cycles to fetchcycles. */
|
||||
fetchcycles += (4 - (fetchcycles & 3));
|
||||
}
|
||||
|
||||
|
||||
@@ -516,12 +535,21 @@ do_mod_rm(void)
|
||||
}
|
||||
|
||||
|
||||
#undef getr8
|
||||
#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l)
|
||||
|
||||
#undef setr8
|
||||
#define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \
|
||||
else cpu_state.regs[r & 3].b.l = v;
|
||||
|
||||
|
||||
/* Reads a byte from the effective address. */
|
||||
static uint8_t
|
||||
geteab(void)
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l;
|
||||
if (cpu_mod == 3) {
|
||||
return (getr8(cpu_rm));
|
||||
}
|
||||
|
||||
return readmemb(easeg + cpu_state.eaaddr);
|
||||
}
|
||||
@@ -548,9 +576,9 @@ read_ea(int memory_only, int bits)
|
||||
return;
|
||||
}
|
||||
if (!memory_only) {
|
||||
if (bits == 8)
|
||||
cpu_data = (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l;
|
||||
else
|
||||
if (bits == 8) {
|
||||
cpu_data = getr8(cpu_rm);
|
||||
} else
|
||||
cpu_data = cpu_state.regs[cpu_rm].w;
|
||||
}
|
||||
}
|
||||
@@ -571,10 +599,7 @@ static void
|
||||
seteab(uint8_t val)
|
||||
{
|
||||
if (cpu_mod == 3) {
|
||||
if (cpu_rm & 4)
|
||||
cpu_state.regs[cpu_rm & 3].b.h = val;
|
||||
else
|
||||
cpu_state.regs[cpu_rm & 3].b.l = val;
|
||||
setr8(cpu_rm, val);
|
||||
} else
|
||||
writememb(easeg + cpu_state.eaaddr, val);
|
||||
}
|
||||
@@ -590,14 +615,6 @@ seteaw(uint16_t val)
|
||||
writememw(easeg, cpu_state.eaaddr, val);
|
||||
}
|
||||
|
||||
#undef getr8
|
||||
#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l)
|
||||
|
||||
#undef setr8
|
||||
#define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \
|
||||
else cpu_state.regs[r & 3].b.l = v;
|
||||
|
||||
|
||||
/* Prepare the ZNP table needed to speed up the setting of the Z, N, and P flags. */
|
||||
static void
|
||||
makeznptable(void)
|
||||
@@ -625,8 +642,10 @@ makeznptable(void)
|
||||
znptable8[c] = 0;
|
||||
else
|
||||
znptable8[c] = P_FLAG;
|
||||
#ifdef ENABLE_808X_LOG
|
||||
if (c == 0xb1)
|
||||
x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]);
|
||||
#endif
|
||||
if (!c)
|
||||
znptable8[c] |= Z_FLAG;
|
||||
if (c & 0x80)
|
||||
@@ -655,10 +674,12 @@ makeznptable(void)
|
||||
znptable16[c] = 0;
|
||||
else
|
||||
znptable16[c] = P_FLAG;
|
||||
#ifdef ENABLE_808X_LOG
|
||||
if (c == 0xb1)
|
||||
x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]);
|
||||
if (c == 0x65b1)
|
||||
x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]);
|
||||
#endif
|
||||
if (!c)
|
||||
znptable16[c] |= Z_FLAG;
|
||||
if (c & 0x8000)
|
||||
@@ -672,7 +693,9 @@ static void
|
||||
reset_common(int hard)
|
||||
{
|
||||
if (hard) {
|
||||
#ifdef ENABLE_808X_LOG
|
||||
x808x_log("x86 reset\n");
|
||||
#endif
|
||||
ins = 0;
|
||||
}
|
||||
use32 = 0;
|
||||
@@ -745,12 +768,19 @@ softresetx86(void)
|
||||
|
||||
|
||||
/* Pushes a word to the stack. */
|
||||
static void
|
||||
push_ex(uint16_t val)
|
||||
{
|
||||
writememw(ss, (SP & 0xFFFF), val);
|
||||
cpu_state.last_ea = SP;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
push(uint16_t val)
|
||||
{
|
||||
writememw(ss, ((SP - 2) & 0xFFFF), val);
|
||||
SP -= 2;
|
||||
cpu_state.last_ea = SP;
|
||||
push_ex(val);
|
||||
}
|
||||
|
||||
|
||||
@@ -1323,7 +1353,7 @@ div(uint16_t l, uint16_t h)
|
||||
}
|
||||
wait(3, 0);
|
||||
}
|
||||
cycles -= 8;
|
||||
wait(8, 0);
|
||||
cpu_src &= size_mask;
|
||||
if (h >= cpu_src) {
|
||||
if (opcode != 0xd4)
|
||||
@@ -1408,7 +1438,7 @@ stos(int bits)
|
||||
if (bits == 16)
|
||||
writememw(es, DI, cpu_data);
|
||||
else
|
||||
writememb(es + DI, cpu_data);
|
||||
writememb(es + DI, (uint8_t) (cpu_data & 0xff));
|
||||
if (flags & D_FLAG)
|
||||
DI -= (bits >> 3);
|
||||
else
|
||||
@@ -1464,9 +1494,6 @@ 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;
|
||||
@@ -1482,10 +1509,10 @@ opcodestart:
|
||||
oldc = flags & C_FLAG;
|
||||
trap = flags & T_FLAG;
|
||||
wait(1, 0);
|
||||
}
|
||||
|
||||
/* if ((CS >= 0xc800) && (CS <= 0xcfff))
|
||||
pclog("%04X:%04X %02X (%04X)\n", CS, cpu_state.pc, opcode, flags); */
|
||||
/* if (!in_rep && !ovr_seg && (CS < 0xf000))
|
||||
pclog("%04X:%04X %02X\n", CS, (cpu_state.pc - 1) & 0xFFFF, opcode); */
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */
|
||||
@@ -1545,14 +1572,14 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_data);
|
||||
else
|
||||
seteab(cpu_data);
|
||||
seteab((uint8_t) (cpu_data & 0xff));
|
||||
if (cpu_mod == 3)
|
||||
wait(1, 0);
|
||||
} else {
|
||||
if (opcode & 1)
|
||||
cpu_state.regs[cpu_reg].w = cpu_data;
|
||||
else
|
||||
setr8(cpu_reg, cpu_data);
|
||||
setr8(cpu_reg, (uint8_t) (cpu_data & 0xff));
|
||||
wait(1, 0);
|
||||
}
|
||||
} else
|
||||
@@ -1580,7 +1607,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
AX = cpu_data;
|
||||
else
|
||||
AL = cpu_data & 0xff;
|
||||
AL = (uint8_t) (cpu_data & 0xff);
|
||||
}
|
||||
wait(1, 0);
|
||||
break;
|
||||
@@ -1665,7 +1692,11 @@ opcodestart:
|
||||
case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/
|
||||
case 0x54: case 0x55: case 0x56: case 0x57:
|
||||
access(30, 16);
|
||||
push(cpu_state.regs[opcode & 0x07].w);
|
||||
if (opcode == 0x54) {
|
||||
SP -= 2;
|
||||
push_ex(cpu_state.regs[opcode & 0x07].w);
|
||||
} else
|
||||
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:
|
||||
@@ -1759,7 +1790,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_data);
|
||||
else
|
||||
seteab(cpu_data);
|
||||
seteab((uint8_t) (cpu_data & 0xff));
|
||||
} else {
|
||||
if (cpu_mod != 3)
|
||||
wait(1, 0);
|
||||
@@ -1801,7 +1832,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_src);
|
||||
else
|
||||
seteab(cpu_src);
|
||||
seteab((uint8_t) (cpu_src & 0xff));
|
||||
break;
|
||||
|
||||
case 0x88: case 0x89:
|
||||
@@ -1813,7 +1844,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_state.regs[cpu_reg].w);
|
||||
else
|
||||
seteab(getr8(cpu_reg));
|
||||
seteab(getr8((uint8_t) (cpu_reg & 0xff)));
|
||||
break;
|
||||
case 0x8A: case 0x8B:
|
||||
/* MOV reg, rm */
|
||||
@@ -1936,8 +1967,7 @@ opcodestart:
|
||||
pfq_clear();
|
||||
break;
|
||||
case 0x9B: /*WAIT*/
|
||||
pclog("PCem: %02X\n", opcode);
|
||||
cycles -= 4;
|
||||
wait(4, 0);
|
||||
break;
|
||||
case 0x9C: /*PUSHF*/
|
||||
access(33, 16);
|
||||
@@ -2007,7 +2037,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
AX = cpu_data;
|
||||
else
|
||||
AL = cpu_data;
|
||||
AL = (uint8_t) (cpu_data & 0xff);
|
||||
if (in_rep != 0)
|
||||
wait(2, 0);
|
||||
}
|
||||
@@ -2182,7 +2212,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_data);
|
||||
else
|
||||
seteab(cpu_data);
|
||||
seteab((uint8_t) (cpu_data & 0xff));
|
||||
break;
|
||||
|
||||
case 0xCC: /*INT 3*/
|
||||
@@ -2305,7 +2335,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_data);
|
||||
else
|
||||
seteab(cpu_data);
|
||||
seteab((uint8_t) (cpu_data & 0xff));
|
||||
break;
|
||||
|
||||
case 0xD4: /*AAM*/
|
||||
@@ -2381,7 +2411,7 @@ opcodestart:
|
||||
cpu_data = DX;
|
||||
if ((opcode & 2) == 0) {
|
||||
access(3, bits);
|
||||
if ((opcode & 1) && is8086) {
|
||||
if ((opcode & 1) && is8086 && !(cpu_data & 1)) {
|
||||
AX = inw(cpu_data);
|
||||
wait(4, 1); /* I/O access and wait state. */
|
||||
} else {
|
||||
@@ -2396,7 +2426,7 @@ opcodestart:
|
||||
access(8, bits);
|
||||
else
|
||||
access(9, bits);
|
||||
if ((opcode & 1) && is8086) {
|
||||
if ((opcode & 1) && is8086 && !(cpu_data & 1)) {
|
||||
outw(cpu_data, AX);
|
||||
wait(4, 1);
|
||||
} else {
|
||||
@@ -2497,7 +2527,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_data);
|
||||
else
|
||||
seteab(cpu_data);
|
||||
seteab((uint8_t) (cpu_data & 0xff));
|
||||
break;
|
||||
case 0x20: /* MUL */
|
||||
case 0x28: /* IMUL */
|
||||
@@ -2550,7 +2580,7 @@ opcodestart:
|
||||
bits = 8 << (opcode & 1);
|
||||
do_mod_rm();
|
||||
access(56, bits);
|
||||
read_ea((rmdat & 0x38) == 0x18 || (rmdat & 0x38) == 0x28, bits);
|
||||
read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits);
|
||||
switch (rmdat & 0x38) {
|
||||
case 0x00: /* INC rm */
|
||||
case 0x08: /* DEC rm */
|
||||
@@ -2570,7 +2600,7 @@ opcodestart:
|
||||
if (opcode & 1)
|
||||
seteaw(cpu_data);
|
||||
else
|
||||
seteab(cpu_data);
|
||||
seteab((uint8_t) (cpu_data & 0xff));
|
||||
break;
|
||||
case 0x10: /* CALL rm */
|
||||
if (!(opcode & 1)) {
|
||||
@@ -2637,7 +2667,10 @@ opcodestart:
|
||||
if (cpu_mod != 3)
|
||||
wait(1, 0);
|
||||
access(38, bits);
|
||||
push(cpu_data);
|
||||
if ((cpu_mod == 3) && (cpu_rm == 4))
|
||||
push(cpu_data - 2);
|
||||
else
|
||||
push(cpu_data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -2659,7 +2692,8 @@ on_halt:
|
||||
in_lock = 0;
|
||||
|
||||
/* FIXME: Find out why this is needed. */
|
||||
if ((romset == ROM_IBMPC) && ((cs + cpu_state.pc) == 0xFE4A7)) {
|
||||
if (((romset == ROM_IBMPC) && ((cs + cpu_state.pc) == 0xFE545)) ||
|
||||
((romset == ROM_IBMPC82) && ((cs + cpu_state.pc) == 0xFE4A7))) {
|
||||
/* You didn't seriously think I was going to emulate the cassette, did you? */
|
||||
CX = 1;
|
||||
BX = 0x500;
|
||||
|
@@ -71,6 +71,7 @@
|
||||
|
||||
#define CPU_SUPPORTS_DYNAREC 1
|
||||
#define CPU_REQUIRES_DYNAREC 2
|
||||
#define CPU_ALTERNATE_XTAL 4
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@@ -55,6 +55,9 @@ CPU cpus_8088[] = {
|
||||
{"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/10", CPU_8088, 1, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/12", CPU_8088, 1, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/16", CPU_8088, 1, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}
|
||||
};
|
||||
|
||||
@@ -66,17 +69,17 @@ CPU cpus_pcjr[] = {
|
||||
|
||||
CPU cpus_europc[] = {
|
||||
/*8088 EuroPC*/
|
||||
{"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 1, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8088/9.54", CPU_8088, 1, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}
|
||||
};
|
||||
|
||||
CPU cpus_8086[] = {
|
||||
/*8086 standard*/
|
||||
{"8086/7.16", CPU_8086, 1, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/7.16", CPU_8086, 1, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/9.54", CPU_8086, 1, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/9.54", CPU_8086, 1, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}
|
||||
};
|
||||
|
@@ -9,7 +9,7 @@
|
||||
* Implementation of the IDE emulation for hard disks and ATAPI
|
||||
* CD-ROM devices.
|
||||
*
|
||||
* Version: @(#)hdc_ide.c 1.0.59 2018/11/09
|
||||
* Version: @(#)hdc_ide.c 1.0.60 2019/02/10
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -2439,6 +2439,9 @@ ide_set_handlers(uint8_t board)
|
||||
static void
|
||||
ide_remove_handlers(uint8_t board)
|
||||
{
|
||||
if (!ide_boards[board])
|
||||
return;
|
||||
|
||||
if (ide_boards[board]->bit32) {
|
||||
io_removehandler(ide_base_main[board], 1,
|
||||
ide_readb, ide_readw, ide_readl,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Implementation of the Intel DMA controllers.
|
||||
*
|
||||
* Version: @(#)dma.c 1.0.4 2018/11/18
|
||||
* Version: @(#)dma.c 1.0.5 2019/02/07
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -659,7 +659,7 @@ dma_channel_read(int channel)
|
||||
if ((dma_c->mode & 0xC) != 8)
|
||||
return(DMA_NODATA);
|
||||
|
||||
if ((!AT) && !channel)
|
||||
if (!AT)
|
||||
refreshread();
|
||||
|
||||
if (! dma_c->size) {
|
||||
@@ -730,7 +730,7 @@ dma_channel_write(int channel, uint16_t val)
|
||||
if ((dma_c->mode & 0xC) != 4)
|
||||
return(DMA_NODATA);
|
||||
|
||||
if ((!AT) && !channel)
|
||||
if (!AT)
|
||||
refreshread();
|
||||
|
||||
if (! dma_c->size) {
|
||||
|
@@ -8,15 +8,15 @@
|
||||
*
|
||||
* Definitions for the keyboard interface.
|
||||
*
|
||||
* Version: @(#)keyboard.h 1.0.16 2018/09/15
|
||||
* Version: @(#)keyboard.h 1.0.17 2019/02/08
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_KEYBOARD_H
|
||||
# define EMU_KEYBOARD_H
|
||||
@@ -61,7 +61,9 @@ extern int mouse_scan;
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t keyboard_pc_device;
|
||||
extern const device_t keyboard_pc82_device;
|
||||
extern const device_t keyboard_xt_device;
|
||||
extern const device_t keyboard_xt86_device;
|
||||
extern const device_t keyboard_tandy_device;
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
extern const device_t keyboard_xt_lxt3_device;
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "86box.h"
|
||||
#include "floppy/fdd.h"
|
||||
#include "machine/machine.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
@@ -54,8 +55,7 @@ typedef struct {
|
||||
int blocked;
|
||||
int tandy;
|
||||
|
||||
uint8_t pa;
|
||||
uint8_t pb;
|
||||
uint8_t pa, pb, pd;
|
||||
uint8_t key_waiting;
|
||||
uint8_t type;
|
||||
} xtkbd_t;
|
||||
@@ -472,14 +472,9 @@ kbd_read(uint16_t port, void *priv)
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
if (!kbd->type && (kbd->pb & 0x80)) {
|
||||
if (video_is_ega_vga())
|
||||
ret = 0x4d;
|
||||
else if (video_is_mda())
|
||||
ret = 0x7d;
|
||||
else
|
||||
ret = 0x6d;
|
||||
} else if ((kbd->type == 1) && (kbd->pb & 0x80))
|
||||
if ((kbd->type <= 1) && (kbd->pb & 0x80))
|
||||
ret = kbd->pd;
|
||||
else if (((kbd->type == 2) || (kbd->type == 3)) && (kbd->pb & 0x80))
|
||||
ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */
|
||||
else
|
||||
ret = kbd->pa;
|
||||
@@ -490,39 +485,37 @@ kbd_read(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 0x62:
|
||||
if (!kbd->type) {
|
||||
if (!kbd->type)
|
||||
ret = 0x00;
|
||||
else if (kbd->type == 1) {
|
||||
if (kbd->pb & 0x04)
|
||||
ret = ((mem_size-64) / 32) & 0x0f;
|
||||
else
|
||||
ret = ((mem_size-64) / 32) >> 4;
|
||||
} else {
|
||||
if (kbd->pb & 0x08) {
|
||||
if (video_is_ega_vga())
|
||||
ret = 0x4;
|
||||
else if (video_is_mda())
|
||||
ret = 0x7;
|
||||
else
|
||||
ret = 0x6;
|
||||
} else {
|
||||
if (kbd->pb & 0x08)
|
||||
ret = kbd->pd >> 4;
|
||||
else {
|
||||
/* LaserXT = Always 512k RAM;
|
||||
LaserXT/3 = Bit 0: set = 512k, clear = 256k. */
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
if (kbd->type == 3)
|
||||
if (kbd->type == 5)
|
||||
ret = (mem_size == 512) ? 0x0d : 0x0c;
|
||||
else
|
||||
#endif
|
||||
ret = 0x0d;
|
||||
ret = kbd->pd & 0x0f;
|
||||
}
|
||||
}
|
||||
ret |= (ppispeakon ? 0x20 : 0);
|
||||
|
||||
if (kbd->type == 2)
|
||||
if (kbd->type == 4)
|
||||
ret |= (tandy1k_eeprom_read() ? 0x10 : 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
pclog("XTkbd: bad read %04X\n", port);
|
||||
ret = 0xff;
|
||||
case 0x63:
|
||||
if ((kbd->type == 2) || (kbd->type == 3))
|
||||
ret = kbd->pd;
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
@@ -549,6 +542,8 @@ kbd_reset(void *priv)
|
||||
static void *
|
||||
kbd_init(const device_t *info)
|
||||
{
|
||||
int i, fdd_count = 0;
|
||||
|
||||
xtkbd_t *kbd;
|
||||
|
||||
kbd = (xtkbd_t *)malloc(sizeof(xtkbd_t));
|
||||
@@ -560,6 +555,78 @@ kbd_init(const device_t *info)
|
||||
kbd_reset(kbd);
|
||||
kbd->type = info->local;
|
||||
|
||||
if (kbd->type <= 3) {
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
if (fdd_get_flags(i))
|
||||
fdd_count++;
|
||||
}
|
||||
|
||||
/* DIP switch readout: bit set = OFF, clear = ON. */
|
||||
/* Switches 7, 8 - floppy drives. */
|
||||
if (!fdd_count)
|
||||
kbd->pd = 0x00;
|
||||
else
|
||||
kbd->pd = ((fdd_count - 1) << 6) | 0x01;
|
||||
/* Switches 5, 6 - video. */
|
||||
if (video_is_mda())
|
||||
kbd->pd |= 0x30;
|
||||
else
|
||||
kbd->pd |= 0x20; /* 0x10 would be 40x25 */
|
||||
/* Switches 3, 4 - memory size. */
|
||||
if (kbd->type == 3) {
|
||||
switch (mem_size) {
|
||||
case 256:
|
||||
kbd->pd |= 0x00;
|
||||
break;
|
||||
case 512:
|
||||
kbd->pd |= 0x04;
|
||||
break;
|
||||
case 576:
|
||||
kbd->pd |= 0x08;
|
||||
break;
|
||||
case 640:
|
||||
default:
|
||||
kbd->pd |= 0x0c;
|
||||
break;
|
||||
}
|
||||
} else if (kbd->type == 2) {
|
||||
switch (mem_size) {
|
||||
case 64:
|
||||
kbd->pd |= 0x00;
|
||||
break;
|
||||
case 128:
|
||||
kbd->pd |= 0x04;
|
||||
break;
|
||||
case 192:
|
||||
kbd->pd |= 0x08;
|
||||
break;
|
||||
case 256:
|
||||
default:
|
||||
kbd->pd |= 0x0c;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mem_size) {
|
||||
case 16:
|
||||
kbd->pd |= 0x00;
|
||||
break;
|
||||
case 32:
|
||||
kbd->pd |= 0x04;
|
||||
break;
|
||||
case 48:
|
||||
kbd->pd |= 0x08;
|
||||
break;
|
||||
case 64:
|
||||
default:
|
||||
kbd->pd |= 0x0c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Switch 2 - return bit clear (switch ON) because no 8087 right now. */
|
||||
/* Switch 1 - always off. */
|
||||
kbd->pd |= 0x01;
|
||||
}
|
||||
|
||||
timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, kbd);
|
||||
|
||||
keyboard_set_table(scancode_xt);
|
||||
@@ -589,7 +656,7 @@ kbd_close(void *priv)
|
||||
|
||||
|
||||
const device_t keyboard_pc_device = {
|
||||
"IBM PC Keyboard",
|
||||
"IBM PC Keyboard (1981)",
|
||||
0,
|
||||
0,
|
||||
kbd_init,
|
||||
@@ -598,8 +665,8 @@ const device_t keyboard_pc_device = {
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt_device = {
|
||||
"XT Keyboard",
|
||||
const device_t keyboard_pc82_device = {
|
||||
"IBM PC Keyboard (1982)",
|
||||
0,
|
||||
1,
|
||||
kbd_init,
|
||||
@@ -608,10 +675,30 @@ const device_t keyboard_xt_device = {
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt_device = {
|
||||
"XT (1982) Keyboard",
|
||||
0,
|
||||
2,
|
||||
kbd_init,
|
||||
kbd_close,
|
||||
kbd_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_xt86_device = {
|
||||
"XT (1986) Keyboard",
|
||||
0,
|
||||
3,
|
||||
kbd_init,
|
||||
kbd_close,
|
||||
kbd_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_tandy_device = {
|
||||
"Tandy 1000 Keyboard",
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
kbd_init,
|
||||
kbd_close,
|
||||
kbd_reset,
|
||||
@@ -622,7 +709,7 @@ const device_t keyboard_tandy_device = {
|
||||
const device_t keyboard_xt_lxt3_device = {
|
||||
"VTech Laser XT3 Keyboard",
|
||||
0,
|
||||
3,
|
||||
/*5*/ 3,
|
||||
kbd_init,
|
||||
kbd_close,
|
||||
kbd_reset,
|
||||
|
@@ -14,14 +14,13 @@
|
||||
#include "machine.h"
|
||||
|
||||
|
||||
void
|
||||
machine_pc_init(const machine_t *model)
|
||||
static void
|
||||
machine_xt_common_init(const machine_t *model)
|
||||
{
|
||||
machine_common_init(model);
|
||||
|
||||
pit_set_out_func(&pit, 1, pit_refresh_timer_xt);
|
||||
|
||||
device_add(&keyboard_pc_device);
|
||||
device_add(&fdc_xt_device);
|
||||
nmi_init();
|
||||
if (joystick_type != 7)
|
||||
@@ -29,16 +28,37 @@ machine_pc_init(const machine_t *model)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
machine_pc_init(const machine_t *model)
|
||||
{
|
||||
machine_xt_common_init(model);
|
||||
|
||||
device_add(&keyboard_pc_device);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
machine_pc82_init(const machine_t *model)
|
||||
{
|
||||
machine_xt_common_init(model);
|
||||
|
||||
device_add(&keyboard_pc82_device);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
machine_xt_init(const machine_t *model)
|
||||
{
|
||||
machine_common_init(model);
|
||||
|
||||
pit_set_out_func(&pit, 1, pit_refresh_timer_xt);
|
||||
machine_xt_common_init(model);
|
||||
|
||||
device_add(&keyboard_xt_device);
|
||||
device_add(&fdc_xt_device);
|
||||
nmi_init();
|
||||
if (joystick_type != 7)
|
||||
device_add(&gameport_device);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
machine_xt86_init(const machine_t *model)
|
||||
{
|
||||
machine_xt_common_init(model);
|
||||
|
||||
device_add(&keyboard_xt86_device);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Handling of the emulated machines.
|
||||
*
|
||||
* Version: @(#)machine.h 1.0.32 2019/01/13
|
||||
* Version: @(#)machine.h 1.0.33 2019/02/08
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -151,6 +151,8 @@ extern void machine_at_r418_init(const machine_t *);
|
||||
extern void machine_at_wd76c10_init(const machine_t *);
|
||||
|
||||
extern void machine_pc_init(const machine_t *);
|
||||
extern void machine_pc82_init(const machine_t *);
|
||||
|
||||
extern void machine_pcjr_init(const machine_t *);
|
||||
|
||||
extern void machine_ps1_m2011_init(const machine_t *);
|
||||
@@ -186,6 +188,7 @@ extern void machine_tandy1k_init(const machine_t *);
|
||||
extern int tandy1k_eeprom_read(void);
|
||||
|
||||
extern void machine_xt_init(const machine_t *);
|
||||
extern void machine_xt86_init(const machine_t *);
|
||||
extern void machine_xt_compaq_init(const machine_t *);
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
extern void machine_xt_laserxt_init(const machine_t *);
|
||||
|
@@ -11,7 +11,7 @@
|
||||
* NOTES: OpenAT wip for 286-class machine with open BIOS.
|
||||
* PS2_M80-486 wip, pending receipt of TRM's for machine.
|
||||
*
|
||||
* Version: @(#)machine_table.c 1.0.45 2019/01/13
|
||||
* Version: @(#)machine_table.c 1.0.46 2019/02/08
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -37,18 +37,20 @@ const machine_t machines[] = {
|
||||
{ "[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL },
|
||||
{ "[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_pc_init, NULL },
|
||||
{ "[8088] IBM PC (1981)", ROM_IBMPC, "ibmpc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 16, 64, 16, 0, machine_pc_init, NULL },
|
||||
{ "[8088] IBM PC (1982)", ROM_IBMPC82, "ibmpc82", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 256, 64, 0, machine_pc82_init, NULL },
|
||||
{ "[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"Intel", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device },
|
||||
{ "[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] IBM XT (1982)", ROM_IBMXT, "ibmxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 256, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] IBM XT (1986)", ROM_IBMXT86, "ibmxt86", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 64, 0, machine_xt86_init, NULL },
|
||||
{ "[8088] Generic XT clone", ROM_GENXT, "genxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL },
|
||||
{ "[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL },
|
||||
{ "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device },
|
||||
{ "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device },
|
||||
{ "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"Intel", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device },
|
||||
{ "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"Intel", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device },
|
||||
{ "[8088] Toshiba T1000", ROM_T1000, "t1000", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, t1000_get_device },
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
{ "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL },
|
||||
{ "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 256, 0, machine_xt_laserxt_init, NULL },
|
||||
#endif
|
||||
{ "[8088] Xi8088", ROM_XI8088, "xi8088", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, NULL },
|
||||
{ "[8088] Zenith Data SupersPort", ROM_ZD_SUPERS, "zdsupers", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 128, 640, 128, 0, machine_xt_zenith_init, NULL },
|
||||
@@ -62,7 +64,7 @@ const machine_t machines[] = {
|
||||
{ "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL },
|
||||
{ "[8086] Toshiba T1200", ROM_T1200, "t1200", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device },
|
||||
#if defined(DEV_BRANCH) && defined(USE_LASERXT)
|
||||
{ "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_lxt3_init, NULL },
|
||||
{ "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 640, 256, 0, machine_xt_lxt3_init, NULL },
|
||||
#endif
|
||||
|
||||
{ "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,8192, 128, 127, machine_at_neat_ami_init, NULL },
|
||||
|
55
src/pc.c
55
src/pc.c
@@ -513,10 +513,7 @@ pc_full_speed(void)
|
||||
|
||||
if (! atfullspeed) {
|
||||
pc_log("Set fullspeed - %i %i %i\n", is386, AT, cpuspeed2);
|
||||
if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286)
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
else
|
||||
setpitclock(14318184.0);
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
}
|
||||
atfullspeed = 1;
|
||||
|
||||
@@ -527,54 +524,12 @@ pc_full_speed(void)
|
||||
void
|
||||
pc_speed_changed(void)
|
||||
{
|
||||
if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286)
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
else
|
||||
setpitclock(14318184.0);
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
|
||||
nvr_period_recalc();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Re-load system configuration and restart. */
|
||||
/* FIXME: this has to be reviewed! */
|
||||
void
|
||||
pc_reload(wchar_t *fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
config_write(cfg_path);
|
||||
|
||||
for (i=0; i<FDD_NUM; i++)
|
||||
fdd_close(i);
|
||||
|
||||
cdrom_close();
|
||||
|
||||
pc_reset_hard_close();
|
||||
|
||||
// FIXME: set up new config file path 'fn'... --FvK
|
||||
|
||||
config_load();
|
||||
|
||||
cdrom_hard_reset();
|
||||
|
||||
zip_hard_reset();
|
||||
|
||||
scsi_disk_hard_reset();
|
||||
|
||||
fdd_load(0, floppyfns[0]);
|
||||
fdd_load(1, floppyfns[1]);
|
||||
fdd_load(2, floppyfns[2]);
|
||||
fdd_load(3, floppyfns[3]);
|
||||
|
||||
network_init();
|
||||
|
||||
pc_reset_hard_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Initialize modules, ran once, after pc_init. */
|
||||
int
|
||||
pc_init_modules(void)
|
||||
@@ -795,7 +750,6 @@ pc_reset_hard_init(void)
|
||||
|
||||
/* Reset the Hard Disk Controller module. */
|
||||
hdc_reset();
|
||||
|
||||
/* Reset and reconfigure the SCSI layer. */
|
||||
scsi_card_init();
|
||||
|
||||
@@ -832,10 +786,7 @@ pc_reset_hard_init(void)
|
||||
|
||||
pc_full_speed();
|
||||
|
||||
if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286)
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
else
|
||||
setpitclock(14318184.0);
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
}
|
||||
|
||||
|
||||
|
129
src/pit.c
129
src/pit.c
@@ -30,7 +30,7 @@ int64_t displine;
|
||||
PIT pit,
|
||||
pit2;
|
||||
float cpuclock;
|
||||
float isa_timing, bus_timing;
|
||||
float /*isa_timing, */bus_timing;
|
||||
|
||||
double PITCONST;
|
||||
float CGACONST;
|
||||
@@ -42,49 +42,68 @@ float RTCCONST;
|
||||
int64_t firsttime=1;
|
||||
void setrtcconst(float clock)
|
||||
{
|
||||
RTCCONST=clock/32768.0;
|
||||
TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT));
|
||||
/* Set default CPU/crystal clock and xt_cpu_multi. */
|
||||
cpuclock = 14318184.0;
|
||||
if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) {
|
||||
cpuclock = clock;
|
||||
PITCONST=cpuclock/1193182.0;
|
||||
CGACONST=(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:
|
||||
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:
|
||||
cpuclock = 24000000.0;
|
||||
break;
|
||||
case 9545456:
|
||||
cpuclock = 28636368.0;
|
||||
break;
|
||||
case 10000000:
|
||||
cpuclock = 30000000.0;
|
||||
break;
|
||||
case 12000000:
|
||||
cpuclock = 36000000.0;
|
||||
break;
|
||||
case 16000000:
|
||||
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=(cpuclock/(19687503.0/11.0));
|
||||
}
|
||||
}
|
||||
xt_cpu_multi <<= TIMER_SHIFT;
|
||||
|
||||
MDACONST=(cpuclock/2032125.0);
|
||||
VGACONST1=(cpuclock/25175000.0);
|
||||
VGACONST2=(cpuclock/28322000.0);
|
||||
RTCCONST=cpuclock/32768.0;
|
||||
TIMER_USEC = (int64_t)((cpuclock / 1000000.0f) * (float)(1 << TIMER_SHIFT));
|
||||
bus_timing = cpuclock/(double)cpu_busspeed;
|
||||
}
|
||||
|
||||
void setpitclock(float clock)
|
||||
{
|
||||
/* Some calculations are done differently 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=(8.0 / 3.0);
|
||||
} else if (clock == 7159092.0) {
|
||||
/* 7.16 MHz CPU - simplify the calculation to avoid
|
||||
loss of precision. */
|
||||
PITCONST=6.0;
|
||||
CGACONST=4.0;
|
||||
} else if (clock == 9545456.0) {
|
||||
/* 9.54 MHz CPU - simplify the calculation to avoid
|
||||
loss of precision. */
|
||||
PITCONST=8.0;
|
||||
CGACONST=(8.0 / 1.5);
|
||||
} else {
|
||||
PITCONST=clock/1193182.0;
|
||||
CGACONST=(clock/(19687503.0/11.0));
|
||||
}
|
||||
MDACONST=(clock/2032125.0);
|
||||
VGACONST1=(clock/25175000.0);
|
||||
VGACONST2=(clock/28322000.0);
|
||||
isa_timing = clock/8000000.0;
|
||||
bus_timing = clock/(double)cpu_busspeed;
|
||||
video_update_timing();
|
||||
|
||||
if (clock == 4772728.0)
|
||||
xt_cpu_multi = 3 * (1 << TIMER_SHIFT);
|
||||
else if (clock == 7159092.0)
|
||||
xt_cpu_multi = 2 * (1 << TIMER_SHIFT);
|
||||
else if (clock == 9545456.0)
|
||||
xt_cpu_multi = (int64_t)(1.5*(double)(1 << TIMER_SHIFT));
|
||||
else
|
||||
xt_cpu_multi = (int64_t)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
|
||||
device_speed_changed();
|
||||
}
|
||||
|
||||
@@ -333,7 +352,7 @@ int pit_get_timer_0()
|
||||
read <<= 1;
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
static int pit_read_timer(PIT *pit, int t)
|
||||
{
|
||||
timer_clock();
|
||||
@@ -354,7 +373,7 @@ static int pit_read_timer(PIT *pit, int t)
|
||||
return pit->count[t] + 1;
|
||||
return pit->count[t];
|
||||
}
|
||||
|
||||
|
||||
void pit_write(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
PIT *pit = (PIT *)p;
|
||||
@@ -540,13 +559,39 @@ void pit_clock(PIT *pit, int t)
|
||||
pit_over(pit, t);
|
||||
}
|
||||
|
||||
static int64_t pit_read_timer_ex(PIT *pit, int t)
|
||||
{
|
||||
int64_t read;
|
||||
timer_clock();
|
||||
if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t]))
|
||||
{
|
||||
read = (int)(pit->c[t] + ((1 << TIMER_SHIFT) - 1));
|
||||
if (pit->m[t] == 2)
|
||||
read += (1LL << TIMER_SHIFT) * PITCONST;
|
||||
if (read < 0)
|
||||
read = 0;
|
||||
if (read > ((0x10000LL << TIMER_SHIFT) * PITCONST))
|
||||
read = ((0x10000LL << TIMER_SHIFT) * PITCONST);
|
||||
if (pit->m[t] == 3)
|
||||
read <<= 1;
|
||||
return read;
|
||||
}
|
||||
if (pit->m[t] == 2) {
|
||||
read = (int64_t) (((pit->count[t] + 1LL) << TIMER_SHIFT) * PITCONST);
|
||||
return read;
|
||||
}
|
||||
read = (int64_t) ((pit->count[t] << TIMER_SHIFT) * PITCONST);
|
||||
return read;
|
||||
}
|
||||
|
||||
void pit_set_using_timer(PIT *pit, int t, int using_timer)
|
||||
{
|
||||
timer_process();
|
||||
if (pit->using_timer[t] && !using_timer)
|
||||
pit->count[t] = pit_read_timer(pit, t);
|
||||
if (!pit->using_timer[t] && using_timer)
|
||||
pit->c[t] = (int64_t)((((int64_t) pit->count[t]) << TIMER_SHIFT) * PITCONST);
|
||||
pit->c[t] = pit_read_timer_ex(pit, t);
|
||||
// pit->c[t] = (int64_t)((((int64_t) pit->count[t]) << TIMER_SHIFT) * PITCONST);
|
||||
pit->using_timer[t] = using_timer;
|
||||
pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t];
|
||||
timer_update_outstanding();
|
||||
|
42
src/rom.c
42
src/rom.c
@@ -13,7 +13,7 @@
|
||||
* - c386sx16 BIOS fails checksum
|
||||
* - the loadfont() calls should be done elsewhere
|
||||
*
|
||||
* Version: @(#)rom.c 1.0.43 2019/01/13
|
||||
* Version: @(#)rom.c 1.0.44 2019/02/08
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -330,9 +330,9 @@ rom_load_bios(int rom_id)
|
||||
mem_mapping_disable(&romext_mapping);
|
||||
|
||||
switch (rom_id) {
|
||||
case ROM_IBMPC: /* IBM PC */
|
||||
case ROM_IBMPC: /* IBM PC (1981) */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmpc/pc102782.bin",
|
||||
L"roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN",
|
||||
0x00e000, 8192, 0, rom)) break;
|
||||
|
||||
/* Try to load the (full) BASIC ROM. */
|
||||
@@ -355,7 +355,32 @@ rom_load_bios(int rom_id)
|
||||
0x00c000, 8192, 0, rom)) break; /* nope */
|
||||
return(1);
|
||||
|
||||
case ROM_IBMXT: /* IBM PX-XT */
|
||||
case ROM_IBMPC82: /* IBM PC (1982) */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmpc82/pc102782.bin",
|
||||
0x00e000, 8192, 0, rom)) break;
|
||||
|
||||
/* Try to load the (full) BASIC ROM. */
|
||||
if (rom_load_linear(
|
||||
L"roms/machines/ibmpc82/ibm-basic-1.10.rom",
|
||||
0x006000, 32768, 0, rom)) return(1);
|
||||
|
||||
/* Nope. Try to load the first BASIC ROM image. */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmpc82/basicc11.f6",
|
||||
0x006000, 8192, 0, rom)) return(1); /* nope */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmpc82/basicc11.f8",
|
||||
0x008000, 8192, 0, rom)) break; /* nope */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmpc82/basicc11.fa",
|
||||
0x00a000, 8192, 0, rom)) break; /* nope */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmpc82/basicc11.fc",
|
||||
0x00c000, 8192, 0, rom)) break; /* nope */
|
||||
return(1);
|
||||
|
||||
case ROM_IBMXT: /* IBM PX-XT (1982) */
|
||||
if (rom_load_linear(
|
||||
L"roms/machines/ibmxt/xt.rom",
|
||||
0x000000, 65536, 0, rom)) return(1);
|
||||
@@ -368,6 +393,15 @@ rom_load_bios(int rom_id)
|
||||
0x008000, 32768, 0, rom)) return(1);
|
||||
break;
|
||||
|
||||
case ROM_IBMXT86: /* IBM PX-XT (1986) */
|
||||
if (! rom_load_linear(
|
||||
L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN",
|
||||
0x000000, 32768, 0, rom)) break;
|
||||
if (rom_load_linear(
|
||||
L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN",
|
||||
0x008000, 32768, 0, rom)) return(1);
|
||||
break;
|
||||
|
||||
case ROM_XI8088:
|
||||
if (rom_load_linear_inverted(
|
||||
L"roms/machines/xi8088/bios-xi8088.bin",
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the ROM image handler.
|
||||
*
|
||||
* Version: @(#)rom.h 1.0.21 2019/01/13
|
||||
* Version: @(#)rom.h 1.0.22 2019/02/08
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Copyright 2018 Fred N. van Kempen.
|
||||
@@ -28,10 +28,12 @@ typedef struct {
|
||||
|
||||
|
||||
enum {
|
||||
ROM_IBMPC = 0, /* 301 keyboard error, 131 cassette (!!!) error */
|
||||
ROM_IBMPC = 0, /* 1981 - 16-64 variant */
|
||||
ROM_IBMPC82, /* 1982 - 64-256 variant */
|
||||
ROM_AMIXT, /* XT Clone with AMI BIOS */
|
||||
ROM_DTKXT,
|
||||
ROM_IBMXT, /* 301 keyboard error */
|
||||
ROM_IBMXT,
|
||||
ROM_IBMXT86,
|
||||
ROM_GENXT, /* 'Generic XT BIOS' */
|
||||
ROM_JUKOPC,
|
||||
ROM_PORTABLE,
|
||||
|
@@ -22,7 +22,7 @@ uint8_t opl2_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= (int)(isa_timing * 8);
|
||||
cycles -= ISA_CYCLES(8);
|
||||
opl2_update2(opl);
|
||||
return opl_read(0, a);
|
||||
}
|
||||
@@ -39,7 +39,7 @@ uint8_t opl2_l_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= (int)(isa_timing * 8);
|
||||
cycles -= ISA_CYCLES(8);
|
||||
opl2_update2(opl);
|
||||
return opl_read(0, a);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ uint8_t opl2_r_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= (int)(isa_timing * 8);
|
||||
cycles -= ISA_CYCLES(8);
|
||||
opl2_update2(opl);
|
||||
return opl_read(1, a);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ uint8_t opl3_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= (int)(isa_timing * 8);
|
||||
cycles -= ISA_CYCLES(8);
|
||||
opl3_update2(opl);
|
||||
return opl_read(0, a);
|
||||
}
|
||||
|
@@ -463,10 +463,17 @@ cga_poll(void *p)
|
||||
cga->cgadispon = 1;
|
||||
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
|
||||
}
|
||||
if ((cga->crtc[10] & 0x60) == 0x20)
|
||||
cga->cursoron = 0;
|
||||
else
|
||||
cga->cursoron = cga->cgablink & 8;
|
||||
switch (cga->crtc[10] & 0x60) {
|
||||
case 0x20:
|
||||
cga->cursoron = 0;
|
||||
break;
|
||||
case 0x60:
|
||||
cga->cursoron = cga->cgablink & 0x10;
|
||||
break;
|
||||
default:
|
||||
cga->cursoron = cga->cgablink & 0x08;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cga->vc == cga->crtc[7]) {
|
||||
|
@@ -8,13 +8,13 @@
|
||||
*
|
||||
* Hercules emulation.
|
||||
*
|
||||
* Version: @(#)vid_hercules.c 1.0.16 2018/11/18
|
||||
* Version: @(#)vid_hercules.c 1.0.17 2019/02/07
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../io.h"
|
||||
@@ -92,6 +93,7 @@ static void
|
||||
hercules_out(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
hercules_t *dev = (hercules_t *)priv;
|
||||
uint8_t old;
|
||||
|
||||
switch (addr) {
|
||||
case 0x03b0:
|
||||
@@ -105,6 +107,7 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x03b3:
|
||||
case 0x03b5:
|
||||
case 0x03b7:
|
||||
old = dev->crtc[dev->crtcreg];
|
||||
dev->crtc[dev->crtcreg] = val;
|
||||
|
||||
/*
|
||||
@@ -115,11 +118,15 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
|
||||
dev->crtc[10] = 0xb;
|
||||
dev->crtc[11] = 0xc;
|
||||
}
|
||||
recalc_timings(dev);
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
break;
|
||||
|
||||
case 0x03b8:
|
||||
old = dev->ctrl;
|
||||
dev->ctrl = val;
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
break;
|
||||
|
||||
case 0x03bf:
|
||||
@@ -158,7 +165,9 @@ hercules_in(uint16_t addr, void *priv)
|
||||
break;
|
||||
|
||||
case 0x03ba:
|
||||
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4);
|
||||
ret = 0x72; /* Hercules ident */
|
||||
if (dev->stat & 0x08)
|
||||
ret |= 0x88;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -169,12 +178,24 @@ hercules_in(uint16_t addr, void *priv)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hercules_waitstates(void *p)
|
||||
{
|
||||
int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8};
|
||||
int ws;
|
||||
|
||||
ws = ws_array[cycles & 0xf];
|
||||
cycles -= ws;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hercules_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
hercules_t *dev = (hercules_t *)priv;
|
||||
|
||||
dev->vram[addr & 0xffff] = val;
|
||||
hercules_waitstates(dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -184,6 +205,7 @@ hercules_read(uint32_t addr, void *priv)
|
||||
hercules_t *dev = (hercules_t *)priv;
|
||||
|
||||
return(dev->vram[addr & 0xffff]);
|
||||
hercules_waitstates(dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +243,10 @@ hercules_poll(void *priv)
|
||||
ca += 0x8000;
|
||||
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1];
|
||||
if (dev->ctrl & 8)
|
||||
dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1];
|
||||
else
|
||||
dat = 0;
|
||||
dev->ma++;
|
||||
for (c = 0; c < 16; c++) {
|
||||
buffer->line[dev->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0;
|
||||
@@ -231,8 +256,11 @@ hercules_poll(void *priv)
|
||||
}
|
||||
} else {
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
if (dev->ctrl & 8) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
|
||||
@@ -267,9 +295,6 @@ hercules_poll(void *priv)
|
||||
} else {
|
||||
dev->vidtime += dev->dispontime;
|
||||
|
||||
if (dev->dispon)
|
||||
dev->stat &= ~1;
|
||||
|
||||
dev->linepos = 0;
|
||||
if (dev->vsynctime) {
|
||||
dev->vsynctime--;
|
||||
@@ -327,7 +352,8 @@ hercules_poll(void *priv)
|
||||
x = dev->crtc[1] * 9;
|
||||
|
||||
dev->lastline++;
|
||||
if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) {
|
||||
if ((dev->ctrl & 8) &&
|
||||
((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) {
|
||||
xsize = x;
|
||||
ysize = dev->lastline - dev->firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
@@ -360,6 +386,9 @@ hercules_poll(void *priv)
|
||||
dev->ma = dev->maback;
|
||||
}
|
||||
|
||||
if (dev->dispon)
|
||||
dev->stat &= ~1;
|
||||
|
||||
if ((dev->sc == (dev->crtc[10] & 31) ||
|
||||
((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1))))
|
||||
dev->con = 1;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Hercules Plus emulation.
|
||||
*
|
||||
* Version: @(#)vid_herculesplus.c 1.0.14 2018/11/18
|
||||
* Version: @(#)vid_herculesplus.c 1.0.15 2019/02/07
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -113,6 +113,7 @@ static void
|
||||
herculesplus_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
herculesplus_t *dev = (herculesplus_t *)priv;
|
||||
uint8_t old;
|
||||
|
||||
switch (port) {
|
||||
case 0x3b0:
|
||||
@@ -127,6 +128,7 @@ herculesplus_out(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x3b5:
|
||||
case 0x3b7:
|
||||
if (dev->crtcreg > 22) return;
|
||||
old = dev->crtc[dev->crtcreg];
|
||||
dev->crtc[dev->crtcreg] = val;
|
||||
if (dev->crtc[10] == 6 && dev->crtc[11] == 7) {
|
||||
/*Fix for Generic Turbo XT BIOS,
|
||||
@@ -134,11 +136,15 @@ herculesplus_out(uint16_t port, uint8_t val, void *priv)
|
||||
dev->crtc[10] = 0xb;
|
||||
dev->crtc[11] = 0xc;
|
||||
}
|
||||
recalc_timings(dev);
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
return;
|
||||
|
||||
case 0x3b8:
|
||||
old = dev->ctrl;
|
||||
dev->ctrl = val;
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
return;
|
||||
|
||||
case 0x3bf:
|
||||
@@ -414,8 +420,11 @@ text_line(herculesplus_t *dev, uint16_t ca)
|
||||
uint32_t col;
|
||||
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
if (dev->ctrl & 8) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
|
||||
@@ -459,8 +468,11 @@ graphics_line(herculesplus_t *dev)
|
||||
ca += 0x8000;
|
||||
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8)
|
||||
| dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
|
||||
if (dev->ctrl & 8)
|
||||
val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8)
|
||||
| dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
|
||||
else
|
||||
val = 0;
|
||||
|
||||
dev->ma++;
|
||||
for (c = 0; c < 16; c++) {
|
||||
@@ -559,7 +571,8 @@ herculesplus_poll(void *priv)
|
||||
else
|
||||
x = dev->crtc[1] * 9;
|
||||
dev->lastline++;
|
||||
if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) {
|
||||
if ((dev->ctrl & 8) &&
|
||||
((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) {
|
||||
xsize = x;
|
||||
ysize = dev->lastline - dev->firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Hercules InColor emulation.
|
||||
*
|
||||
* Version: @(#)vid_incolor.c 1.0.13 2018/10/11
|
||||
* Version: @(#)vid_incolor.c 1.0.14 2019/02/08
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -210,6 +210,7 @@ static void
|
||||
incolor_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
incolor_t *dev = (incolor_t *)priv;
|
||||
uint8_t old;
|
||||
|
||||
switch (port) {
|
||||
case 0x3b0:
|
||||
@@ -226,6 +227,7 @@ incolor_out(uint16_t port, uint8_t val, void *priv)
|
||||
dev->palette[dev->palette_idx % 16] = val;
|
||||
++dev->palette_idx;
|
||||
}
|
||||
old = dev->crtc[dev->crtcreg];
|
||||
dev->crtc[dev->crtcreg] = val;
|
||||
|
||||
if (dev->crtc[10] == 6 && dev->crtc[11] == 7) {
|
||||
@@ -234,11 +236,15 @@ incolor_out(uint16_t port, uint8_t val, void *priv)
|
||||
dev->crtc[10] = 0xb;
|
||||
dev->crtc[11] = 0xc;
|
||||
}
|
||||
recalc_timings(dev);
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
return;
|
||||
|
||||
case 0x3b8:
|
||||
old = dev->ctrl;
|
||||
dev->ctrl = val;
|
||||
if (old ^ val)
|
||||
recalc_timings(dev);
|
||||
return;
|
||||
|
||||
case 0x3bf:
|
||||
@@ -795,8 +801,11 @@ text_line(incolor_t *dev, uint16_t ca)
|
||||
uint32_t col;
|
||||
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
if (dev->ctrl & 8) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
|
||||
@@ -862,10 +871,13 @@ graphics_line(incolor_t *dev)
|
||||
mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */
|
||||
for (plane = 0; plane < 4; plane++, mask = mask >> 1)
|
||||
{
|
||||
if (mask & 1)
|
||||
val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) |
|
||||
dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
|
||||
else val[plane] = 0;
|
||||
if (dev->ctrl & 8) {
|
||||
if (mask & 1)
|
||||
val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) |
|
||||
dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
|
||||
else val[plane] = 0;
|
||||
} else
|
||||
val[plane] = 0;
|
||||
}
|
||||
dev->ma++;
|
||||
|
||||
@@ -976,7 +988,8 @@ incolor_poll(void *priv)
|
||||
else
|
||||
x = dev->crtc[1] * 9;
|
||||
dev->lastline++;
|
||||
if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) {
|
||||
if ((dev->ctrl & 8) &&
|
||||
((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) {
|
||||
xsize = x;
|
||||
ysize = dev->lastline - dev->firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
|
@@ -85,7 +85,7 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback(
|
||||
lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis ||
|
||||
lpddoi->guidType == GUID_Slider)
|
||||
{
|
||||
memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(state->axis[state->nr_axes].name) + 1);
|
||||
memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
|
||||
joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType);
|
||||
if (lpddoi->guidType == GUID_XAxis)
|
||||
state->axis[state->nr_axes].id = 0;
|
||||
@@ -103,13 +103,13 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback(
|
||||
}
|
||||
else if (lpddoi->guidType == GUID_Button)
|
||||
{
|
||||
memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(state->button[state->nr_buttons].name) + 1);
|
||||
memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
|
||||
joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType);
|
||||
state->nr_buttons++;
|
||||
}
|
||||
else if (lpddoi->guidType == GUID_POV)
|
||||
{
|
||||
memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(state->pov[state->nr_povs].name) + 1);
|
||||
memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
|
||||
joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType);
|
||||
state->nr_povs++;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ void joystick_init()
|
||||
joystick_log("Joystick %i :\n", c);
|
||||
joystick_log(" tszInstanceName = %s\n", device_instance.tszInstanceName);
|
||||
joystick_log(" tszProductName = %s\n", device_instance.tszProductName);
|
||||
memcpy(plat_joystick_state[c].name, device_instance.tszInstanceName, 260);
|
||||
memcpy(plat_joystick_state[c].name, device_instance.tszInstanceName, strlen(device_instance.tszInstanceName) + 1);
|
||||
|
||||
memset(&devcaps, 0, sizeof(devcaps));
|
||||
devcaps.dwSize = sizeof(devcaps);
|
||||
|
@@ -12,7 +12,7 @@
|
||||
* we will not use that, but, instead, use a new window which
|
||||
* coverrs the entire desktop.
|
||||
*
|
||||
* Version: @(#)win_sdl.c 1.0.4 2018/11/18
|
||||
* Version: @(#)win_sdl.c 1.0.5 2019/02/08
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Michael Dr<44>ing, <michael@drueing.de>
|
||||
@@ -62,6 +62,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
/* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */
|
||||
#undef HAVE_STDARG_H
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../device.h"
|
||||
#include "../plat.h"
|
||||
|
Reference in New Issue
Block a user