From 9e7fc6a60d87fc38c75180873000a25b52d70601 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 Feb 2024 17:52:00 +0100 Subject: [PATCH 1/3] DMA ports 81h and 82h workaround for proper CPU speed detection on the MegaPC BIOS and limited the MegaPC CPU speeds to >= 16 MHz and <= 25 MHz. --- src/dma.c | 46 ++++++++++++++++++++++++++++++------- src/machine/machine_table.c | 4 ++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/dma.c b/src/dma.c index 55cf31236..1dcc3b25b 100644 --- a/src/dma.c +++ b/src/dma.c @@ -949,16 +949,46 @@ dma_page_read(uint16_t addr, UNUSED(void *priv)) uint8_t convert[8] = CHANNELS; uint8_t ret = 0xff; - addr &= 0x0f; - ret = dmaregs[2][addr]; + if (((addr & 0xfffc) == 0x80) && (CS == 0xf000) && + ((cpu_state.pc & 0xfffffff8) == 0x00007278) && + !strcmp(machine_get_internal_name(), "megapc")) switch (addr) { + /* The Amstrad MegaPC Quadtel BIOS times a sequence of: + mov ax,di + div bx + And expects this value to be at least 0x06e0 for 20 MHz, + and at least 0x0898 for 25 MHz, everything below 0x06e0 + is assumed to be 16 MHz. Given that for some reason, this + does not occur on 86Box, we have to work around it here, + we return 0x0528 for 16 MHz, because it's the next in the + mathematical sequence (it equals 0x06e0 - (0x0898 - 0x06e0)). */ + case 0x0081: + if (cpu_busspeed >= 25000000) + ret = 0x98; + else if (cpu_busspeed >= 20000000) + ret = 0xe0; + else + ret = 0x28; + break; + case 0x0082: + if (cpu_busspeed >= 25000000) + ret = 0x08; + else if (cpu_busspeed >= 20000000) + ret = 0x06; + else + ret = 0x05; + break; + } else { + addr &= 0x0f; + ret = dmaregs[2][addr]; - if (addr >= 8) - addr = convert[addr & 0x07] | 4; - else - addr = convert[addr & 0x07]; + if (addr >= 8) + addr = convert[addr & 0x07] | 4; + else + addr = convert[addr & 0x07]; - if (addr < 8) - ret = dma[addr].page_l; + if (addr < 8) + ret = dma[addr].page_l; + } return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 0a0af878e..b45a7471c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4628,8 +4628,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_386SX, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, From ff5ea614eee7857fd5bda0456dd7a22e5ca56cfd Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 Feb 2024 19:56:55 +0100 Subject: [PATCH 2/3] DMA: Change the MegaPC 0528h to 0580h. --- src/dma.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/dma.c b/src/dma.c index 1dcc3b25b..50ae598b8 100644 --- a/src/dma.c +++ b/src/dma.c @@ -959,15 +959,16 @@ dma_page_read(uint16_t addr, UNUSED(void *priv)) and at least 0x0898 for 25 MHz, everything below 0x06e0 is assumed to be 16 MHz. Given that for some reason, this does not occur on 86Box, we have to work around it here, - we return 0x0528 for 16 MHz, because it's the next in the - mathematical sequence (it equals 0x06e0 - (0x0898 - 0x06e0)). */ + we return 0x0580 for 16 MHz, because it logically follows + in the sequence (0x06e0 = 0x0898 * (20 / 25), and + 0x0580 = 0x06e0 * (16 / 20)). */ case 0x0081: if (cpu_busspeed >= 25000000) ret = 0x98; else if (cpu_busspeed >= 20000000) ret = 0xe0; else - ret = 0x28; + ret = 0x80; break; case 0x0082: if (cpu_busspeed >= 25000000) From 91494bab97bcb55d48327e6027a0771e2d181f67 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 3 Feb 2024 04:33:42 +0100 Subject: [PATCH 3/3] 808x: Fix the flags at the end of the ADC and SBB instructions, fixes #4103. --- src/cpu/808x.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 0b6bd66b5..90563d9ab 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1223,34 +1223,48 @@ static void add(int bits) { int size_mask = (1 << bits) - 1; + int special_case = 0; + uint32_t temp_src = cpu_src; + + if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + special_case = 1; cpu_data = cpu_dest + cpu_src; + if ((cpu_alu_op == 2) && (cpu_state.flags & C_FLAG)) + cpu_src--; set_apzs(bits); set_of_add(bits); /* Anything - FF with carry on is basically anything + 0x100: value stays unchanged but carry goes on. */ - if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + if (special_case) cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); + set_cf((temp_src & size_mask) > (cpu_data & size_mask)); } static void sub(int bits) { int size_mask = (1 << bits) - 1; + int special_case = 0; + uint32_t temp_src = cpu_src; + + if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + special_case = 1; cpu_data = cpu_dest - cpu_src; + if ((cpu_alu_op == 3) && (cpu_state.flags & C_FLAG)) + cpu_src--; set_apzs(bits); set_of_sub(bits); /* Anything - FF with carry on is basically anything - 0x100: value stays unchanged but carry goes on. */ - if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + if (special_case) cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); + set_cf((temp_src & size_mask) > (cpu_dest & size_mask)); } static void