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:
OBattler
2019-02-11 01:33:15 +01:00
parent a4c11f9536
commit c1f18d9abc
21 changed files with 611 additions and 359 deletions

View File

@@ -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;

View File

@@ -71,6 +71,7 @@
#define CPU_SUPPORTS_DYNAREC 1
#define CPU_REQUIRES_DYNAREC 2
#define CPU_ALTERNATE_XTAL 4
typedef struct {

View File

@@ -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}
};

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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 *);

View File

@@ -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 },

View File

@@ -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
View File

@@ -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();

View File

@@ -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",

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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]) {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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"