From c7c8f0a8147f953c6db64c4a44745d4d05d9b8a1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Jan 2025 14:49:38 +0100 Subject: [PATCH 01/18] Another attempt to fix the hook. --- src/qt/qt_main.cpp | 110 ++++++++++++++++++++++++++------ src/qt/qt_winrawinputfilter.cpp | 50 ++------------- 2 files changed, 93 insertions(+), 67 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index c24f9f8ba..bf8de4070 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -144,6 +144,54 @@ keyboard_getkeymap() } } +void +win_keyboard_handle(uint32_t scancode, int up, int e0, int e1) +{ + /* If it's not a scan code that starts with 0xE1 */ + if (e1) { + if (scancode == 0x1D) { + scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would + otherwise be E0 00 but that is invalid + anyway). + Also, take a potential mapping into + account. */ + } else + scancode = 0xFFFF; + if (scancode != 0xFFFF) + keyboard_input(!up, scancode); + } else { + if (e0) + scancode |= 0x100; + + /* Translate the scan code to 9-bit */ + scancode = convert_scan_code(scancode); + + /* Remap it according to the list from the Registry */ + if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { + // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); + scancode = scancode_map[scancode]; + } + + /* If it's not 0xFFFF, send it to the emulated + keyboard. + We use scan code 0xFFFF to mean a mapping that + has a prefix other than E0 and that is not E1 1D, + which is, for our purposes, invalid. */ + + /* Translate right CTRL to left ALT if the user has so + chosen. */ + if ((scancode == 0x11d) && rctrl_is_lalt) + scancode = 0x038; + + /* Normal scan code pass through, pass it through as is if + it's not an invalid scan code. */ + if (scancode != 0xFFFF) + keyboard_input(!up, scancode); + + main_window->checkFullscreenHotkey(); + } +} + static LRESULT CALLBACK emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { @@ -151,6 +199,23 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) /* Checks if CTRL was pressed. */ BOOL bCtrlDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1); BOOL is_over_window = (GetForegroundWindow() == ((HWND) main_window->winId())); + BOOL ret = TRUE; +/* Leave this in, in case we have to still bring hook input back. */ +#ifdef HOOK_INPUT_TESTS + static int last = 0; + + pclog("Old: %08X, %08X, %08X, %i\n", lpKdhs->scanCode, lpKdhs->flags, lpKdhs->vkCode, last); + + if (!last && (lpKdhs->scanCode == 0x00000036)) + lpKdhs->flags &= ~LLKHF_EXTENDED; + + if (lpKdhs->scanCode == 0x00000236) + last = 1; + else if (last && (lpKdhs->scanCode == 0x00000036)) + last = 0; + + pclog("New: %08X, %08X, %08X, %i\n", lpKdhs->scanCode, lpKdhs->flags, lpKdhs->vkCode, last); +#endif if (show_second_monitors) for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { const auto &secondaryRenderer = main_window->renderers[monitor_index]; @@ -158,30 +223,34 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) (GetForegroundWindow() == ((HWND) secondaryRenderer->winId()))); } - if ((nCode < 0) || (nCode != HC_ACTION)/* || (!mouse_capture && !video_fullscreen)*/ || !is_over_window) + if ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window) return CallNextHookEx(NULL, nCode, wParam, lParam); else if ((lpKdhs->scanCode == 0x01) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x01) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x0f) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x0f) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x39) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x3e) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x49) && bCtrlDown && !(lpKdhs->flags & LLKHF_UP)) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) - return TRUE; + ret = TRUE; else return CallNextHookEx(NULL, nCode, wParam, lParam); + + win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0); + + return ret; } #endif @@ -455,6 +524,15 @@ main(int argc, char *argv[]) hook_enabled = 0; } + if (hook_enabled) { + /* Yes, low-level hooks *DO* work with raw input, at least global ones. */ + llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0); + atexit([] () -> void { + if (llhook) + UnhookWindowsHookEx(llhook); + }); + } + /* Setup raw input */ auto rawInputFilter = WindowsRawInputFilter::Register(main_window); if (rawInputFilter) { @@ -507,7 +585,6 @@ main(int argc, char *argv[]) /* Initialize the rendering window, or fullscreen. */ QTimer::singleShot(0, &app, [] { pc_reset_hard_init(); - main_thread = new std::thread(main_thread_fn); /* Set the PAUSE mode depending on the renderer. */ #ifdef USE_VNC @@ -516,18 +593,9 @@ main(int argc, char *argv[]) else #endif plat_pause(0); - }); -#ifdef Q_OS_WINDOWS - if (hook_enabled) { - /* Yes, low-level hooks *DO* work with raw input, at least global ones. */ - llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0); - atexit([] () -> void { - if (llhook) - UnhookWindowsHookEx(llhook); - }); - } -#endif + main_thread = new std::thread(main_thread_fn); + }); const auto ret = app.exec(); cpu_thread_run = 0; diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 2c11a068a..3a2109c8e 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -44,6 +44,8 @@ #include <86box/plat.h> #include <86box/86box.h> +extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); + #include #include @@ -166,54 +168,10 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input) void WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) { - USHORT scancode; - RAWKEYBOARD rawKB = raw->data.keyboard; - scancode = rawKB.MakeCode; - /* If it's not a scan code that starts with 0xE1 */ - if ((rawKB.Flags & RI_KEY_E1)) { - if (rawKB.MakeCode == 0x1D) { - scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would - otherwise be E0 00 but that is invalid - anyway). - Also, take a potential mapping into - account. */ - } else - scancode = 0xFFFF; - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - } else { - if (rawKB.Flags & RI_KEY_E0) - scancode |= 0x100; - - /* Translate the scan code to 9-bit */ - scancode = convert_scan_code(scancode); - - /* Remap it according to the list from the Registry */ - if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { - // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); - scancode = scancode_map[scancode]; - } - - /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - - /* Translate right CTRL to left ALT if the user has so - chosen. */ - if ((scancode == 0x11d) && rctrl_is_lalt) - scancode = 0x038; - - /* Normal scan code pass through, pass it through as is if - it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - - window->checkFullscreenHotkey(); - } + win_keyboard_handle(rawKB.MakeCode, (rawKB.Flags & RI_KEY_BREAK), + (rawKB.Flags & RI_KEY_E0), (rawKB.Flags & RI_KEY_E1)); } void From 5a40204e31637e7e3b3b5b0cb28e4efdfdd85dc1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Jan 2025 16:04:46 +0100 Subject: [PATCH 02/18] Windows: Bring back hook input, this time with fixes for right Shift and Pause. --- src/qt/qt_main.cpp | 37 +++++++++++++++++++-------------- src/qt/qt_winrawinputfilter.cpp | 15 +++++++------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index bf8de4070..eb3c0df82 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -200,23 +200,9 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) BOOL bCtrlDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1); BOOL is_over_window = (GetForegroundWindow() == ((HWND) main_window->winId())); BOOL ret = TRUE; -/* Leave this in, in case we have to still bring hook input back. */ -#ifdef HOOK_INPUT_TESTS + static int last = 0; - pclog("Old: %08X, %08X, %08X, %i\n", lpKdhs->scanCode, lpKdhs->flags, lpKdhs->vkCode, last); - - if (!last && (lpKdhs->scanCode == 0x00000036)) - lpKdhs->flags &= ~LLKHF_EXTENDED; - - if (lpKdhs->scanCode == 0x00000236) - last = 1; - else if (last && (lpKdhs->scanCode == 0x00000036)) - last = 0; - - pclog("New: %08X, %08X, %08X, %i\n", lpKdhs->scanCode, lpKdhs->flags, lpKdhs->vkCode, last); -#endif - if (show_second_monitors) for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { const auto &secondaryRenderer = main_window->renderers[monitor_index]; is_over_window = is_over_window || ((secondaryRenderer != nullptr) && @@ -246,7 +232,26 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) ret = TRUE; else - return CallNextHookEx(NULL, nCode, wParam, lParam); + ret = CallNextHookEx(NULL, nCode, wParam, lParam); + + if (lpKdhs->scanCode == 0x00000045) { + if ((lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000090)) { + /* NumLock. */ + lpKdhs->flags &= ~LLKHF_EXTENDED; + } else if (!(lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000013)) { + /* Pause - send E1 1D. */ + pclog("Send E1 1D\n"); + win_keyboard_handle(0xe1, 0, 0, 0); + win_keyboard_handle(0x1d, 0, 0, 0); + } + } else if (!last && (lpKdhs->scanCode == 0x00000036)) + /* Non-fake right shift. */ + lpKdhs->flags &= ~LLKHF_EXTENDED; + + if (lpKdhs->scanCode == 0x00000236) + last = 1; + else if (last && (lpKdhs->scanCode == 0x00000036)) + last = 0; win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0); diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 3a2109c8e..a1da0af61 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -66,7 +66,9 @@ WindowsRawInputFilter::Register(MainWindow *window) .hwndTarget = nullptr} }; - if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE) + if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE)) + return std::unique_ptr(nullptr); + else if (!hook_enabled && (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)) return std::unique_ptr(nullptr); std::unique_ptr inputfilter(new WindowsRawInputFilter(window)); @@ -97,7 +99,10 @@ WindowsRawInputFilter::~WindowsRawInputFilter() .hwndTarget = NULL} }; - RegisterRawInputDevices(rid, 2, sizeof(rid[0])); + if (hook_enabled) + RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])); + else + RegisterRawInputDevices(rid, 2, sizeof(rid[0])); } bool @@ -155,10 +160,8 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input) mouse_handle(raw); break; case RIM_TYPEHID: - { - win_joystick_handle(raw); - break; - } + win_joystick_handle(raw); + break; } } } From 117bbc43c7d0a5054ce72a48cef99a98c00935d6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Jan 2025 19:44:03 +0100 Subject: [PATCH 03/18] Windows: Pause's fake CTRL needs to be adjusted for break code as well. --- src/qt/qt_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index eb3c0df82..c61fa1960 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -242,7 +242,7 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) /* Pause - send E1 1D. */ pclog("Send E1 1D\n"); win_keyboard_handle(0xe1, 0, 0, 0); - win_keyboard_handle(0x1d, 0, 0, 0); + win_keyboard_handle(0x1d, LLKHF_UP, 0, 0); } } else if (!last && (lpKdhs->scanCode == 0x00000036)) /* Non-fake right shift. */ From 2d25a116ad039015eee11651cf62b3de7cf2fb25 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 4 Jan 2025 20:43:59 +0100 Subject: [PATCH 04/18] Refine the FDD PS/1 and PS/2 check to ignore the PS/ValuePoint machines, fixes #5101. --- src/floppy/fdd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 3a0b03a9b..a381f67f1 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -294,7 +294,7 @@ fdd_type_invert_densel(int type) int ret; if (drive_types[type].flags & FLAG_PS2) - ret = !!strstr(machine_getname(), "PS/"); + ret = (!!strstr(machine_getname(), "PS/1")) || (!!strstr(machine_getname(), "PS/2")); else ret = drive_types[type].flags & FLAG_INVERT_DENSEL; From 0a73b6e1b6f2dec5ca338201d350439bcff9e583 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 3 Jan 2025 15:58:13 -0500 Subject: [PATCH 05/18] Fixes to es137x code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes Battler noticed. Co-Authored-By: TC1995 <9269715+TC1995@users.noreply.github.com> Co-Authored-By: Miran Grča --- src/sound/snd_audiopci.c | 91 +++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index c4f1c2f90..ec3501f81 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -446,11 +446,13 @@ es137x_reset(void *priv) /* Interrupt/Chip Select Status Register, Address 04H Addressable as longword only */ - if (dev->type >= AUDIOPCI_CT5880) + if (dev->type == AUDIOPCI_ES1370) + dev->int_status = 0x00000060; + else if (dev->type == AUDIOPCI_CT5880) dev->int_status = 0x52080ec0; - else if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + else if (dev->type == AUDIOPCI_ES1373) dev->int_status = 0x7f080ec0; - else + else /* AUDIOPCI_ES1371 */ dev->int_status = 0x7ffffec0; /* UART Status Register, Address 09H @@ -784,7 +786,7 @@ es137x_inb(uint16_t port, void *priv) break; case 0x03: ret = dev->int_ctrl >> 24; - if ((dev->type < AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if (dev->type == AUDIOPCI_ES1371) ret |= 0xfc; break; @@ -857,19 +859,19 @@ es137x_inb(uint16_t port, void *priv) /* S/PDIF Channel Status Control Register, Address 1CH Addressable as byte, word, longword */ case 0x1c: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus & 0xff; break; case 0x1d: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 8; break; case 0x1e: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 16; break; case 0x1f: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 24; break; @@ -882,10 +884,15 @@ es137x_inb(uint16_t port, void *priv) ret = dev->si_cr >> 8; break; case 0x22: - ret = (dev->si_cr >> 16) | 0x80; + ret = dev->si_cr >> 16; + if (dev->type != AUDIOPCI_ES1370) + ret |= 0x80; break; case 0x23: - ret = 0xff; + if (dev->type == AUDIOPCI_ES1370) + ret = 0x00; + else + ret = 0xff; break; default: @@ -910,7 +917,7 @@ es137x_inw(uint16_t port, void *priv) break; case 0x02: ret = (dev->int_ctrl >> 16) & 0xff0f; - if ((dev->type < AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if (dev->type == AUDIOPCI_ES1371) ret |= 0xfc00; break; @@ -935,11 +942,11 @@ es137x_inw(uint16_t port, void *priv) /* S/PDIF Channel Status Control Register, Address 1CH Addressable as byte, word, longword */ case 0x1c: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus & 0xffff; break; case 0x1e: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 16; break; @@ -949,7 +956,9 @@ es137x_inw(uint16_t port, void *priv) ret = dev->si_cr & 0xffff; break; case 0x22: - ret = (dev->si_cr >> 16) | 0xff80; + ret = dev->si_cr >> 16; + if (dev->type != AUDIOPCI_ES1370) + ret |= 0xff80; break; /* DAC1 Channel Sample Count Register, Address 24H @@ -1056,14 +1065,16 @@ es137x_inl(uint16_t port, void *priv) /* S/PDIF Channel Status Control Register, Address 1CH Addressable as byte, word, longword */ case 0x1c: - if ((dev->type >= AUDIOPCI_ES1373) || (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus; break; /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - ret = dev->si_cr | 0xff800000; + ret = dev->si_cr; + if (dev->type != AUDIOPCI_ES1370) + ret |= 0xff800000; break; /* DAC1 Channel Sample Count Register, Address 24H @@ -1148,11 +1159,11 @@ es137x_outb(uint16_t port, uint8_t val, void *priv) Addressable as longword only, but PCem implements byte access, which must be for a reason */ case 0x06: - if ((dev->type >= AUDIOPCI_ES1373) || (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) dev->int_status = (dev->int_status & 0xff08ffff) | (val << 16); break; case 0x07: - if ((dev->type >= AUDIOPCI_CT5880) || (dev->type != AUDIOPCI_ES1370)) + if (dev->type == AUDIOPCI_CT5880) dev->int_status = (dev->int_status & 0xd2ffffff) | (val << 24); break; @@ -1235,18 +1246,28 @@ es137x_outb(uint16_t port, uint8_t val, void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - dev->si_cr = (dev->si_cr & 0xffffff00) | val; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xffff00) | val; + else + dev->si_cr = (dev->si_cr & 0xffffff00) | val; break; case 0x21: - dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xff00ff) | (val << 8); + else + dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); if (!(dev->si_cr & SI_P1_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC1; if (!(dev->si_cr & SI_P2_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC2; + es137x_update_irqs(dev); break; case 0x22: - dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16); + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xc0ffff) | ((val & 0x3f) << 16); + else + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16); break; default: @@ -1334,7 +1355,11 @@ es137x_outw(uint16_t port, uint16_t val, void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - dev->si_cr = (dev->si_cr & 0xffff0000) | val; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xff0000) | val; + else + dev->si_cr = (dev->si_cr & 0xffff0000) | val; + if (!(dev->si_cr & SI_P1_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC1; if (!(dev->si_cr & SI_P2_INTR_EN)) @@ -1342,7 +1367,10 @@ es137x_outw(uint16_t port, uint16_t val, void *priv) es137x_update_irqs(dev); break; case 0x22: - dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xc0ffff) | ((val & 0x3f) << 16); + else + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); break; /* DAC1 Channel Sample Count Register, Address 24H @@ -1417,9 +1445,9 @@ es137x_outl(uint16_t port, uint32_t val, void *priv) Addressable as longword only */ case 0x04: audiopci_log("[W] STATUS = %08X\n", val); - if (dev->type >= AUDIOPCI_CT5880) + if (dev->type == AUDIOPCI_CT5880) dev->int_status = (dev->int_status & 0xd208ffff) | (val & 0x2df70000); - else if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + else if (dev->type == AUDIOPCI_ES1373) dev->int_status = (dev->int_status & 0xff08ffff) | (val & 0x00f70000); break; @@ -1523,7 +1551,10 @@ es137x_outl(uint16_t port, uint32_t val, void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - dev->si_cr = (val & 0x007fffff) | 0xff800000; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = val & 0x3fffff; + else + dev->si_cr = (val & 0x007fffff) | 0xff800000; if (!(dev->si_cr & SI_P1_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC1; if (!(dev->si_cr & SI_P2_INTR_EN)) @@ -2032,7 +2063,7 @@ es1371_pci_read(int func, int addr, void *priv) return 0x80; /* Maximum latency */ case 0x40: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) return dev->subsys_lock; break; @@ -2163,7 +2194,7 @@ es1371_pci_write(int func, int addr, uint8_t val, void *priv) break; case 0x40: - if ((dev->type >= AUDIOPCI_ES1373) && (dev->type != AUDIOPCI_ES1370)) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) dev->subsys_lock = val; break; @@ -2386,7 +2417,7 @@ es137x_poll(void *priv) es137x_update(dev); if (dev->int_ctrl & INT_DAC1_EN) { - if (((dev->type >= AUDIOPCI_ES1373) && (dev->int_ctrl & INT_DAC1_BYPASS)) || (dev->type == AUDIOPCI_ES1370)) { + if ((((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) && (dev->int_ctrl & INT_DAC1_BYPASS)) || (dev->type == AUDIOPCI_ES1370)) { if ((dev->calc_sample_rate_synth != 44100) && (dev->type == AUDIOPCI_ES1370)) { if ((dev->dac[0].buffer_pos - dev->dac[0].buffer_pos_end) >= 0 && dev->step_synth >= dev->interp_step_synth) es137x_fetch(dev, 0); @@ -2444,7 +2475,7 @@ dac0_count: } if (dev->int_ctrl & INT_DAC2_EN) { - if (((dev->type >= AUDIOPCI_ES1373) && (dev->int_ctrl & INT_DAC2_BYPASS)) || (dev->type == AUDIOPCI_ES1370)) { + if ((((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) && (dev->int_ctrl & INT_DAC2_BYPASS)) || (dev->type == AUDIOPCI_ES1370)) { if ((dev->calc_sample_rate != 44100) && (dev->type == AUDIOPCI_ES1370)) { if ((dev->dac[1].buffer_pos - dev->dac[1].buffer_pos_end) >= 0 && dev->step_pcm >= dev->interp_step) es137x_fetch(dev, 1); From 8dc0beaeec0224ecb780e5e7ba7c35ed6b4bcab2 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Sun, 5 Jan 2025 12:15:01 +0600 Subject: [PATCH 06/18] pc87307: Fix GPIO base address configuration Don't clobber the GPIO I/O Base value. According to the PC87307 datasheet, port 0x60 bits [2:7] are read-only for the Parallel Port (4) device and cannot be altered by software. For others devices, the 0x60 port may be written with any value. The SGI firmware emits the following PC87307 initialization sequence after each reset: /* Select the GPIO device (7) */ SIO IDX: 2E <-- 07 SIO DAT: 2F <-- 07 /* I/O Base MSB = 0x0F */ SIO IDX: 2E <-- 60 SIO DAT: 2F <-- 0F /* I/O Base LSB = 0xC0 */ SIO IDX: 2E <-- 61 SIO DAT: 2F <-- C0 /* Enable address decoding (I/O Base = 0xFC0) */ SIO IDX: 2E <-- 30 SIO DAT: 2F <-- 01 The GPIO I/O Base is erroneously assigned to 0x7C0. Fix by removing the 0x07 mask. --- src/sio/sio_pc87307.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index 63e19c03d..cb772aa5b 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -34,6 +34,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_fallthrough.h> typedef struct pc87307_t { uint8_t id; @@ -323,8 +324,12 @@ pc87307_write(uint16_t port, uint8_t val, void *priv) } break; case 0x60: + if (dev->regs[0x07] == 0x04) { + val &= 0x03; + } + fallthrough; case 0x62: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07)) break; switch (dev->regs[0x07]) { From eaa4f1637978e89df820a4e3f3e5fed7c9d18544 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Jan 2025 16:42:24 +0100 Subject: [PATCH 07/18] Windows hook input: Remove an excessive log line. --- src/qt/qt_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index c61fa1960..f77370574 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -240,7 +240,6 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) lpKdhs->flags &= ~LLKHF_EXTENDED; } else if (!(lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000013)) { /* Pause - send E1 1D. */ - pclog("Send E1 1D\n"); win_keyboard_handle(0xe1, 0, 0, 0); win_keyboard_handle(0x1d, LLKHF_UP, 0, 0); } From 3226999246af7afc6d3d9e988b5cedd947a4fe80 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 5 Jan 2025 14:47:39 -0500 Subject: [PATCH 08/18] Fix wrong sample rate of ES1370 software synth playback Fixes low pitch problems when MIDI is played back through the software synth. Co-Authored-By: Cacodemon345 <38420290+Cacodemon345@users.noreply.github.com> --- src/sound/snd_audiopci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index ec3501f81..62a8e0056 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -423,9 +423,9 @@ es1370_calc_sample_rate(es137x_t *dev) dev->calc_sample_rate = 5512; } - dev->calc_sample_rate_synth = 44100 / (1 << ((dev->int_ctrl >> 12) & 3)); - dev->interp_factor_synth = 1. / (double) (1 << ((dev->int_ctrl >> 12) & 3)); - dev->interp_step_synth = (1 << ((dev->int_ctrl >> 12) & 3)); + dev->calc_sample_rate_synth = 44100 / (1 << (((dev->int_ctrl >> 12) & 3) ^ 3)); + dev->interp_factor_synth = 1. / (double) ((1 << ((dev->int_ctrl >> 12) & 3) ^ 3)); + dev->interp_step_synth = (1 << (((dev->int_ctrl >> 12) & 3) ^ 3)); } static void From ee099eba07eab2245345eafcafaf13eedb1f41ca Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 5 Jan 2025 16:16:12 -0500 Subject: [PATCH 09/18] Add CT1297 to CT5880, seen on the CT4810 --- src/sound/snd_audiopci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index ec3501f81..92ec5a8f4 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -2828,6 +2828,10 @@ static const device_config_t ct5880_config[] = { .description = "SigmaTel STAC9721T (stereo)", .value = AC97_CODEC_STAC9721 }, + { + .description = "TriTech TR28023 / Creative CT1297", + .value = AC97_CODEC_TR28023 + }, { .description = "" } }, .default_int = AC97_CODEC_STAC9708 From 6b05602ea4d1593edf8d0fff17e733b182e94637 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Jan 2025 22:35:50 +0100 Subject: [PATCH 10/18] QT: Increase buffer size and improve sanity checking when removing an image. --- src/qt/qt_mediahistorymanager.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_mediahistorymanager.cpp b/src/qt/qt_mediahistorymanager.cpp index 2acdc8e5b..d548c0779 100644 --- a/src/qt/qt_mediahistorymanager.cpp +++ b/src/qt/qt_mediahistorymanager.cpp @@ -336,16 +336,20 @@ MediaHistoryManager::removeMissingImages(device_index_list_t &device_history) continue; } - char temp[MAX_IMAGE_PATH_LEN -1] = { 0 }; + char temp[MAX_IMAGE_PATH_LEN * 2] = { 0 }; if (path_abs(checked_path.toUtf8().data())) { if (checked_path.length() > (MAX_IMAGE_PATH_LEN - 1)) - fatal("removeMissingImages(): checked_path.length() > 2047\n"); + fatal("removeMissingImages(): checked_path.length() > %i\n", MAX_IMAGE_PATH_LEN - 1); else snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s", checked_path.toUtf8().constData()); - } else - snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, - path_get_slash(usr_path), checked_path.toUtf8().constData()); + } else { + if ((strlen(usr_path) + strlen(path_get_slash(usr_path)) + checked_path.length()) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("removeMissingImages(): Combined absolute path length > %i\n", MAX_IMAGE_PATH_LEN - 1); + else + snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, + path_get_slash(usr_path), checked_path.toUtf8().constData()); + } path_normalize(temp); QString qstr = QString::fromUtf8(temp); From 50c97f01582c64bdecb5d17a0e5468c45de7fc7f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Jan 2025 16:59:15 +0100 Subject: [PATCH 11/18] Voodoo 3/Banshee: Some CMDFIFO fixes. --- src/video/vid_voodoo_banshee.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 0c5e5f7bb..4fa27e2e4 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -1095,7 +1095,7 @@ banshee_status(banshee_t *banshee) int fifo_entries = FIFO_ENTRIES; int swap_count = voodoo->swap_count; int written = voodoo->cmd_written + voodoo->cmd_written_fifo; - int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] || voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] || voodoo->voodoo_busy; + int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || (voodoo->cmdfifo_depth_rd_2 != voodoo->cmdfifo_depth_wr_2) || voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] || voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] || voodoo->voodoo_busy; uint32_t ret = 0; if (fifo_entries < 0x20) @@ -1117,6 +1117,9 @@ banshee_status(banshee_t *banshee) if (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) ret |= (1 << 11); + if (voodoo->cmdfifo_depth_rd_2 != voodoo->cmdfifo_depth_wr_2) + ret |= (1 << 12); + if (!voodoo->voodoo_busy) voodoo_wake_fifo_thread(voodoo); From e833e1da3fdcede2d147dba3e22b1f9627f3f1ae Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Jan 2025 20:12:49 +0100 Subject: [PATCH 12/18] Force resizes on overscan parameter changes. --- src/video/vid_svga.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5054bd8e7..6a91713fb 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -628,6 +628,8 @@ svga_recalctimings(svga_t *svga) int hsyncstart; int hsyncend; #endif + int old_monitor_overscan_x = svga->monitor->mon_overscan_x; + int old_monitor_overscan_y = svga->monitor->mon_overscan_y; svga->vtotal = svga->crtc[6]; svga->dispend = svga->crtc[0x12]; @@ -1009,6 +1011,9 @@ svga_recalctimings(svga_t *svga) svga->dpms_ui = 0; ui_sb_set_text_w(NULL); } + + if (enable_overscan && (svga->monitor->mon_overscan_x != old_monitor_overscan_x || svga->monitor->mon_overscan_y != old_monitor_overscan_y)) + video_force_resize_set_monitor(1, svga->monitor_index); } static void From c3faf20226192f02e17b25d3612541bfd2278480 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Jan 2025 02:42:09 +0100 Subject: [PATCH 13/18] AHA-1542CP and ISA PnP memory range fixes, fixes AHA-1542CP on Packard Bell PB450. --- src/device/isapnp.c | 47 +++++++++++++++++++++++++++++++++++------ src/scsi/scsi_aha154x.c | 8 +++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 0139eeb23..470147953 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -137,6 +137,8 @@ isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld) card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ card->config.mem[i].size -= card->config.mem[i].base; + else + card->config.mem[i].size = (card->config.mem[i].size | 0xff) ^ 0xffffffff; } for (uint8_t i = 0; i < 4; i++) { reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); @@ -789,10 +791,25 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) break; } - isapnp_log("ISAPnP: >>%s Memory range %d with %d bytes at %06X-%06X, align %d", - in_df ? ">" : "", mem_range, - *((uint16_t *) &card->rom[i + 10]) << 8, *((uint16_t *) &card->rom[i + 4]) << 8, ((card->rom[i + 3] & 0x4) ? 0 : (*((uint16_t *) &card->rom[i + 4]) << 8)) + (*((uint16_t *) &card->rom[i + 6]) << 8), - (*((uint16_t *) &card->rom[i + 8]) + 1) << 16); + isapnp_log("ISAPnP: >>%s Memory range %d with %d bytes at %06X-%06X to %06X-%06X, align %d", + /* %s */ in_df ? ">" : "", + /* %d */ mem_range, + /* %d */ *((uint16_t *) &card->rom[i + 8]), + /* %06X */ *((uint16_t *) &card->rom[i + 4]) << 8, + /* %06X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + (*((uint16_t *) &card->rom[i + 10]) << 8) : + /* Range. */ + (*((uint16_t *) &card->rom[i + 4]) << 8)) + + (*((uint16_t *) &card->rom[i + 10]) << 8), + /* %06X */ *((uint16_t *) &card->rom[i + 6]) << 8, + /* %06X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + (*((uint16_t *) &card->rom[i + 10]) << 8) : + /* Range. */ + (*((uint16_t *) &card->rom[i + 6]) << 8)) + + (*((uint16_t *) &card->rom[i + 10]) << 8), + /* %d */ *((uint16_t *) &card->rom[i + 8])); res = 1 << mem_range; mem_range++; } else { @@ -806,9 +823,25 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) break; } - isapnp_log("ISAPnP: >>%s 32-bit memory range %d with %d bytes at %08X-%08X, align %d", in_df ? ">" : "", mem_range_32, - *((uint32_t *) &card->rom[i + 16]) << 8, *((uint32_t *) &card->rom[i + 4]) << 8, ((card->rom[i + 3] & 0x4) ? 0 : (*((uint32_t *) &card->rom[i + 4]) << 8)) + (*((uint32_t *) &card->rom[i + 8]) << 8), - *((uint32_t *) &card->rom[i + 12])); + isapnp_log("ISAPnP: >>%s 32-bit memory range %d with %d bytes at %08X-%08X, align %d", + /* %s */ in_df ? ">" : "", + /* %d */ mem_range_32, + /* %d */ *((uint32_t *) &card->rom[i + 12]), + /* %08X */ *((uint32_t *) &card->rom[i + 4]), + /* %08X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + *((uint32_t *) &card->rom[i + 16]) : + /* Range. */ + *((uint32_t *) &card->rom[i + 4])) + + *((uint32_t *) &card->rom[i + 16]), + /* %08X */ *((uint32_t *) &card->rom[i + 8]), + /* %08X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + *((uint32_t *) &card->rom[i + 16]) : + /* Range. */ + *((uint32_t *) &card->rom[i + 8])) + + *((uint32_t *) &card->rom[i + 16]), + /* %d */ *((uint32_t *) &card->rom[i + 12])); res = 1 << (4 + mem_range_32); mem_range_32++; } diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index e3f38c4e5..58779e7ac 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -678,6 +678,7 @@ aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) aha_eeprom_save(dev); dev->rom_addr = config->mem[0].base; + aha_log("Base = %08X, Size = %08X\n", config->mem[0].base, config->mem[0].size); if (dev->rom_addr) { mem_mapping_enable(&dev->bios.mapping); aha_log("SCSI BIOS set to: %08X-%08X\n", dev->rom_addr, dev->rom_addr + config->mem[0].size - 1); @@ -869,13 +870,12 @@ aha_setmcode(x54x_t *dev) } aha1542cp_pnp_rom = (uint8_t *) malloc(dev->pnp_len + 7); fseek(fp, dev->pnp_offset, SEEK_SET); - (void) !fread(aha1542cp_pnp_rom, dev->pnp_len, 1, fp); + (void) !fread(aha1542cp_pnp_rom, 4, 1, fp); memset(&(aha1542cp_pnp_rom[4]), 0x00, 5); fseek(fp, dev->pnp_offset + 4, SEEK_SET); (void) !fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, fp); - /* Even the real AHA-1542CP microcode seem to be flipping bit - 4 to not erroneously indicate there is a range length. */ - aha1542cp_pnp_rom[0x87] |= 0x04; + /* Patch determined from Dizzy's AHA-1542CP PNP ROM dump. */ + aha1542cp_pnp_rom[0x26] = 0x03; /* Insert the terminator and the checksum byte that will later be filled in by the isapnp code. */ aha1542cp_pnp_rom[dev->pnp_len + 5] = 0x79; From 632c490d93cac9f7fb7b9b5fdbbd1b022fbfe4b6 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 16 Nov 2022 02:04:28 -0500 Subject: [PATCH 14/18] Atari PC 3 --- src/include/86box/machine.h | 1 + src/machine/m_xt.c | 24 +++++++++++++++++++++++ src/machine/machine_table.c | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 44a55d94f..c84a6176f 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -916,6 +916,7 @@ extern int machine_xt86_init(const machine_t *); extern int machine_xt_americxt_init(const machine_t *); extern int machine_xt_amixt_init(const machine_t *); +extern int machine_xt_ataripc3_init(const machine_t *); extern int machine_xt_dtk_init(const machine_t *); extern int machine_xt_jukopc_init(const machine_t *); extern int machine_xt_openxt_init(const machine_t *); diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 008acbff2..62466bf91 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -212,6 +212,30 @@ machine_xt_amixt_init(const machine_t *model) return ret; } +// TODO +// Onboard EGA Graphics (NSI Logic EVC315-S on early boards STMicroelectronics EGA on later revisions) +// Adaptec ACB-2072 RLL Controller Card (Optional) +// Atari PCM1 Mouse Support +int +machine_xt_ataripc3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ataripc3/AWARD_ATARI_PC_BIOS_3.08.BIN", + 0x000f8000, 32768, 0); +#if 0 + ret = bios_load_linear("roms/machines/ataripc3/c101701-004 308.u61", + 0x000f8000, 0x8000, 0); +#endif + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model, 0); + + return ret; +} + int machine_xt_znic_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f5a0a9d1c..a14dbc692 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -484,6 +484,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8088] Atari PC 3", + .internal_name = "ataripc3", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_ataripc3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FDC, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, //&fdc_xt_device, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, { .name = "[8088] Bondwell BW230", .internal_name = "bw230", From 8bb65dcfa27e77eb1729cdda112ba9b888a6fb07 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 16 Nov 2022 02:04:40 -0500 Subject: [PATCH 15/18] Atari PC 4 --- src/include/86box/machine.h | 1 + src/machine/m_at_286_386sx.c | 31 ++++++++++++++++++++++++++++ src/machine/machine_table.c | 39 ++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c84a6176f..ad8b47638 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -450,6 +450,7 @@ extern int machine_at_mr286_init(const machine_t *); extern int machine_at_neat_init(const machine_t *); extern int machine_at_neat_ami_init(const machine_t *); +extern int machine_at_ataripc4_init(const machine_t *); extern int machine_at_quadt386sx_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 36629658f..9c1eb817b 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -212,6 +212,37 @@ machine_at_neat_ami_init(const machine_t *model) return ret; } +// TODO +// Onboard Paradise PVGA1A-JK VGA Graphics +// Data Technology Corporation DTC7187 RLL Controller +int +machine_at_ataripc4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ataripc4/AMI_PC4X_1.7_EVEN.BIN", + "roms/machines/ataripc4/AMI_PC4X_1.7_ODD.BIN", +#if 0 + ret = bios_load_interleaved("roms/machines/ataripc4/ami_pc4x_1.7_even.bin", + "roms/machines/ataripc4/ami_pc4x_1.7_odd.bin", +#endif + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&neat_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&keyboard_at_ami_device); + + return ret; +} + int machine_at_px286_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a14dbc692..b60d35fd7 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3444,6 +3444,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[NEAT] Atari PC 4", + .internal_name = "ataripc4", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_ataripc4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FDC, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = &keyboard_at_ami_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, //&fdc_at_device, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has "AMI KEYBOARD BIOS", most likely 'F'. */ { .name = "[NEAT] DataExpert 286", From f39c3491bff09003c896d97c7d369246e9152844 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Jan 2025 11:26:15 +0100 Subject: [PATCH 16/18] Voodoo: Fixes HUD transparency bugs in Extreme Assault Voodoo executable (interpreter and x86-64 recompiler only). --- src/include/86box/vid_voodoo_codegen_x86-64.h | 46 +++++++++++++++++-- src/include/86box/vid_voodoo_render.h | 16 ++++--- src/video/vid_voodoo_fb.c | 14 ++++++ src/video/vid_voodoo_render.c | 8 ++++ 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/include/86box/vid_voodoo_codegen_x86-64.h b/src/include/86box/vid_voodoo_codegen_x86-64.h index dc0ebce72..e8b7299f2 100644 --- a/src/include/86box/vid_voodoo_codegen_x86-64.h +++ b/src/include/86box/vid_voodoo_codegen_x86-64.h @@ -2157,6 +2157,12 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0xc2); } + addbyte(0xf3); /*MOVQ XMM15(colbfog), XMM0 */ + addbyte(0x44); + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xf8); + if (params->fogMode & FOG_ENABLE) { if (params->fogMode & FOG_CONSTANT) { addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ @@ -2580,17 +2586,17 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0xef); addbyte(0xe4); break; - case AFUNC_ASATURATE: - addbyte(0x66); /*PMULLW XMM4, XMM11(minus_254)*/ + case AFUNC_ACOLORBEFOREFOG: + addbyte(0x66); /*PMULLW XMM4, XMM15(colbfog)*/ addbyte(0x41); addbyte(0x0f); addbyte(0xd5); - addbyte(0xe3); + addbyte(0xe7); addbyte(0xf3); /*MOVQ XMM5, XMM4*/ addbyte(0x0f); addbyte(0x7e); addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ addbyte(0x41); addbyte(0x0f); addbyte(0xfd); @@ -2610,6 +2616,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0x71); addbyte(0xd4); addbyte(8); + break; } switch (src_afunc) { @@ -2762,7 +2769,36 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0xef); addbyte(0xc0); break; - case AFUNC_ACOLORBEFOREFOG: + case AFUNC_ASATURATE: + addbyte(0x66); /*PMULLW XMM0, XMM11(minus_254)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x42); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); break; } diff --git a/src/include/86box/vid_voodoo_render.h b/src/include/86box/vid_voodoo_render.h index cd1962430..4070dfc1a 100644 --- a/src/include/86box/vid_voodoo_render.h +++ b/src/include/86box/vid_voodoo_render.h @@ -210,11 +210,10 @@ void voodoo_codegen_close(voodoo_t *voodoo); newdest_g = (dest_g * (255 - dest_a)) / 255; \ newdest_b = (dest_b * (255 - dest_a)) / 255; \ break; \ - case AFUNC_ASATURATE: \ - _a = MIN(src_a, 1 - dest_a); \ - newdest_r = (dest_r * _a) / 255; \ - newdest_g = (dest_g * _a) / 255; \ - newdest_b = (dest_b * _a) / 255; \ + case AFUNC_ACOLORBEFOREFOG: \ + newdest_r = (dest_r * colbfog_r) / 255; \ + newdest_g = (dest_g * colbfog_g) / 255; \ + newdest_b = (dest_b * colbfog_b) / 255; \ break; \ } \ \ @@ -254,8 +253,11 @@ void voodoo_codegen_close(voodoo_t *voodoo); src_g = (src_g * (255 - dest_a)) / 255; \ src_b = (src_b * (255 - dest_a)) / 255; \ break; \ - case AFUNC_ACOLORBEFOREFOG: \ - fatal("AFUNC_ACOLORBEFOREFOG\n"); \ + case AFUNC_ASATURATE: \ + _a = MIN(src_a, 1 - dest_a); \ + src_r = (dest_r * _a) / 255; \ + src_g = (dest_g * _a) / 255; \ + src_b = (dest_b * _a) / 255; \ break; \ } \ \ diff --git a/src/video/vid_voodoo_fb.c b/src/video/vid_voodoo_fb.c index 5ae26b4c5..ddf68360f 100644 --- a/src/video/vid_voodoo_fb.c +++ b/src/video/vid_voodoo_fb.c @@ -252,6 +252,9 @@ voodoo_fb_writew(uint32_t addr, uint16_t val, void *priv) { rgba8_t write_data = colour_data; uint16_t new_depth = depth_data; + int colbfog_r = 0; + int colbfog_g = 0; + int colbfog_b = 0; if (params->fbzMode & FBZ_DEPTH_ENABLE) { uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); @@ -262,6 +265,10 @@ voodoo_fb_writew(uint32_t addr, uint16_t val, void *priv) if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b) goto skip_pixel; + colbfog_r = write_data.r; + colbfog_g = write_data.g; + colbfog_b = write_data.b; + if (params->fogMode & FOG_ENABLE) { int32_t z = new_depth << 12; int64_t w_depth = (int64_t) (int32_t) new_depth; @@ -438,6 +445,9 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) for (int c = 0; c < count; c++) { rgba8_t write_data = colour_data[c]; uint16_t new_depth = depth_data[c]; + int colbfog_r = 0; + int colbfog_g = 0; + int colbfog_b = 0; if (params->fbzMode & FBZ_DEPTH_ENABLE) { uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); @@ -448,6 +458,10 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b) goto skip_pixel; + colbfog_r = write_data.r; + colbfog_g = write_data.g; + colbfog_b = write_data.b; + if (params->fogMode & FOG_ENABLE) { int32_t z = new_depth << 12; int64_t w_depth = new_depth; diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index 0f31fbc9f..870f428c7 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -967,6 +967,10 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t * int src_g = 0; int src_b = 0; int src_a = 0; + int colbfog_r = 0; + int colbfog_g = 0; + int colbfog_b = 0; + int colbfog_a = 0; int msel_r; int msel_g; int msel_b; @@ -1263,6 +1267,10 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t * if (cca_invert_output) src_a ^= 0xff; + colbfog_r = src_r; + colbfog_g = src_g; + colbfog_b = src_b; + if (params->fogMode & FOG_ENABLE) APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w); From 573f4c89cb07bcbd580f629c41dcb943de4bba57 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Jan 2025 11:33:19 +0100 Subject: [PATCH 17/18] Fix saturate alpha blending modes on interpreter. --- src/include/86box/vid_voodoo_render.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/86box/vid_voodoo_render.h b/src/include/86box/vid_voodoo_render.h index 4070dfc1a..e88d21dd5 100644 --- a/src/include/86box/vid_voodoo_render.h +++ b/src/include/86box/vid_voodoo_render.h @@ -254,7 +254,7 @@ void voodoo_codegen_close(voodoo_t *voodoo); src_b = (src_b * (255 - dest_a)) / 255; \ break; \ case AFUNC_ASATURATE: \ - _a = MIN(src_a, 1 - dest_a); \ + _a = MIN(src_a, 255 - dest_a); \ src_r = (dest_r * _a) / 255; \ src_g = (dest_g * _a) / 255; \ src_b = (dest_b * _a) / 255; \ From 80735cc70a8c25a559c2d81da0156fc086d3d302 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Jan 2025 11:38:46 +0100 Subject: [PATCH 18/18] Fixed a warning in src/video/vid_voodoo_render.c. --- src/video/vid_voodoo_render.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index 870f428c7..d8f812f7f 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -970,7 +970,6 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t * int colbfog_r = 0; int colbfog_g = 0; int colbfog_b = 0; - int colbfog_a = 0; int msel_r; int msel_g; int msel_b;