From 304a47c1bb1744809e2047e9a36508aef9f8c546 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Wed, 7 May 2025 22:49:05 +0200 Subject: [PATCH 01/29] Add files via upload --- src/video/vid_et4000w32.c | 160 +++++++++++++++++++++++++++++++------- 1 file changed, 133 insertions(+), 27 deletions(-) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 246decb9c..c772ffdd9 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -43,8 +43,11 @@ #define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" #define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" #define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.bin" +#define BIOS_ROM_PATH_W32P_IMASCAN_VLB "roms/video/et4000w32/tseng_et4000w32p-8.03.bin" +#define BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB "roms/video/et4000w32/m27c256b-at-dip28-miro20td-675dada18e7fa701369657.bin" #define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" #define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" +#define BIOS_ROM_PATH_W32P_REVCD_ONBOARD "roms/video/et4000w32/vid.BIN" #define ACL_WRST 1 #define ACL_RDST 2 @@ -55,7 +58,10 @@ enum { ET4000W32, ET4000W32I, ET4000W32P_REVC, + ET4000W32P_REVCD_ONBOARD, ET4000W32P_VIDEOMAGIC_REVB, + ET4000W32P_IMASCAN_VLB, + ET4000W32P_MIROVIDEO20TD_VLB, ET4000W32P, ET4000W32P_CARDEX, ET4000W32P_DIAMOND @@ -178,7 +184,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); else stg_ramdac_out(addr, val, svga->ramdac, svga); @@ -302,13 +308,13 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) if (svga->hwcursor.cur_xsize == 128) { svga->hwcursor.xoff &= 0x7f; svga->hwcursor.yoff &= 0x7f; - if (et4000->type > ET4000W32P_REVC) { + if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if (svga->bpp == 24) { et4000->adjust_cursor = 2; } } } else { - if (et4000->type > ET4000W32P_REVC) { + if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if ((svga->bpp == 24) && et4000->adjust_cursor) { et4000->adjust_cursor = 0; } @@ -348,7 +354,7 @@ et4000w32p_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) return sdac_ramdac_in(addr, 0, svga->ramdac, svga); else return stg_ramdac_in(addr, svga->ramdac, svga); @@ -503,8 +509,8 @@ et4000w32p_recalctimings(svga_t *svga) svga->hdisp >>= 1; svga->dots_per_clock >>= 1; } - if (et4000->type <= ET4000W32P_REVC) { - if (et4000->type == ET4000W32P_REVC) { + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type == ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if (svga->hdisp != 1024) et4000->adjust_cursor = 1; } else @@ -514,7 +520,7 @@ et4000w32p_recalctimings(svga_t *svga) case 24: svga->hdisp /= 3; svga->dots_per_clock /= 3; - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { svga->hdisp = 640; @@ -548,7 +554,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 0x40: case 0x60: /* 256+ colours */ - if (et4000->type <= ET4000W32P_REVC) + if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) svga->clock /= 2; switch (svga->bpp) { @@ -729,13 +735,13 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | (val << 8); break; case 0x8e: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->acl.queued.pixel_depth = val & 0x30; else et4000->acl.queued.vbus = val & 0x03; break; case 0x8f: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->acl.queued.xy_dir = val & 0xb7; else et4000->acl.queued.xy_dir = val & 0x03; @@ -759,7 +765,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | (val << 8); break; case 0x9c: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) et4000->acl.queued.ctrl_routing = val & 0xdb; else et4000->acl.queued.ctrl_routing = val & 0xb7; @@ -785,7 +791,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) case 0xa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24); et4000->acl.internal = et4000->acl.queued; - if (et4000->type >= ET4000W32P_REVC) { + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { et4000w32p_blit_start(et4000); et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); if (!(et4000->acl.queued.ctrl_routing & 0x43)) { @@ -849,7 +855,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) static void et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank) { - if (et4000->type >= ET4000W32P_REVC) { + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { if (!(et4000->acl.status & ACL_XYST)) { et4000w32_log("XY MMU block not started\n"); return; @@ -1087,7 +1093,7 @@ et4000w32p_mmu_read(uint32_t addr, void *priv) case 0x8d: return et4000->acl.internal.dest_off >> 8; case 0x8e: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) return et4000->acl.internal.pixel_depth; return et4000->acl.internal.vbus; case 0x8f: @@ -2779,6 +2785,30 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + break; + + case ET4000W32P_IMASCAN_VLB: + /* ET4000/W32p Imascan RGB */ + et4000->rev = 5; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_IMASCAN_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + break; + + case ET4000W32P_MIROVIDEO20TD_VLB: + /* ET4000/W32p miroVIDEO 20TD LIVE! */ + et4000->rev = 5; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; @@ -2791,6 +2821,18 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + break; + + case ET4000W32P_REVCD_ONBOARD: + /* ET4000/W32p rev C */ + et4000->rev = 7; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVCD_ONBOARD, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = sdac_getclock; @@ -2890,12 +2932,30 @@ et4000w32p_videomagic_revb_vlb_available(void) return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB); } +int +et4000w32p_imascan_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_IMASCAN_VLB); +} + +int +et4000w32p_mirovideo20td_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB); +} + int et4000w32p_revc_available(void) { return rom_present(BIOS_ROM_PATH_W32P_REVC); } +int +et4000w32p_revcd_onboard_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_REVCD_ONBOARD); +} + int et4000w32p_noncardex_available(void) { @@ -2943,19 +3003,23 @@ et4000w32p_force_redraw(void *priv) static const device_config_t et4000w32p_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_string = NULL, - .default_int = 2, - .file_filter = NULL, - .spinner = { 0 }, - .selection = { - { .description = "1 MB", .value = 1 }, - { .description = "2 MB", .value = 2 }, - { .description = "" } - }, - .bios = { { 0 } } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2, + .selection = { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } + } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -3017,6 +3081,34 @@ const device_t et4000w32i_vlb_device = { .config = et4000w32p_config }; +const device_t et4000w32p_imascan_vlb_device = { + .name = "Tseng Labs ET4000/w32p VLB (Imascan)", + .internal_name = "et4000w32p_imascan_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_IMASCAN_VLB, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + .available = et4000w32p_imascan_vlb_available, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + +const device_t et4000w32p_mirovideo20td_vlb_device = { + .name = "Tseng Labs ET4000/w32p VLB (miroVIDEO 20TD LIVE!)", + .internal_name = "et4000w32p_mirovideo20td_vlb", + .flags = DEVICE_VLB, + .local = ET4000W32P_MIROVIDEO20TD_VLB, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + .available = et4000w32p_mirovideo20td_vlb_available, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + const device_t et4000w32p_videomagic_revb_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)", .internal_name = "et4000w32p_videomagic_revb_vlb", @@ -3073,6 +3165,20 @@ const device_t et4000w32p_revc_pci_device = { .config = et4000w32p_config }; +const device_t et4000w32p_revcd_onboard_pci_device = { + .name = "Tseng Labs ET4000/w32p Rev. C/D PCI (On-Board)", + .internal_name = "et4000w32p_revc_pci", + .flags = DEVICE_PCI, + .local = ET4000W32P_REVCD_ONBOARD, + .init = et4000w32p_init, + .close = et4000w32p_close, + .reset = NULL, + .available = et4000w32p_revcd_onboard_available, + .speed_changed = et4000w32p_speed_changed, + .force_redraw = et4000w32p_force_redraw, + .config = et4000w32p_config +}; + const device_t et4000w32p_noncardex_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. D VLB", .internal_name = "et4000w32p_nc_vlb", From f7079384f85ffc7649622fb61c67d309013ab0cd Mon Sep 17 00:00:00 2001 From: WinTP <1789016472@qq.com> Date: Tue, 13 May 2025 13:56:10 +0800 Subject: [PATCH 02/29] Update Simplified Chinese translation --- src/qt/languages/zh-CN.po | 72 +++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index d2ed7ce71..2af5abef9 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -849,8 +849,8 @@ msgstr "一个旧式计算机模拟器\n\n作者: Miran Grča (OBattler)、Richa msgid "Hardware not available" msgstr "硬件不可用" -msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection." -msgstr "请确认 %1 已安装且使用兼容 libpcap 的网络连接。" +msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." +msgstr "请确认 %1 已安装且使用兼容 %1 的网络连接。" msgid "Invalid configuration" msgstr "无效配置" @@ -1240,7 +1240,7 @@ msgid "Host CD/DVD Drive (%1:)" msgstr "主机 CD/DVD 驱动器 (%1:)" msgid "&Connected" -msgstr "" +msgstr "已连接(&C)" msgid "Clear image history" msgstr "清除映像历史记录" @@ -1300,7 +1300,7 @@ msgid "\nFalling back to software rendering." msgstr "\n回到软件渲染。" msgid "

When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.

" -msgstr "

选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

选择媒体图像(光盘、软盘等)时,打开对话框将从与 86Box 配置文件相同的目录开始。这一设置可能只会在 macOS 上产生影响。

" msgid "This machine might have been moved or copied." msgstr "这台机器可能被移动或复制过。" @@ -1315,7 +1315,7 @@ msgid "I Copied It" msgstr "我已复制这台机器" msgid "86Box Monitor #" -msgstr "86Box 监测器 " +msgstr "86Box 监测器 #" msgid "No MCA devices." msgstr "无 MCA 设备。" @@ -1804,7 +1804,7 @@ msgid "Five + Wheel" msgstr "五键+滚轮" msgid "Five + 2 Wheels" -msgstr "" +msgstr "五键+双滚轮" msgid "A3 - SMT2 Serial / SMT3(R)V" msgstr "A3 - SMT2 串行 / SMT3(R)V" @@ -2050,25 +2050,25 @@ msgid "[Generic] RAM Disk (max. speed)" msgstr "[Generic] RAM 磁盘 (最大速度)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Generic] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Generic] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Generic] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Generic] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Generic] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A 克隆 (ISA)" @@ -2076,6 +2076,12 @@ msgstr "IBM 8514/A 克隆 (ISA)" msgid "Vendor" msgstr "制造商" +msgid "30 Hz (JMP2 = 1)" +msgstr "30 Hz (JMP2 = 1)" + +msgid "60 Hz (JMP2 = 2)" +msgstr "60 Hz (JMP2 = 2)" + msgid "Generic PC/XT Memory Expansion" msgstr "通用 PC/XT 内存扩展" @@ -2089,61 +2095,61 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。" msgid "Inhibit multimedia keys" -msgstr "" +msgstr "禁止多媒体按键" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "保存设置前要求用户确认" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "硬重置前要求用户确认" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "退出前要求用户确认" msgid "Options" -msgstr "" +msgstr "选项" msgid "Model" -msgstr "" +msgstr "模型" msgid "Model:" -msgstr "" +msgstr "模型:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Vulkan 渲染器初始化失败。" msgid "GLSL Error" -msgstr "" +msgstr "GLSL 错误" msgid "Could not load shader: %1" -msgstr "" +msgstr "无法加载着色器:%1" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL 版本需要达到 3.0 或更高。当前 GLSL 版本为 %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "无法加载材质:%1" msgid "Could not compile shader:\n\n%1" -msgstr "" +msgstr "无法编译着色器:\n\n%1" msgid "Program not linked:\n\n%1" -msgstr "" +msgstr "程序未链接:\n\n%1" msgid "Shader Manager" -msgstr "" +msgstr "着色器管理器" msgid "Shader Configuration" -msgstr "" +msgstr "着色器配置" msgid "Add" -msgstr "" +msgstr "添加" msgid "Move up" -msgstr "" +msgstr "上移" msgid "Move down" -msgstr "" +msgstr "下移" msgid "Could not load file %1" -msgstr "" +msgstr "无法加载文件 %1" From 0157520b767042e022c98f8977f90fb2d3323759 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 13 May 2025 17:05:13 +0200 Subject: [PATCH 03/29] PS/2 mouse: fix the "no poll" condition. --- src/device/mouse_ps2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 0d34235fe..2c1722f51 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -333,13 +333,13 @@ ps2_poll(void *priv) atkbc_dev_t *dev = (atkbc_dev_t *) priv; int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3; - int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || !mouse_state_changed()) || - ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size))); + int cond = (mouse_capture || video_fullscreen) && mouse_scan && (dev->mode == MODE_STREAM) && + mouse_state_changed() && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size)); - if (!cond && (dev->mode == MODE_STREAM)) + if (cond) ps2_report_coordinates(dev, 1); - return cond; + return !cond; } /* From e8c8d3373e3bd8ef013907ad8e31c90db83557dd Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 14 May 2025 10:15:14 +0200 Subject: [PATCH 04/29] AT KBC: some fixes. --- src/device/kbc_at.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index aaa746570..2b9cf8c18 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -2149,6 +2149,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->wantdata = 0; dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } break; @@ -2160,11 +2166,36 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) dev->wantdata = 1; dev->state = STATE_KBC_PARAM; dev->command = 0xd1; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } else if (fast_reset && ((val & 0xf0) == 0xf0)) { pulse_output(dev, val & 0x0f); dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; + return; + } else if (val == 0xad) { + /* Fast track it because of the Bochs BIOS. */ + kbc_at_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + + dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } else if (val == 0xae) { /* Fast track it because of the LG MultiNet. */ @@ -2172,6 +2203,12 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv) set_enable_kbd(dev, 1); dev->state = STATE_MAIN_IBF; + + /* + Explicitly clear IBF so that any preceding + command is not executed. + */ + dev->status &= ~STAT_IFULL; return; } break; From cb6712805973a8a85b1a211fe9aa9d2327fbb9c7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 14 May 2025 19:08:35 +0200 Subject: [PATCH 05/29] AT / PS/2 keyboard: abort any pending scan code send and reinitialize queue on set defaults (command F5/F6). --- src/device/kbc_at.c | 1 + src/device/kbc_at_dev.c | 2 +- src/include/86box/keyboard.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 2b9cf8c18..ce80209a7 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -220,6 +220,7 @@ kbc_at_set_fast_reset(const uint8_t new_fast_reset) fast_reset = new_fast_reset; } +#define ENABLE_KBC_AT_LOG 1 #ifdef ENABLE_KBC_AT_LOG int kbc_at_do_log = ENABLE_KBC_AT_LOG; diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index c1041e6e1..cd55f91fa 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -58,7 +58,7 @@ kbc_at_dev_log(const char *fmt, ...) # define kbc_at_dev_log(fmt, ...) #endif -static void +void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main) { if (reset_main) { diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index dd8cae54b..9dfb1c8e4 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -291,6 +291,7 @@ extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t v extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); extern void kbc_at_handler(int set, void *priv); +extern void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main); extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main); extern void kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main); extern void kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa); From f09ebba33031f94d04c036e149482e26443697f6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 14 May 2025 19:18:49 +0200 Subject: [PATCH 06/29] Fix the previous commit. --- src/device/kbc_at.c | 1 - src/device/keyboard_at.c | 181 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index ce80209a7..2b9cf8c18 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -220,7 +220,6 @@ kbc_at_set_fast_reset(const uint8_t new_fast_reset) fast_reset = new_fast_reset; } -#define ENABLE_KBC_AT_LOG 1 #ifdef ENABLE_KBC_AT_LOG int kbc_at_do_log = ENABLE_KBC_AT_LOG; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 4b1097df4..ee5036f74 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -428,11 +428,11 @@ static const scancode scancode_set1[512] = { { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */ { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */ { .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */ - { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */ + { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xda, 0 } }, /* 15a */ { .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */ { .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */ { .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */ - { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */ + { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xde, 0 } }, /* 15e */ { .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */ { .mk = { 0 }, .brk = { 0 } }, /* 160 */ { .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */ @@ -3643,6 +3643,13 @@ keyboard_at_write(void *priv) case 0xf6: /* set defaults */ keyboard_at_log("%s: set defaults%s\n", dev->name, (val == 0xf6) ? "" : " and disable keyboard"); + dev->port->out_new = -1; + dev->port->wantcmd = 0; + + kbc_at_dev_queue_reset(dev, 1); + + dev->last_scan_code = 0x00; + keyboard_scan = !(val & 0x01); keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n", dev->name, val, keyboard_scan); @@ -3728,6 +3735,44 @@ keyboard_at_write(void *priv) } } +#ifdef SCAN_CODE_TABLES_COMPARISON +/* Non-translated to translated scan codes. */ +static const uint8_t nont_to_t[256] = { + 0x00, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, + 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, + 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, + 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, + 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, + 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, + 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, + 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, + 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, + 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, + 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, + 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; +#endif + /* * Initialize the device for use by the user. * @@ -3777,6 +3822,138 @@ keyboard_at_init(const device_t *info) inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa; +#ifdef SCAN_CODE_TABLES_COMPARISON + pclog_toggle_suppr(); + + pclog("Scan code set 01 vs. 81 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set1[i].mk[j] == scancode_set81[i].mk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].mk[j], scancode_set81[i].mk[j]); + j++; + } while ((scancode_set1[i].mk[j] != 0) && (scancode_set81[i].mk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 81 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set1[i].brk[j] == scancode_set81[i].brk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].brk[j], scancode_set81[i].brk[j]); + j++; + } while ((scancode_set1[i].brk[j] != 0) && (scancode_set81[i].brk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 02 vs. 82 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set2[i].mk[j] == scancode_set82[i].mk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set2[i].mk[j], scancode_set82[i].mk[j]); + j++; + } while ((scancode_set2[i].mk[j] != 0) && (scancode_set82[i].mk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 02 vs. 82 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + do { + if (scancode_set2[i].brk[j] == scancode_set82[i].brk[j]) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set2[i].brk[j], scancode_set82[i].brk[j]); + j++; + } while ((scancode_set2[i].brk[j] != 0) && (scancode_set82[i].brk[j] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 02 (make):\n===============================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + int k = 0; + int was_f0 = 0; + do { + if (scancode_set2[i].mk[k] == 0xf0) + was_f0 = 1; + else { + uint8_t code = nont_to_t[scancode_set2[i].mk[k]]; + + if (was_f0) { + if (code & 0x80) + code = 0x00; + else + code |= 0x80; + + was_f0 = 0; + } + + if (scancode_set1[i].mk[j] == code) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].mk[j], code); + + j++; + } + + k++; + } while ((scancode_set1[i].mk[j] != 0) && (scancode_set2[i].mk[k] != 0)); + pclog("\n"); + } + + pclog("\nScan code set 01 vs. 02 (break):\n================================\n"); + for (int i = 0; i < 512; i++) { + pclog("Scan code %03X:", i); + int j = 0; + int k = 0; + int was_f0 = 0; + do { + if (scancode_set2[i].brk[k] == 0xf0) + was_f0 = 1; + else { + uint8_t code = nont_to_t[scancode_set2[i].brk[k]]; + + if (was_f0) { + if (code & 0x80) + code = 0x00; + else + code |= 0x80; + + was_f0 = 0; + } + + if (scancode_set1[i].brk[j] == code) + pclog(" --"); + else + pclog(" (%02X != %02X)", scancode_set1[i].brk[j], code); + + j++; + } + + k++; + } while ((scancode_set1[i].brk[j] != 0) && (scancode_set2[i].brk[k] != 0)); + pclog("\n"); + } + + pclog_toggle_suppr(); + + fatal("Comparison finished\n"); +#endif + /* Return our private data to the I/O layer. */ return dev; } From 4fb38db2f8694c3856fb77f1600400d8acdd7f26 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 14 May 2025 20:12:17 +0200 Subject: [PATCH 07/29] Update machine.h Add the Phoenix BIOS variant for the Micronics 09-00021 (part 1) --- src/include/86box/machine.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c28add516..8abd8fef1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -519,6 +519,7 @@ extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); extern int machine_at_spc6000a_init(const machine_t *); extern int machine_at_micronics386_init(const machine_t *); +extern int machine_at_micronics386px_init(const machine_t *); extern int machine_at_ecs386v_init(const machine_t *); extern int machine_at_tandy4000_init(const machine_t *); From bf07f6452e4781ba1cd8ee2c2ca1db8169ed1e53 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 14 May 2025 20:15:21 +0200 Subject: [PATCH 08/29] Add the Phoenix BIOS variant for the Micronics 09-00021 (part 2) --- src/machine/m_at_286_386sx.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b084bfbbd..c9fb124cb 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -281,6 +281,26 @@ machine_at_micronics386_init(const machine_t *model) return ret; } +int +machine_at_micronics386px_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-LO.BIN", + "roms/machines/micronics386/386-Micronics-09-00021-HI.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_init(model); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_scat_init(const machine_t *model, int is_v4, int is_ami) { From b334bd09aff796983da71dec7c8f4057e85795b9 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 14 May 2025 20:18:24 +0200 Subject: [PATCH 09/29] Add the Phoenix BIOS variant for the Micronics 09-00021 (part 3) --- src/machine/machine_table.c | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 34e69ed24..5acee0350 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5435,7 +5435,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[ISA] Micronics 09-00021", + .name = "[ISA] Micronics 09-00021 (Tandon BIOS)", .internal_name = "micronics386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_DISCRETE, @@ -5474,6 +5474,46 @@ const machine_t machines[] = { .net_device = NULL }, /* Has IBM AT KBC firmware. */ + { + .name = "[ISA] Micronics 09-00021 (Phoenix BIOS)", + .internal_name = "micronics386px", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_micronics386px_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, + .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_APM, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has IBM AT KBC firmware. */ { .name = "[ISA] Tandy 4000", .internal_name = "tandy4000", From c804a2892a9f1b48f4fc80503d75c77e7410de79 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 15 May 2025 00:27:46 +0200 Subject: [PATCH 10/29] Some more Compaq AT changes of the night (May 15th, 2025) 1. Properly return the flat panel display bit in port 0x1bc6, fixes adapt.com and the corresponding Portable identification in the disk cmos. 2. Preliminary MDA mapping on the Plasma display, per bit 3 toggling of port 0x23c6. 3. Implemented port 0x17c6. 4. Cleanups. --- src/machine/m_at_compaq.c | 552 +++++++++++++++++++++----------------- 1 file changed, 304 insertions(+), 248 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 904122bad..c0b254388 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -61,11 +61,6 @@ enum { /*Very rough estimate*/ #define VID_CLOCK (double) (651 * 416 * 60) -static uint8_t cga_crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - /* Mapping of attributes to colours */ static uint32_t amber; static uint32_t black; @@ -97,7 +92,10 @@ compaq_plasma_display_get(void) typedef struct compaq_plasma_t { cga_t cga; + uint8_t ctl_mode; + uint8_t port_13c6; uint8_t port_23c6; + uint8_t port_27c6; uint8_t internal_monitor; uint8_t attrmap; } compaq_plasma_t; @@ -116,16 +114,18 @@ compaq_plasma_recalctimings(compaq_plasma_t *self) double _dispofftime; double disptime; - if (!self->internal_monitor && !(self->port_23c6 & 1)) { + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { cga_recalctimings(&self->cga); return; } disptime = 651; _dispontime = 640; - _dispofftime = disptime - _dispontime; - self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); - self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST / 2; + _dispofftime *= CGACONST / 2; + self->cga.dispontime = (uint64_t) (_dispontime); + self->cga.dispofftime = (uint64_t) (_dispofftime); } static void @@ -144,9 +144,9 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; self->cga.vram[addr & 0x7fff] = val; + compaq_plasma_waitstates(&self->cga); } - static uint8_t compaq_plasma_read(uint32_t addr, void *priv) { @@ -163,49 +163,59 @@ static void compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t old; + + if (self->port_23c6 & 0x08) { + if ((addr >= 0x3d0) && (addr <= 0x3dc)) + addr ^= 0x60; + } switch (addr) { /* Emulated CRTC, register select */ + case 0x3d0: + case 0x3d2: case 0x3d4: + case 0x3d6: cga_out(addr, val, &self->cga); break; /* Emulated CRTC, value */ + case 0x3d1: + case 0x3d3: case 0x3d5: - old = self->cga.crtc[self->cga.crtcreg]; - self->cga.crtc[self->cga.crtcreg] = val & cga_crtcmask[self->cga.crtcreg]; - + case 0x3d7: /* Register 0x12 controls the attribute mappings for the * plasma screen. */ if (self->cga.crtcreg == 0x12) { self->attrmap = val; compaq_plasma_recalcattrs(self); - break; + return; } + cga_out(addr, val, &self->cga); - if (old != val) { - if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) { - self->cga.fullchange = changeframecount; - compaq_plasma_recalctimings(self); - } - } + compaq_plasma_recalctimings(self); break; case 0x3d8: case 0x3d9: + case 0x3db: + case 0x3dc: cga_out(addr, val, &self->cga); break; case 0x13c6: - compaq_plasma_display_set((val & 8) ? 1 : 0); + self->port_13c6 = val; + compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); break; case 0x23c6: self->port_23c6 = val; - if (val & 8) /* Disable internal CGA */ - mem_mapping_disable(&self->cga.mapping); + if (val & 0x08) /* Disable internal CGA */ + mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x8000); else - mem_mapping_enable(&self->cga.mapping); + mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x8000); + break; + + case 0x27c6: + self->port_27c6 = val; break; default: @@ -219,40 +229,53 @@ compaq_plasma_in(uint16_t addr, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; uint8_t ret = 0xff; + if (self->port_23c6 & 0x08) { + if ((addr >= 0x3d0) && (addr <= 0x3dc)) + addr ^= 0x60; + } + switch (addr) { case 0x3d4: case 0x3da: + case 0x3db: + case 0x3dc: ret = cga_in(addr, &self->cga); break; + case 0x3d1: + case 0x3d3: case 0x3d5: + case 0x3d7: if (self->cga.crtcreg == 0x12) { ret = self->attrmap & 0x0f; - if (self->internal_monitor) + if (compaq_plasma_display_get()) ret |= 0x30; /* Plasma / CRT */ } else ret = cga_in(addr, &self->cga); + break; + + case 0x3d8: + ret = self->cga.cgamode; break; case 0x13c6: - ret = compaq_plasma_display_get() ? 8 : 0; - ret |= 4; + ret = self->port_13c6; + break; + + case 0x17c6: + ret = 0xf6; break; case 0x1bc6: - ret = 0; - if (compaq_plasma_display_get()) { - if ((self->cga.cgamode & 0x12) == 0x12) { - if (self->port_23c6 & 8) - ret |= 0x40; - else - ret |= 0x20; - } - } + ret = 0x40; break; case 0x23c6: - ret = 0; + ret = self->port_23c6; + break; + + case 0x27c6: + ret = self->port_27c6 & 0x3f; break; default: @@ -276,6 +299,8 @@ compaq_plasma_poll(void *priv) int cursorline; int blink = 0; int underline = 0; + int c; + int x; uint32_t ink = 0; uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; uint32_t bg = black; @@ -292,230 +317,252 @@ compaq_plasma_poll(void *priv) } /* graphic mode and not mode 40h */ - if (!self->internal_monitor && !(self->port_23c6 & 1)) { + if (!self->internal_monitor && !(self->port_23c6 & 0x01)) { + /* standard cga mode */ cga_poll(&self->cga); return; - } + } else { + /* mode 40h or text mode */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); + self->cga.cgastat |= 1; + self->cga.linepos = 1; + if (self->cga.cgadispon) { + if (self->cga.displine == 0) + video_wait_for_buffer(); - /* mode 40h or text mode */ - if (!self->cga.linepos) { - timer_advance_u64(&self->cga.timer, self->cga.dispofftime); - self->cga.cgastat |= 1; - self->cga.linepos = 1; - if (self->cga.cgadispon) { - if (self->cga.displine == 0) { - video_wait_for_buffer(); - } - if (self->cga.cgamode & 2) { - if (self->cga.cgamode & 0x10) { - /* 640x400 mode */ - if (self->port_23c6 & 1) /* 640*400 */ { - addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - } - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7FFF]; - addr++; + /* 80-col */ + if (self->cga.cgamode & 0x01) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1; + ma += (self->cga.displine >> 4) * 80; - for (uint8_t c = 0; c < 8; c++) { - ink = (dat & 0x80) ? fg : bg; - if (!(self->cga.cgamode & 8)) - ink = black; - (buffer32->line[self->cga.displine])[x * 8 + c] = ink; - dat <<= 1; + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + + /* for each text column */ + for (x = 0; x < 80; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else + chr = attr = 0; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + blink = ((attr & 0x80) << 3) + 7 + 16; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ma++; + } + } + /* 40-col */ + else if (!(self->cga.cgamode & 0x02)) { + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1; + ma += (self->cga.displine >> 4) * 40; + + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc); + + for (x = 0; x < 40; x++) { + /* video output enabled */ + if (self->cga.cgamode & 0x08) { + /* character */ + chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; + /* text attributes */ + attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; + } else + chr = attr = 0; + + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); + /* check if character underline mode should be set */ + underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + if (underline) { + /* set forecolor to white */ + attr = attr | 0x7; + } + blink = 0; + /* set foreground */ + cols[1] = blinkcols[attr][1]; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + blink = ((attr & 0x80) << 3) + 7 + 16; + } + + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (self->cga.sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ma++; } } else { - addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); - for (uint8_t x = 0; x < 80; x++) { - dat = self->cga.vram[addr & 0x7fff]; - addr++; + if (self->cga.cgamode & 0x10) { + /* 640x400 mode */ + if (self->port_23c6 & 0x01) /* 640*400 */ { + addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - for (uint8_t c = 0; c < 4; c++) { - pattern = (dat & 0xC0) >> 6; - if (!(self->cga.cgamode & 8)) - pattern = 0; - - switch (pattern & 3) { - case 0: - ink0 = ink1 = black; - break; - case 1: - if (self->cga.displine & 1) { - ink0 = black; - ink1 = black; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 2: - if (self->cga.displine & 1) { - ink0 = black; - ink1 = amber; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 3: - ink0 = ink1 = amber; - break; - - default: - break; + for (uint8_t c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(self->cga.cgamode & 0x08)) + ink = black; + buffer32->line[self->cga.displine][(x << 3) + c] = ink; + dat <<= 1; } - buffer32->line[self->cga.displine][x * 8 + 2 * c] = ink0; - buffer32->line[self->cga.displine][x * 8 + 2 * c + 1] = ink1; - dat <<= 2; - } - } - } - } else if (self->cga.cgamode & 1) { - /* 80-col */ - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) * 2; - ma += (self->cga.displine >> 4) * 80; - - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); - - /* for each text column */ - for (uint8_t x = 0; x < 80; x++) { - /* video output enabled */ - chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; - attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); - /* blink active */ - if (self->cga.cgamode & 0x20) { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if (blink) { - /* set blinking */ - cols[1] = cols[0]; } } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + for (uint8_t x = 0; x < 80; x++) { + dat = self->cga.vram[addr & 0x7fff]; + addr++; - ++ma; - } - } else { /* 40-col */ - sc = self->cga.displine & 0x0f; - addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) * 2; - ma += (self->cga.displine >> 4) * 40; + for (uint8_t c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(self->cga.cgamode & 0x08)) + pattern = 0; - if ((self->cga.crtc[0x0a] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; + break; + case 1: + case 2: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = amber; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 3: + ink0 = ink1 = amber; + break; - for (uint8_t x = 0; x < 40; x++) { - chr = self->cga.vram[(addr + 2 * x) & 0x7FFF]; - attr = self->cga.vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); - /* blink active */ - if (self->cga.cgamode & 0x20) { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - /* attribute 7 active and not cursor */ - if (blink) { - /* set blinking */ - cols[1] = cols[0]; + default: + break; + } + buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0; + buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1; + dat <<= 2; + } } - } else { - /* Set intensity bit */ - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; } - /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (sc == 7)) { - /* for each pixel in character width */ - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c * 2)] = buffer32->line[self->cga.displine][(x << 4) + (c * 2) + 1] = mdaattr[attr][blink][1]; - } else if (drawcursor) { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (uint8_t c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm2[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; } } - } - self->cga.displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (self->cga.displine == 400) { /* Start of VSYNC */ - self->cga.cgastat |= 8; - self->cga.cgadispon = 0; - } - if (self->cga.displine == 416) { /* End of VSYNC */ - self->cga.displine = 0; - self->cga.cgastat &= ~8; - self->cga.cgadispon = 1; - } - } else { - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; + self->cga.displine++; + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (self->cga.displine == 400) { /* Start of VSYNC */ + self->cga.cgastat |= 8; + self->cga.cgadispon = 0; + } + if (self->cga.displine == 416) { /* End of VSYNC */ + self->cga.displine = 0; + self->cga.cgastat &= ~8; + self->cga.cgadispon = 1; + } + } else { + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + if (self->cga.cgadispon) + self->cga.cgastat &= ~1; - timer_advance_u64(&self->cga.timer, self->cga.dispontime); - self->cga.linepos = 0; + self->cga.linepos = 0; - if (self->cga.displine == 400) { - /* Hardcode 640x400 window size */ - if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) { + if (self->cga.displine == 400) { xsize = 640; ysize = 400; - if (xsize < 64) - xsize = 656; - if (ysize < 32) - ysize = 200; - set_screen_size(xsize, ysize); - if (video_force_resize_get()) - video_force_resize_set(0); + if ((self->cga.cgamode & 0x08) || video_force_resize_get()) { + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + /* ogc specific */ + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; + + /* Fixed 640x400 resolution */ + video_res_x = 640; + video_res_y = 400; + + if (self->cga.cgamode & 0x02) { + if (self->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + + self->cga.cgablink++; } - video_blit_memtoscreen(0, 0, xsize, ysize); - frames++; - - /* Fixed 640x400 resolution */ - video_res_x = 640; - video_res_y = 400; - - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) - video_bpp = 1; - else - video_bpp = 2; - } else - video_bpp = 0; - - self->cga.cgablink++; } } } @@ -560,7 +607,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) /* Set up colours */ amber = makecol(0xff, 0x7d, 0x00); - black = makecol(0x64, 0x0c, 0x00); + black = makecol(0x64, 0x19, 0x00); /* Initialize the attribute mapping. Start by defaulting everything * to black on amber, and with bold set by bit 3 */ @@ -631,12 +678,14 @@ compaq_plasma_init(UNUSED(const device_t *info)) { compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); if (compaq_machine_type == COMPAQ_PORTABLEIII) loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); else loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49); + cga_init(&self->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); + self->cga.composite = 0; self->cga.revision = 0; @@ -644,12 +693,16 @@ compaq_plasma_init(UNUSED(const device_t *info)) self->internal_monitor = 1; cga_comp_init(self->cga.revision); - timer_add(&self->cga.timer, compaq_plasma_poll, self, 1); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); - io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x13c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x1bc6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - io_sethandler(0x23c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + timer_set_callback(&self->cga.timer, compaq_plasma_poll); + timer_set_p(&self->cga.timer, self); + + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); + for (int i = 1; i <= 2; i++) { + io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + } + io_sethandler(0x03d0, 0x000c, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); /* Default attribute mapping is 4 */ self->attrmap = 4; @@ -793,7 +846,8 @@ machine_at_compaq_init(const machine_t *model, int type) switch (type) { case COMPAQ_PORTABLEII: - machine_at_init(model); + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; case COMPAQ_PORTABLEIII: @@ -801,7 +855,9 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); - machine_at_init(model); + + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; case COMPAQ_PORTABLEIII386: From 6aec346cc5e88f5012a9a764ba5c729373fcb174 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 May 2025 04:11:29 +0200 Subject: [PATCH 11/29] AT keyboard: Fix last scan code resending, fixes E0-prefixed keys on some machines. --- src/device/kbc_at_dev.c | 10 ++++++---- src/device/keyboard_at.c | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index cd55f91fa..b20e38860 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -95,10 +95,6 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main) dev->cmd_queue[dev->cmd_queue_end] = val; dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf; } - - /* TODO: This should be done on actual send to host. */ - if (val != 0xfe) - dev->last_scan_code = val; } static void @@ -123,6 +119,8 @@ kbc_at_dev_poll(void *priv) (dev->queue_start != dev->queue_end)) { kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]); dev->port->out_new = dev->queue[dev->queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask; } if (dev->ignore || !(*dev->scan) || dev->port->wantcmd) @@ -143,6 +141,8 @@ kbc_at_dev_poll(void *priv) if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; } if (dev->cmd_queue_start == dev->cmd_queue_end) @@ -166,6 +166,8 @@ kbc_at_dev_poll(void *priv) if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) { kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]); dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start]; + if (dev->port->out_new != 0xfe) + dev->last_scan_code = dev->port->out_new; dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf; } if (dev->cmd_queue_start == dev->cmd_queue_end) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index ee5036f74..7fa2b9706 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -3494,7 +3494,6 @@ keyboard_at_invalid_cmd(atkbc_dev_t *dev) kbc_at_dev_queue_add(dev, inv_cmd_response, 0); } - static void keyboard_at_write(void *priv) { @@ -3719,7 +3718,6 @@ keyboard_at_write(void *priv) /* TODO: This is supposed to resend multiple bytes after some commands. */ case 0xfe: /* resend last scan code */ keyboard_at_log("%s: resend last scan code\n", dev->name); - kbc_at_dev_queue_add(dev, 0xfa, 0); kbc_at_dev_queue_add(dev, dev->last_scan_code, 0); break; From 4331d78b829427024a4e46e338655c279929f92c Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 May 2025 04:26:14 +0200 Subject: [PATCH 12/29] Added the DTK PKM-0031Y. --- src/chipset/CMakeLists.txt | 1 + src/chipset/sl82c461.c | 362 +++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 3 + src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 21 ++ src/machine/machine_table.c | 40 ++++ 6 files changed, 428 insertions(+) create mode 100644 src/chipset/sl82c461.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 94ef408f6..7d17b9983 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -72,6 +72,7 @@ add_library(chipset OBJECT sis_5572_usb.c sis_5595_pmu.c sis_55xx.c + sl82c461.c via_vt82c49x.c via_vt82c505.c gc100.c diff --git a/src/chipset/sl82c461.c b/src/chipset/sl82c461.c new file mode 100644 index 000000000..f94aa2e99 --- /dev/null +++ b/src/chipset/sl82c461.c @@ -0,0 +1,362 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Symphony SL82C461 (Haydn II) chipset. + * + * Symphony SL82C461 Configuration Registers (WARNING: May be inaccurate!): + * + * - Register 00h: + * - Bit 6: External cache present (if clear, AMI BIOS'es will not + * allow enabling external cache). + * + * - Register 01h: + * - Bit 0: Fast Gate A20 Enable (Handler mostly). + * Is it? Enabling/disabling fast gate A20 doesn't appear + * to do much to any register at all. + * + * - Register 02h: + * - Bit 0: Optional Chipset Turbo Pin; + * - Bits 4-2: + * - 000 = CLK2/3; + * - 001 = CLK2/4; + * - 010 = CLK2/5; + * - 011 = 7.159 MHz (ATCLK2); + * - 100 = CLK2/6; + * - 110 = CLK2/2.5; + * - 111 = CLK2/2. + * + * - Register 06h: + * - Bit 2: Decoupled Refresh Option. + * + * - Register 08h: + * - Bits 3, 2: I/O Recovery Time (SYSCLK): + * - 0, 0 = 0; + * - 1, 1 = 12. + * - Bit 1: Extended ALE. + * + * - Register 25h: + * Bit 7 here causes AMI 111192 CMOS Setup to return 7168 KB RAM + * instead of 6912 KB. This is 256 KB off. Relocation? + * Also, returning bit 5 clear instead of set, causes the AMI BIOS + * to set bits 0,1 of register 45h to 1,0 instead of 0,1. + * + * - Register 2Dh: + * - Bit 7: Enable 256KB Memory Relocation; + * - Bit 6: Enable 384KB Memory Relocation, bit 7 must also be set. + * + * - Register 2Eh: + * - Bit 7: CC000-CFFFF Shadow Read Enable; + * - Bit 6: CC000-CFFFF Shadow Write Enable; + * - Bit 5: C8000-CBFFF Shadow Read Enable; + * - Bit 4: C8000-CBFFF Shadow Write Enable; + * - Bit 3: C4000-C7FFF Shadow Read Enable; + * - Bit 2: C4000-C7FFF Shadow Write Enable; + * - Bit 1: C0000-C3FFF Shadow Read Enable; + * - Bit 0: C0000-C3FFF Shadow Write Enable. + * + * - Register 2Fh: + * - Bit 7: DC000-DFFFF Shadow Read Enable; + * - Bit 6: DC000-DFFFF Shadow Write Enable; + * - Bit 5: D8000-DBFFF Shadow Read Enable; + * - Bit 4: D8000-DBFFF Shadow Write Enable; + * - Bit 3: D4000-D7FFF Shadow Read Enable; + * - Bit 2: D4000-D7FFF Shadow Write Enable; + * - Bit 1: D0000-D3FFF Shadow Read Enable; + * - Bit 0: D0000-D3FFF Shadow Write Enable. + * + * - Register 30h: + * - Bit 7: E0000-EFFFF Shadow Read Enable; + * - Bit 6: E0000-EFFFF Shadow Write Enable. + * + * - Register 31h: + * - Bit 7: F0000-FFFFF Shadow Read Enable; + * - Bit 6: F0000-FFFFF Shadow Write Enable. + * + * - Register 33h (NOTE: Waitstates also affect register 32h): + * - Bits 3, 0: + * - 0,0 = 0 W/S; + * - 1,0 = 1 W/S; + * - 1,1 = 2 W/S. + * + * - Register 40h: + * - Bit 3: External Cache Enabled (0 = yes, 1 = no); + * I also see bits 5, 4, 3 of register 44h affected: + * - 38h (so all 3 set) when cache is disabled; + * - 00h (all 3 clear) when it's enabled. + * + * - Register 45h: + * - Bit 3: Video Shadow RAM Cacheable; + * - Bit 4: Adapter Shadow RAM Cacheable; + * - Bit 5: BIOS Shadow RAM Cacheable. + * + * Authors: Miran Grca, + * Tiseno100, + * + * Copyright 2025 Miran Grca. + * Copyright 2021-2025 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/chipset.h> + +typedef struct { + uint8_t index; + uint8_t regs[256]; + uint8_t shadow[4]; +} sl82c461_t; + +#ifdef ENABLE_SL82C461_LOG +int sl82c461_do_log = ENABLE_SL82C461_LOG; + +static void +sl82c461_log(const char *fmt, ...) +{ + va_list ap; + + if (sl82c461_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define sl82c461_log(fmt, ...) +#endif + +static void +sl82c461_recalcmapping(sl82c461_t *dev) +{ + int do_shadow = 0; + + for (uint32_t i = 0; i < 8; i += 2) { + if ((dev->regs[0x2e] ^ dev->shadow[0x00]) & (3 << i)) { + uint32_t base = 0x000c0000 + ((i >> 1) << 14); + uint32_t read = ((dev->regs[0x2e] >> i) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x2e] >> i) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00004000, read | write); + + do_shadow++; + } + + if ((dev->regs[0x2f] ^ dev->shadow[0x01]) & (3 << i)) { + uint32_t base = 0x000d0000 + ((i >> 1) << 14); + uint32_t read = ((dev->regs[0x2f] >> i) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x2f] >> i) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00004000, read | write); + + do_shadow++; + } + } + + if ((dev->regs[0x30] ^ dev->shadow[0x02]) & 0xc0) { + uint32_t base = 0x000e0000; + uint32_t read = ((dev->regs[0x30] >> 6) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x30] >> 6) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + mem_set_mem_state_both(base, 0x00010000, read | write); + + do_shadow++; + } + + if ((dev->regs[0x31] ^ dev->shadow[0x03]) & 0xc0) { + uint32_t base = 0x000f0000; + uint32_t read = ((dev->regs[0x31] >> 6) & 0x02) ? MEM_READ_INTERNAL : + MEM_READ_EXTANY; + uint32_t write = ((dev->regs[0x31] >> 6) & 0x01) ? MEM_WRITE_INTERNAL : + MEM_WRITE_EXTANY; + + shadowbios = !!((dev->regs[0x31] >> 6) & 0x02); + shadowbios_write = !!((dev->regs[0x31] >> 6) & 0x01); + + mem_set_mem_state_both(base, 0x00010000, read | write); + + do_shadow++; + } + + if (do_shadow) { + memcpy(dev->shadow, &(dev->regs[0x2e]), 4 * sizeof(uint8_t)); + flushmmucache_nopc(); + } +} + +static void +sl82c461_write(uint16_t addr, uint8_t val, void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + + sl82c461_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + if (addr & 0x0001) { + dev->regs[dev->index] = val; + + switch (dev->index) { + case 0x01: + /* NOTE: This is to be verified. */ + mem_a20_alt = val & 1; + mem_a20_recalc(); + break; + case 0x02: { + double bus_clk; + switch (val & 0x1c) { + case 0x00: + bus_clk = cpu_busspeed / 3.0; + break; + case 0x04: + bus_clk = cpu_busspeed / 4.0; + break; + case 0x08: + bus_clk = cpu_busspeed / 5.0; + break; + default: + case 0x0c: + bus_clk = 7159091.0; + break; + case 0x10: + bus_clk = cpu_busspeed / 6.0; + break; + case 0x18: + bus_clk = cpu_busspeed / 2.5; + break; + case 0x1c: + bus_clk = cpu_busspeed / 2.0; + break; + } + cpu_set_isa_speed((int) round(bus_clk)); + break; + } case 0x2d: + switch (val & 0xc0) { + case 0xc0: + mem_remap_top(384); + break; + case 0x80: + mem_remap_top(256); + break; + default: + case 0x00: + mem_remap_top(0); + break; + } + break; + case 0x2e ... 0x31: + sl82c461_recalcmapping(dev); + break; + case 0x33: + switch (val & 0x09) { + default: + case 0x00: + cpu_waitstates = 0; + break; + case 0x08: + cpu_waitstates = 1; + break; + case 0x09: + cpu_waitstates = 2; + break; + } + cpu_update_waitstates(); + break; + case 0x40: + cpu_cache_ext_enabled = !(val & 0x08); + cpu_update_waitstates(); + break; + } + } else + dev->index = val; +} + +static uint8_t +sl82c461_read(uint16_t addr, void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + uint8_t ret = 0x00; + + if (addr & 0x0001) + if (dev->index == 0x00) + ret = dev->regs[dev->index] | 0x40; + else + ret = dev->regs[dev->index]; + else + ret = dev->index; + + sl82c461_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + + return ret; +} + +static void +sl82c461_close(void *priv) +{ + sl82c461_t *dev = (sl82c461_t *) priv; + + free(dev); +} + +static void * +sl82c461_init(const device_t *info) +{ + sl82c461_t *dev = (sl82c461_t *) calloc(1, sizeof(sl82c461_t)); + + dev->regs[0x00] = 0x40; + + dev->regs[0x02] = 0x0c; + dev->regs[0x40] = 0x08; + + memset(dev->shadow, 0xff, 4 * sizeof(uint8_t)); + + mem_a20_alt = 0x00; + mem_a20_recalc(); + + cpu_set_isa_speed(7159091.0); + + sl82c461_recalcmapping(dev); + + cpu_waitstates = 0; + cpu_cache_ext_enabled = 0; + + cpu_update_waitstates(); + + io_sethandler(0x00a8, 2, + sl82c461_read, NULL, NULL, + sl82c461_write, NULL, NULL, dev); + + return dev; +} + +const device_t sl82c461_device = { + .name = "Symphony SL82C461 (Haydn II)", + .internal_name = "sis_85c471", + .flags = 0, + .local = 0, + .init = sl82c461_init, + .close = sl82c461_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index fe088b209..94884383b 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -159,6 +159,9 @@ extern const device_t stpc_atlas_device; extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; +/* Symphony */ +extern const device_t sl82c461_device; + /* UMC */ extern const device_t umc_8886f_device; extern const device_t umc_8886af_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 8abd8fef1..77768832e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -555,6 +555,7 @@ extern int machine_at_aptiva510_init(const machine_t *); extern int machine_at_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); +extern int machine_at_dtk461_init(const machine_t *); extern int machine_at_sis401_init(const machine_t *); extern int machine_at_isa486_init(const machine_t *); extern int machine_at_av4_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e75c5414e..fded8c094 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -134,6 +134,27 @@ machine_at_tandy4000_init(const machine_t *model) return ret; } +int +machine_at_dtk461_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dtk461/DTK.BIO", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sl82c461_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_sis401_common_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5acee0350..e60ccf71d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6403,6 +6403,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMIKey F KBC firmware. */ + { + .name = "[Symphony SL42C460] DTK PKM-0031Y", + .internal_name = "dtk461", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SYMPHONY_SL82C460, + .init = machine_at_dtk461_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .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_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, but it does not write a byte after C9, which is consistent with AMIKey, so From 4beee4452b8e83cc0cb0da70dc0289ab004629f7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 May 2025 05:15:15 +0200 Subject: [PATCH 13/29] Siemens D824: Use the VL82C113 (should be 114 but the only datasheet available of it, has no registers, but says it's backwards compatible with the 113). --- src/machine/m_at_386dx_486.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index fded8c094..0e382d0c4 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -443,7 +443,11 @@ machine_at_d824_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); - device_add(&keyboard_ps2_device); + /* + Technically, it should be the VL82C114 but we do not have + a proper datasheet of it that tells us the registers. + */ + device_add(&vl82c113_device); device_add(&ide_isa_device); device_add(&fdc37c651_device); From 1995ee582a7e15cfb4dbd8b4db940ffe78b3e243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Thu, 15 May 2025 06:46:10 +0200 Subject: [PATCH 14/29] DTK PKM-0031Y: Fix RAM limits. --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e60ccf71d..e5310d7c0 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6428,7 +6428,7 @@ const machine_t machines[] = { .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 65536, + .max = 32768, .step = 1024 }, .nvrmask = 127, From 94313fed0373296af47857a8bb79cfc63127d9c9 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Thu, 15 May 2025 17:44:54 -0300 Subject: [PATCH 15/29] AC97: Add Winbond W83971D codec --- src/include/86box/snd_ac97.h | 2 ++ src/sound/snd_ac97_codec.c | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/include/86box/snd_ac97.h b/src/include/86box/snd_ac97.h index 45a921863..a365f5afa 100644 --- a/src/include/86box/snd_ac97.h +++ b/src/include/86box/snd_ac97.h @@ -100,6 +100,7 @@ #define AC97_CODEC_STAC9708 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08) #define AC97_CODEC_STAC9721 AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09) #define AC97_CODEC_TR28023 AC97_VENDOR_ID('T', 'R', 'A', 0x03) +#define AC97_CODEC_W83971D AC97_VENDOR_ID('W', 'E', 'C', 0x01) #define AC97_CODEC_WM9701A AC97_VENDOR_ID('W', 'M', 'L', 0x00) typedef struct ac97_vendor_reg_t { @@ -150,6 +151,7 @@ extern const device_t cs4297a_device; extern const device_t stac9708_device; extern const device_t stac9721_device; extern const device_t tr28023_device; +extern const device_t w83971d_device; extern const device_t wm9701a_device; extern const device_t ac97_via_device; diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index e92830f67..4a9c1e6c6 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -104,6 +104,12 @@ static const struct { .extid_flags = 0, .pcsr_mask = 0x3f }, + { + .device = &w83971d_device, + .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, + .reset_flags = (27 << AC97_3D_SHIFT), + .pcsr_mask = 0x3f + }, { .device = &wm9701a_device, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, @@ -284,8 +290,9 @@ line_gain: case 0x22: /* 3D Control */ switch (ac97_codecs[dev->model].reset_flags >> AC97_3D_SHIFT) { - case 1: /* Analog Devices */ - case 6: /* Crystal */ + case 1: /* Analog Devices */ + case 6: /* Crystal */ + case 27: /* Winbond */ val &= 0x000f; break; @@ -764,6 +771,20 @@ const device_t tr28023_device = { .config = NULL }; +const device_t w83971d_device = { + .name = "Winbond W83971D", + .internal_name = "w83971d", + .flags = DEVICE_AC97, + .local = AC97_CODEC_W83971D, + .init = ac97_codec_init, + .close = ac97_codec_close, + .reset = ac97_codec_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t wm9701a_device = { .name = "Wolfson WM9701A", .internal_name = "wm9701a", From 2007632e73d6db3566bc3383d172f4931fc6c662 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Thu, 15 May 2025 17:45:27 -0300 Subject: [PATCH 16/29] AC97: Remove redundant initializers --- src/sound/snd_ac97_codec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index 4a9c1e6c6..1b28a8aab 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -68,7 +68,6 @@ static const struct { .device = &cs4297_device, .misc_flags = AC97_MASTER_6B | AC97_AUXOUT | AC97_AUXOUT_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, .pcsr_mask = 0x7f, .vendor_regs = (const ac97_vendor_reg_t[]) {{0, 0x5a, 0x0301, 0x0000}, {0}} }, @@ -100,8 +99,6 @@ static const struct { { .device = &tr28023_device, .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_MONOOUT_6B | AC97_PCBEEP | AC97_PHONE | AC97_POP | AC97_MS | AC97_LPBK, - .reset_flags = 0, - .extid_flags = 0, .pcsr_mask = 0x3f }, { @@ -114,7 +111,6 @@ static const struct { .device = &wm9701a_device, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .reset_flags = AC97_DAC_18B | AC97_ADC_18B, - .extid_flags = 0, .pcsr_mask = 0x3f } // clang-format on From 941766f2e84ec581f29c06f92e21db3361878b8d Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 16 May 2025 05:04:48 +0200 Subject: [PATCH 17/29] Added the ZEOS Martin. --- src/chipset/vl82c480.c | 117 +++++++++++++++++++++++++++-------- src/include/86box/machine.h | 1 + src/include/86box/nvr.h | 1 + src/machine/m_at_286_386sx.c | 4 +- src/machine/m_at_386dx_486.c | 42 ++++++++++--- src/machine/machine_table.c | 65 +++++++++++++++---- src/nvr_at.c | 42 ++++++++++++- src/sio/sio_vl82c113.c | 6 +- 8 files changed, 226 insertions(+), 52 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 496544c63..8ca2c5847 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -24,34 +24,37 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/io.h> +#include <86box/machine.h> #include <86box/mem.h> #include <86box/nmi.h> #include <86box/port_92.h> #include <86box/chipset.h> typedef struct vl82c480_t { - uint8_t idx; - uint8_t regs[256]; + uint8_t idx; + uint8_t regs[256]; + uint32_t banks[4]; } vl82c480_t; static int -vl82c480_shflags(uint8_t access) +vl82c480_shflags(uint8_t access, uint8_t access2) { int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + int wp = ((access2 & 0x03) == 0x01); switch (access) { default: case 0x00: - ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); break; case 0x01: - ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); break; case 0x02: - ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; + ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); break; case 0x03: - ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; + ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); break; } @@ -59,27 +62,60 @@ vl82c480_shflags(uint8_t access) } static void -vl82c480_recalc(vl82c480_t *dev) +vl82c480_recalc_shadow(vl82c480_t *dev) { uint32_t base; uint8_t access; + uint8_t access2; shadowbios = 0; shadowbios_write = 0; for (uint8_t i = 0; i < 6; i++) { for (uint8_t j = 0; j < 8; j += 2) { - base = 0x000a0000 + (i << 16) + (j << 13); - access = (dev->regs[0x0d + i] >> j) & 3; - mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); + base = 0x000a0000 + (i << 16) + (j << 13); + access = (dev->regs[0x0d + i] >> j) & 3; + access2 = (dev->regs[0x13 + i] >> j) & 3; + mem_set_mem_state(base, 0x4000, vl82c480_shflags(access, access2)); shadowbios |= ((base >= 0xe0000) && (access & 0x02)); - shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); + shadowbios_write |= ((base >= 0xe0000) && (access & 0x01) && !(access2 & 0x01)); } } flushmmucache(); } +static void +vl82c480_recalc_banks(vl82c480_t *dev) +{ + uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; + uint8_t shifts[4] = { 0, 4, 0, 4 }; + uint8_t regs[4] = { 0x02, 0x02, 0x03, 0x03 }; + uint32_t total = 0; + + for (uint8_t i = 0; i < 4; i++) { + uint8_t shift = shifts[i]; + uint8_t reg = regs[i]; + uint8_t cfg = (dev->regs[reg] >> shift) & 0x7; + uint32_t size = sizes[cfg]; + + total += MIN(dev->banks[i], size); + } + + if (total > 1024) { + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10); + } else { + if (total >= 1024) + mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000); + else + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_high_mapping); + } + + flushmmucache(); +} + static void vl82c480_write(uint16_t addr, uint8_t val, void *priv) { @@ -91,16 +127,24 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) break; case 0xed: - if (dev->idx >= 0x01 && dev->idx <= 0x24) { + if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) || + ((dev->idx >= 0x20) && (dev->idx <= 0x24))) { switch (dev->idx) { default: dev->regs[dev->idx] = val; break; + case 0x02: case 0x03: + dev->regs[dev->idx] = val; + if (!strcmp(machine_get_internal_name(), "martin")) + vl82c480_recalc_banks(dev); + break; case 0x04: if (dev->regs[0x00] == 0x98) dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); else dev->regs[dev->idx] = val; + if (!strcmp(machine_get_internal_name(), "martin")) + dev->regs[dev->idx] &= 0x1f; break; case 0x05: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); @@ -108,14 +152,11 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) case 0x07: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); break; - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: + case 0x0d ... 0x18: dev->regs[dev->idx] = val; - vl82c480_recalc(dev); + vl82c480_recalc_shadow(dev); + if (dev->idx >= 0x13) + flushmmucache(); break; } } @@ -124,8 +165,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) /* TODO: This is actually Fast A20 disable. */ #if 0 case 0xee: - if (mem_a20_alt) - outb(0x92, inb(0x92) & ~2); + mem_a20_alt = 0x00; + mem_a20_recalc(); break; #endif @@ -146,14 +187,16 @@ vl82c480_read(uint16_t addr, void *priv) break; case 0xed: - ret = dev->regs[dev->idx]; + if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) || + ((dev->idx >= 0x20) && (dev->idx <= 0x24))) + ret = dev->regs[dev->idx]; break; /* TODO: This is actually Fast A20 enable. */ #if 0 case 0xee: - if (!mem_a20_alt) - outb(0x92, inb(0x92) | 2); + mem_a20_alt = 0x02; + mem_a20_recalc(); break; #endif @@ -180,7 +223,9 @@ vl82c480_close(void *priv) static void * vl82c480_init(const device_t *info) { - vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); + vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t)); + uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 }; + uint32_t ms = mem_size; dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; @@ -191,9 +236,27 @@ vl82c480_init(const device_t *info) dev->regs[0x07] = 0x21; dev->regs[0x08] = 0x38; + for (uint8_t i = 0; i < 4; i++) { + uint32_t size = 0; + + for (uint8_t j = 2; i < 7; j++) { + if (ms >= sizes[j]) + size = sizes[j]; + else + break; + } + + ms -= size; + + dev->banks[i] = size; + + if ((ms == 0) || (size == 0)) + break; + } + io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev); - device_add(&port_92_device); + device_add(&port_92_pci_device); return dev; } diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 77768832e..24bfb245e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -545,6 +545,7 @@ extern int machine_at_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); +extern int machine_at_martin_init(const machine_t *); extern int machine_at_403tg_init(const machine_t *); extern int machine_at_403tg_d_init(const machine_t *); diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 0f7d22172..273fc0a37 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -99,6 +99,7 @@ extern const device_t ami_1994_nvr_device; extern const device_t ami_1995_nvr_device; extern const device_t via_nvr_device; extern const device_t p6rp4_nvr_device; +extern const device_t martin_nvr_device; extern const device_t elt_nvr_device; #endif diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index c9fb124cb..e7aa66662 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -724,7 +724,9 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5402_onboard_device); - machine_at_common_ide_init(model); + machine_at_common_init_ex(model, 2); + + device_add(&ide_isa_device); device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */ device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0e382d0c4..0b47c285f 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -412,14 +412,16 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); - - device_add(&vl82c480_device); - if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + device_add(&vl82c113_device); + + device_add(&ide_isa_device); device_add(&fdc37c651_ide_device); return ret; @@ -436,13 +438,13 @@ machine_at_d824_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); - - device_add(&vl82c480_device); - if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + /* Technically, it should be the VL82C114 but we do not have a proper datasheet of it that tells us the registers. @@ -455,6 +457,30 @@ machine_at_d824_init(const machine_t *model) return ret; } +int +machine_at_martin_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/martin/NONSCSI.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + device_add(&vl82c480_device); + device_add(&vl82c113_device); + + device_add(&ide_vlb_device); + device_add(&fdc37c651_ide_device); + + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_acera1g_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e60ccf71d..281505469 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6526,7 +6526,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ + /* Has a VLSI VL82C114 Combination I/O which holds the KBC. */ { .name = "[VLSI 82C481] Siemens Nixdorf D824", .internal_name = "d824", @@ -6554,7 +6554,7 @@ const machine_t machines[] = { .max = 32768, .step = 2048 }, - .nvrmask = 127, + .nvrmask = 255, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -6773,6 +6773,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMI MegaKey KBC. */ + { + .name = "[i420TX] J-Bond PCI400C-A", + .internal_name = "pci400ca", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_pci400ca_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_PCI, + .flags = MACHINE_SCSI, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = &keyboard_at_ami_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a standalone AMI Megakey 1993, which is type 'P'. */ { .name = "[IMS 8848] Tekram G486IP", @@ -6934,13 +6974,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC. */ + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { - .name = "[i420TX] J-Bond PCI400C-A", - .internal_name = "pci400ca", + .name = "[VLSI 82C480] ZEOS Martin", + .internal_name = "martin", .type = MACHINE_TYPE_486_S2, - .chipset = MACHINE_CHIPSET_INTEL_420TX, - .init = machine_at_pci400ca_init, + .chipset = MACHINE_CHIPSET_VLSI_VL82C480, + .init = machine_at_martin_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -6955,15 +6995,15 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, - .flags = MACHINE_SCSI, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { - .min = 1024, + .min = 2048, .max = 65536, - .step = 1024 + .step = 2048 }, .nvrmask = 127, - .kbc_device = &keyboard_at_ami_device, + .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, @@ -6975,7 +7015,6 @@ const machine_t machines[] = { .net_device = NULL }, - /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ /* Has a Fujitsu MBL8042H KBC. */ diff --git a/src/nvr_at.c b/src/nvr_at.c index bde80b434..2acfa47a4 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -296,6 +296,7 @@ #define FLAG_P6RP4_HACK 0x10 #define FLAG_PIIX4 0x20 #define FLAG_MULTI_BANK 0x40 +#define FLAG_MARTIN_HACK 0x80 typedef struct local_t { int8_t stat; @@ -733,6 +734,13 @@ nvr_read(uint16_t addr, void *priv) ret = REGD_VRT; break; + case 0x11: + if (local->flags & FLAG_MARTIN_HACK) + ret = nvr->regs[local->addr[addr_id]] | 0x02; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + case 0x2c: if (!nvr->is_new && (local->flags & FLAG_AMI_1994_HACK)) ret = nvr->regs[local->addr[addr_id]] & 0x7f; @@ -771,6 +779,17 @@ nvr_read(uint16_t addr, void *priv) ret = checksum >> 8; else ret = checksum & 0xff; + } else if (!nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) { + for (i = 0x10; i <= 0x2d; i++) { + if (i == 0x11) + checksum += (nvr->regs[i] | 0x02); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x2e) + ret = checksum >> 8; + else + ret = checksum & 0xff; } else ret = nvr->regs[local->addr[addr_id]]; break; @@ -1123,9 +1142,11 @@ nvr_at_init(const device_t *info) if (info->local & 0x10) { local->def = 0x00; local->flags |= FLAG_AMI_1992_HACK; - } else if (info->local == 36) + } else if ((info->local == 36) || (info->local == 68)) { local->def = 0x00; - else + if (info->local == 68) + local->flags |= FLAG_MARTIN_HACK; + } else local->def = 0xff; nvr->irq = 8; local->cent = RTC_CENTURY_AT; @@ -1160,6 +1181,9 @@ nvr_at_init(const device_t *info) /* Initialize the generic NVR. */ nvr_init(nvr); + if (nvr->is_new && (local->flags & FLAG_MARTIN_HACK)) + nvr->regs[0x11] = nvr->regs[0x2f] = 0x02; + if (nvr_at_inited == 0) { /* Start the timers. */ timer_add(&local->update_timer, timer_update, nvr, 0); @@ -1426,6 +1450,20 @@ const device_t amstrad_megapc_nvr_device = { .config = NULL }; +const device_t martin_nvr_device = { + .name = "Zeos Martin NVRAM", + .internal_name = "martin_nvr", + .flags = DEVICE_ISA16, + .local = 68, + .init = nvr_at_init, + .close = nvr_at_close, + .reset = nvr_at_reset, + .available = NULL, + .speed_changed = nvr_at_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + const device_t elt_nvr_device = { .name = "Epson Equity LT NVRAM", .internal_name = "elt_nvr", diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c index ee18b1893..b000fe5dd 100644 --- a/src/sio/sio_vl82c113.c +++ b/src/sio/sio_vl82c113.c @@ -22,6 +22,7 @@ #include <86box/timer.h> #include <86box/device.h> #include <86box/keyboard.h> +#include <86box/machine.h> #include <86box/nvr.h> #include <86box/sio.h> #include <86box/plat_unused.h> @@ -133,7 +134,10 @@ vl82c113_init(UNUSED(const device_t *info)) { vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); - dev->nvr = device_add(&at_nvr_device); + if (!strcmp(machine_get_internal_name(), "martin")) + dev->nvr = device_add(&martin_nvr_device); + else + dev->nvr = device_add(&amstrad_megapc_nvr_device); dev->nvr_enabled = 1; dev->nvr_base = 0x0070; From 948f50667e2845976010020e0c83bc2a94015b61 Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 16 May 2025 18:18:23 +0200 Subject: [PATCH 18/29] the ZEOS Martin Board actually has VLB Slots. --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index ffdf902a3..2e72dd1fa 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6995,7 +6995,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2, + .bus_flags = MACHINE_PS2_VLB, .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, From 34bd61fd1bdd6862a6abe7ff356742e96445d32e Mon Sep 17 00:00:00 2001 From: toggo9 <121191375+toggo9@users.noreply.github.com> Date: Fri, 16 May 2025 18:21:51 +0200 Subject: [PATCH 19/29] Correct the ET4000/W32p file. --- src/video/vid_et4000w32.c | 160 +++++++------------------------------- 1 file changed, 27 insertions(+), 133 deletions(-) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c772ffdd9..246decb9c 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -43,11 +43,8 @@ #define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" #define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" #define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.bin" -#define BIOS_ROM_PATH_W32P_IMASCAN_VLB "roms/video/et4000w32/tseng_et4000w32p-8.03.bin" -#define BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB "roms/video/et4000w32/m27c256b-at-dip28-miro20td-675dada18e7fa701369657.bin" #define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" #define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" -#define BIOS_ROM_PATH_W32P_REVCD_ONBOARD "roms/video/et4000w32/vid.BIN" #define ACL_WRST 1 #define ACL_RDST 2 @@ -58,10 +55,7 @@ enum { ET4000W32, ET4000W32I, ET4000W32P_REVC, - ET4000W32P_REVCD_ONBOARD, ET4000W32P_VIDEOMAGIC_REVB, - ET4000W32P_IMASCAN_VLB, - ET4000W32P_MIROVIDEO20TD_VLB, ET4000W32P, ET4000W32P_CARDEX, ET4000W32P_DIAMOND @@ -184,7 +178,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) sdac_ramdac_out(addr, 0, val, svga->ramdac, svga); else stg_ramdac_out(addr, val, svga->ramdac, svga); @@ -308,13 +302,13 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) if (svga->hwcursor.cur_xsize == 128) { svga->hwcursor.xoff &= 0x7f; svga->hwcursor.yoff &= 0x7f; - if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type > ET4000W32P_REVC) { if (svga->bpp == 24) { et4000->adjust_cursor = 2; } } } else { - if (et4000->type > ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type > ET4000W32P_REVC) { if ((svga->bpp == 24) && et4000->adjust_cursor) { et4000->adjust_cursor = 0; } @@ -354,7 +348,7 @@ et4000w32p_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) return sdac_ramdac_in(addr, 0, svga->ramdac, svga); else return stg_ramdac_in(addr, svga->ramdac, svga); @@ -509,8 +503,8 @@ et4000w32p_recalctimings(svga_t *svga) svga->hdisp >>= 1; svga->dots_per_clock >>= 1; } - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { - if (et4000->type == ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type <= ET4000W32P_REVC) { + if (et4000->type == ET4000W32P_REVC) { if (svga->hdisp != 1024) et4000->adjust_cursor = 1; } else @@ -520,7 +514,7 @@ et4000w32p_recalctimings(svga_t *svga) case 24: svga->hdisp /= 3; svga->dots_per_clock /= 3; - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { svga->hdisp = 640; @@ -554,7 +548,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 0x40: case 0x60: /* 256+ colours */ - if (et4000->type <= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type <= ET4000W32P_REVC) svga->clock /= 2; switch (svga->bpp) { @@ -735,13 +729,13 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | (val << 8); break; case 0x8e: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.pixel_depth = val & 0x30; else et4000->acl.queued.vbus = val & 0x03; break; case 0x8f: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.xy_dir = val & 0xb7; else et4000->acl.queued.xy_dir = val & 0x03; @@ -765,7 +759,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00ff) | (val << 8); break; case 0x9c: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.ctrl_routing = val & 0xdb; else et4000->acl.queued.ctrl_routing = val & 0xb7; @@ -791,7 +785,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) case 0xa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24); et4000->acl.internal = et4000->acl.queued; - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type >= ET4000W32P_REVC) { et4000w32p_blit_start(et4000); et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); if (!(et4000->acl.queued.ctrl_routing & 0x43)) { @@ -855,7 +849,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) static void et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uint8_t bank) { - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) { + if (et4000->type >= ET4000W32P_REVC) { if (!(et4000->acl.status & ACL_XYST)) { et4000w32_log("XY MMU block not started\n"); return; @@ -1093,7 +1087,7 @@ et4000w32p_mmu_read(uint32_t addr, void *priv) case 0x8d: return et4000->acl.internal.dest_off >> 8; case 0x8e: - if (et4000->type >= ET4000W32P_REVC && ET4000W32P_REVCD_ONBOARD) + if (et4000->type >= ET4000W32P_REVC) return et4000->acl.internal.pixel_depth; return et4000->acl.internal.vbus; case 0x8f: @@ -2785,30 +2779,6 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - break; - - case ET4000W32P_IMASCAN_VLB: - /* ET4000/W32p Imascan RGB */ - et4000->rev = 5; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_IMASCAN_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - - et4000->svga.ramdac = device_add(&stg_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = stg_getclock; - break; - - case ET4000W32P_MIROVIDEO20TD_VLB: - /* ET4000/W32p miroVIDEO 20TD LIVE! */ - et4000->rev = 5; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; @@ -2821,18 +2791,6 @@ et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVC, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - break; - - case ET4000W32P_REVCD_ONBOARD: - /* ET4000/W32p rev C */ - et4000->rev = 7; - - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_REVCD_ONBOARD, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = sdac_getclock; @@ -2932,30 +2890,12 @@ et4000w32p_videomagic_revb_vlb_available(void) return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB); } -int -et4000w32p_imascan_vlb_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P_IMASCAN_VLB); -} - -int -et4000w32p_mirovideo20td_vlb_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P_MIROVIDEO20TD_VLB); -} - int et4000w32p_revc_available(void) { return rom_present(BIOS_ROM_PATH_W32P_REVC); } -int -et4000w32p_revcd_onboard_available(void) -{ - return rom_present(BIOS_ROM_PATH_W32P_REVCD_ONBOARD); -} - int et4000w32p_noncardex_available(void) { @@ -3003,23 +2943,19 @@ et4000w32p_force_redraw(void *priv) static const device_config_t et4000w32p_config[] = { // clang-format off { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 2, - .selection = { - { - .description = "1 MB", - .value = 1 - }, - { - .description = "2 MB", - .value = 2 - }, - { - .description = "" - } - } + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 2, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1 MB", .value = 1 }, + { .description = "2 MB", .value = 2 }, + { .description = "" } + }, + .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on @@ -3081,34 +3017,6 @@ const device_t et4000w32i_vlb_device = { .config = et4000w32p_config }; -const device_t et4000w32p_imascan_vlb_device = { - .name = "Tseng Labs ET4000/w32p VLB (Imascan)", - .internal_name = "et4000w32p_imascan_vlb", - .flags = DEVICE_VLB, - .local = ET4000W32P_IMASCAN_VLB, - .init = et4000w32p_init, - .close = et4000w32p_close, - .reset = NULL, - .available = et4000w32p_imascan_vlb_available, - .speed_changed = et4000w32p_speed_changed, - .force_redraw = et4000w32p_force_redraw, - .config = et4000w32p_config -}; - -const device_t et4000w32p_mirovideo20td_vlb_device = { - .name = "Tseng Labs ET4000/w32p VLB (miroVIDEO 20TD LIVE!)", - .internal_name = "et4000w32p_mirovideo20td_vlb", - .flags = DEVICE_VLB, - .local = ET4000W32P_MIROVIDEO20TD_VLB, - .init = et4000w32p_init, - .close = et4000w32p_close, - .reset = NULL, - .available = et4000w32p_mirovideo20td_vlb_available, - .speed_changed = et4000w32p_speed_changed, - .force_redraw = et4000w32p_force_redraw, - .config = et4000w32p_config -}; - const device_t et4000w32p_videomagic_revb_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)", .internal_name = "et4000w32p_videomagic_revb_vlb", @@ -3165,20 +3073,6 @@ const device_t et4000w32p_revc_pci_device = { .config = et4000w32p_config }; -const device_t et4000w32p_revcd_onboard_pci_device = { - .name = "Tseng Labs ET4000/w32p Rev. C/D PCI (On-Board)", - .internal_name = "et4000w32p_revc_pci", - .flags = DEVICE_PCI, - .local = ET4000W32P_REVCD_ONBOARD, - .init = et4000w32p_init, - .close = et4000w32p_close, - .reset = NULL, - .available = et4000w32p_revcd_onboard_available, - .speed_changed = et4000w32p_speed_changed, - .force_redraw = et4000w32p_force_redraw, - .config = et4000w32p_config -}; - const device_t et4000w32p_noncardex_vlb_device = { .name = "Tseng Labs ET4000/w32p Rev. D VLB", .internal_name = "et4000w32p_nc_vlb", From e98424a8ae988d9e49c9f27d19122194a09c43f9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 02:35:11 +0200 Subject: [PATCH 20/29] Added the ICS SB486PV. --- src/chipset/intel_4x0.c | 7 ++- src/device.c | 10 +++- src/device/kbc_at.c | 5 +- src/include/86box/machine.h | 3 +- src/include/86box/sio.h | 3 ++ src/machine/m_at_386dx_486.c | 93 ++++++++++++++++++++++++++++++++++-- src/machine/machine_table.c | 42 ++++++++++++++++ src/sio/sio_82091aa.c | 14 ++++++ src/video/vid_cl54xx.c | 8 ++-- 9 files changed, 172 insertions(+), 13 deletions(-) diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index f9d6af150..84bd872f8 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1656,7 +1656,12 @@ i4x0_init(const device_t *info) regs[0x57] = 0x31; regs[0x59] = 0x0f; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02; - dev->max_drb = 3; + /* At the very least the 420ZX seems to read to 0x64, per the SB486PV. */ + if (dev->type == INTEL_420ZX) { + regs[0x64] = 0x02; + dev->max_drb = 4; + } else + dev->max_drb = 3; dev->drb_unit = 1; dev->drb_default = 0x02; break; diff --git a/src/device.c b/src/device.c index 1922806b9..910ff4ff9 100644 --- a/src/device.c +++ b/src/device.c @@ -897,8 +897,14 @@ device_is_valid(const device_t *device, int mch) { int ret = 1; - if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) - ret = machine_has_bus(mch, device->flags & DEVICE_BUS); + if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) { + /* Hide PCI devices on machines with only an internal PCI bus. */ + if ((device->flags & DEVICE_PCI) && + machine_has_flags(mch, MACHINE_PCI_INTERNAL)) + ret = 0; + else + ret = machine_has_bus(mch, device->flags & DEVICE_BUS); + } return ret; } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 2b9cf8c18..a8a8c51cc 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1336,7 +1336,10 @@ write64_ami(void *priv, uint8_t val) kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n"); if (!(dev->flags & DEVICE_PCI)) write_p2(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_delay_to_ob(dev, dev->ob, 0, 0x00); + if (strstr(machine_get_internal_name(), "sb486pv") != NULL) + kbc_delay_to_ob(dev, 0x03, 0, 0x00); + else + kbc_delay_to_ob(dev, dev->ob, 0, 0x00); dev->pending++; return 0; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 24bfb245e..febce3fa1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -105,7 +105,7 @@ /* Feature flags for advanced devices. */ #define MACHINE_APM 0x00080000 /* sys has APM */ #define MACHINE_ACPI 0x00100000 /* sys has ACPI */ -#define MACHINE_HWM 0x00200000 /* sys has hw monitor */ +#define MACHINE_PCI_INTERNAL 0x00200000 /* sys has only internal PCI */ #define MACHINE_CARTRIDGE 0x00400000 /* sys has cartridge bays */ /* Feature flags for internal storage controllers. */ #define MACHINE_MFM 0x00800000 /* sys has int MFM/RLL */ @@ -588,6 +588,7 @@ extern int machine_at_sb486p_init(const machine_t *); extern int machine_at_486sp3_init(const machine_t *); extern int machine_at_486sp3c_init(const machine_t *); extern int machine_at_486sp3g_init(const machine_t *); +extern int machine_at_sb486pv_init(const machine_t *); extern int machine_at_486ap4_init(const machine_t *); extern int machine_at_g486vpa_init(const machine_t *); extern int machine_at_486vipio2_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index bdff29f7f..06bf57f8f 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -71,7 +71,10 @@ extern const device_t fdc37m60x_370_device; /* ITE */ extern const device_t it8661f_device; extern const device_t it8671f_device; + +/* Intel */ extern const device_t i82091aa_device; +extern const device_t i82091aa_26e_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_pri_device; extern const device_t i82091aa_ide_device; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0b47c285f..c2cf82352 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -756,7 +756,6 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } - static const device_config_t pb450_config[] = { // clang-format off { @@ -1640,6 +1639,91 @@ machine_at_486sp3g_init(const machine_t *model) return ret; } +static const device_config_t sb486pv_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "sb486pv", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "AMI 062594 (0108)", .internal_name = "sb486pv", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/41-0108-062594-SATURN2.rom", "" } }, + { .name = "AMI 062594 (0301)", .internal_name = "sb486pv_94", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/0301-062594-SATURN2.rom", "" } }, + { .name = "AMI 071595 (1301)", .internal_name = "sb486pv_95", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/amiboot.rom", "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t sb486pv_device = { + .name = "ICS SB486PV", + .internal_name = "sb486pv_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = sb486pv_config +}; + +int +machine_at_sb486pv_init(const machine_t *model) +{ + int ret = 0; + const char* fn; + + /* No ROMs available */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + ret = bios_load_linear(fn, 0x000e0000, 131072, 0); + else + ret = bios_load_linear_inverted(fn, 0x000e0000, 131072, 0); + device_context_restore(); + + machine_at_common_init(model); + // machine_at_common_init_ex(model, 2); + + // device_add(&amstrad_megapc_nvr_device); + device_add(&ide_pci_device); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0e, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0f, PCI_CARD_VIDEO, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sio_zb_device); + device_add(&ide_rz1000_pci_single_channel_device); + device_add(&i82091aa_26e_device); + if (!strcmp(fn, "roms/machines/sb486pv/amiboot.rom")) + device_add(&intel_flash_bxt_device); + else + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420zx_device); + + return ret; +} + int machine_at_486ap4_init(const machine_t *model) { @@ -1833,12 +1917,11 @@ machine_at_sbc490_init(const machine_t *model) pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&ali1489_device); device_add(&fdc37c665_device); - - if (gfxcard[0] == VID_INTERNAL) - device_add(&tgui9440_onboard_pci_device); - device_add(&keyboard_ps2_ami_device); device_add(&sst_flash_29ee010_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index ffdf902a3..3f69865c3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -69,6 +69,7 @@ extern const device_t pb450_device; extern const device_t jukopc_device; extern const device_t vendex_device; extern const device_t c5sbm2_device; +extern const device_t sb486pv_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -8515,6 +8516,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has an AMI MEGAKey 'P' or 'R' keyboard controller. */ + { + .name = "[i420ZX] ICS SB486PV", + .internal_name = "sb486pv", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_INTEL_420ZX, + .init = machine_at_sb486pv_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + /* Has PCI but no user-facing slots. */ + .bus_flags = MACHINE_PCI, + .flags = MACHINE_PS2_KBC | MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM | MACHINE_PCI_INTERNAL, + .ram = { + .min = 2048, + .max = 65536, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &sb486pv_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5436_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ { .name = "[IMS 8848] J-Bond PCI400C-B", diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index d3cd5017a..71f8749f2 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -295,6 +295,20 @@ const device_t i82091aa_device = { .config = NULL }; +const device_t i82091aa_26e_device = { + .name = "Intel 82091AA Super I/O (Port 26Eh)", + .internal_name = "i82091aa_26e", + .flags = 0, + .local = 0x140, + .init = i82091aa_init, + .close = i82091aa_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t i82091aa_398_device = { .name = "Intel 82091AA Super I/O (Port 398h)", .internal_name = "i82091aa_398", diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 43c4e22b2..dbb9d5993 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -33,6 +33,7 @@ #include <86box/pci.h> #include <86box/rom.h> #include <86box/device.h> +#include <86box/machine.h> #include <86box/timer.h> #include <86box/video.h> #include <86box/i2c.h> @@ -4316,7 +4317,8 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5436: - if (info->local & 0x200) { + if ((info->local & 0x200) && + !strstr(machine_get_internal_name(), "sb486pv")) { romfn = NULL; gd54xx->has_bios = 0; } else @@ -4461,8 +4463,8 @@ gd54xx_init(const device_t *info) } io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) { - if (romfn == NULL) + if (gd54xx->pci && (id >= CIRRUS_ID_CLGD5430)) { + if (info->local & 0x200) pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); else pci_add_card(PCI_ADD_NORMAL, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); From 2a58d761b94397775b2410f1cb1639b9729e64fb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 03:05:46 +0200 Subject: [PATCH 21/29] VL82C480: Fix and clean-up the DRAM banks calculation code, closes #5592. --- src/chipset/vl82c480.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 8ca2c5847..56e9f1d71 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -237,20 +237,16 @@ vl82c480_init(const device_t *info) dev->regs[0x08] = 0x38; for (uint8_t i = 0; i < 4; i++) { - uint32_t size = 0; - - for (uint8_t j = 2; i < 7; j++) { + for (uint8_t j = 2; j < 7; j++) { if (ms >= sizes[j]) - size = sizes[j]; + dev->banks[i] = sizes[j]; else break; } - ms -= size; + ms -= dev->banks[i]; - dev->banks[i] = size; - - if ((ms == 0) || (size == 0)) + if ((ms == 0) || (dev->banks[i] == 0)) break; } From 5ebed5dc57e96453e9ff6b77f8c2357575156b6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 03:09:21 +0200 Subject: [PATCH 22/29] POST Card: Some Compaq-related fixes. --- src/device/postcard.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/device/postcard.c b/src/device/postcard.c index b91d8b402..95a4df646 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -147,14 +147,17 @@ postcard_init(UNUSED(const device_t *info)) if (machine_has_bus(machine, MACHINE_BUS_MCA)) postcard_port = 0x680; /* MCA machines */ - else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 ")) + else if (strstr(machines[machine].name, " PS/2 ") || + strstr(machine_getname_ex(machine), " PS/1 ")) postcard_port = 0x190; /* ISA PS/2 machines */ else if (strstr(machines[machine].name, " IBM XT ")) postcard_port = 0x60; /* IBM XT */ else if (strstr(machines[machine].name, " IBM PCjr")) { postcard_port = 0x10; /* IBM PCjr */ postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */ - } else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI)) + } else if (strstr(machines[machine].name, " Compaq ") && + !strstr(machines[machine].name, " Presario ") && + !strstr(machines[machine].name, " ProSignia ")) postcard_port = 0x84; /* ISA Compaq machines */ else if (strstr(machines[machine].name, "Olivetti")) postcard_port = 0x378; /* Olivetti machines */ From 1eb4355d769c17cebc2d23814c72f061d32ba0ac Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 03:16:52 +0200 Subject: [PATCH 23/29] FDC: Remove an excess commented out line. --- src/floppy/fdc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index e779ea2d7..e7166d1ba 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -81,7 +81,6 @@ int fdc_current[FDC_MAX] = { 0, 0 }; volatile int fdcinited = 0; -// #define ENABLE_FDC_LOG 1 #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; From b97a23aa571256d9f3c67fe6962b8833b88474b1 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 17 May 2025 05:28:45 +0200 Subject: [PATCH 24/29] WIP Plasma code --- src/machine/m_at_compaq.c | 191 +++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 74 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index c0b254388..ddd3f2a0c 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -84,20 +84,14 @@ compaq_plasma_display_set(uint8_t internal) cpq_st_display_internal = internal; } -static uint8_t -compaq_plasma_display_get(void) -{ - return cpq_st_display_internal; -} - typedef struct compaq_plasma_t { cga_t cga; - uint8_t ctl_mode; + mem_mapping_t font_ram_mapping; + uint8_t *font_ram; uint8_t port_13c6; uint8_t port_23c6; uint8_t port_27c6; uint8_t internal_monitor; - uint8_t attrmap; } compaq_plasma_t; static int compaq_machine_type = 0; @@ -119,13 +113,11 @@ compaq_plasma_recalctimings(compaq_plasma_t *self) return; } - disptime = 651; - _dispontime = 640; + disptime = 651; + _dispontime = 640; _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST / 2; - _dispofftime *= CGACONST / 2; - self->cga.dispontime = (uint64_t) (_dispontime); - self->cga.dispofftime = (uint64_t) (_dispofftime); + self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); } static void @@ -160,14 +152,31 @@ compaq_plasma_read(uint32_t addr, void *priv) } static void -compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) +compaq_plasma_font_write(uint32_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - if (self->port_23c6 & 0x08) { - if ((addr >= 0x3d0) && (addr <= 0x3dc)) - addr ^= 0x60; - } + addr &= 0x1fff; + + self->font_ram[addr] = val; +} +static uint8_t +compaq_plasma_font_read(uint32_t addr, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; + uint8_t ret = 0x00; + + addr &= 0x1fff; + + ret = self->font_ram[addr]; + + return ret; +} + +static void +compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) +{ + compaq_plasma_t *self = (compaq_plasma_t *) priv; switch (addr) { /* Emulated CRTC, register select */ @@ -183,21 +192,11 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (self->cga.crtcreg == 0x12) { - self->attrmap = val; - compaq_plasma_recalcattrs(self); - return; - } cga_out(addr, val, &self->cga); - compaq_plasma_recalctimings(self); break; case 0x3d8: case 0x3d9: - case 0x3db: - case 0x3dc: cga_out(addr, val, &self->cga); break; @@ -208,10 +207,15 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x23c6: self->port_23c6 = val; - if (val & 0x08) /* Disable internal CGA */ - mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x8000); - else - mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x8000); + pclog("Write 23c6=%02x.\n", val); + if (val & 0x08) { /* Disable internal CGA */ + mem_mapping_disable(&self->cga.mapping); + mem_mapping_enable(&self->font_ram_mapping); + } else { + mem_mapping_enable(&self->cga.mapping); + mem_mapping_disable(&self->font_ram_mapping); + } + compaq_plasma_recalcattrs(self); break; case 0x27c6: @@ -229,11 +233,6 @@ compaq_plasma_in(uint16_t addr, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; uint8_t ret = 0xff; - if (self->port_23c6 & 0x08) { - if ((addr >= 0x3d0) && (addr <= 0x3dc)) - addr ^= 0x60; - } - switch (addr) { case 0x3d4: case 0x3da: @@ -246,13 +245,8 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x3d3: case 0x3d5: case 0x3d7: - if (self->cga.crtcreg == 0x12) { - ret = self->attrmap & 0x0f; - if (compaq_plasma_display_get()) - ret |= 0x30; /* Plasma / CRT */ - } else - ret = cga_in(addr, &self->cga); - break; + ret = cga_in(addr, &self->cga); + break; case 0x3d8: ret = self->cga.cgamode; @@ -260,10 +254,16 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x13c6: ret = self->port_13c6; +#if 0 + if ((self->cga.cgamode & 0x28) == 0x00) + ret |= 0x04; +#endif + pclog("Read 13c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x17c6: - ret = 0xf6; + ret = 0xe6; + pclog("Read 17c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x1bc6: @@ -272,6 +272,7 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x23c6: ret = self->port_23c6; + pclog("Read 23c6=%02x.\n", ret); break; case 0x27c6: @@ -350,12 +351,15 @@ compaq_plasma_poll(void *priv) chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; /* text attributes */ attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; - } else - chr = attr = 0; + } else { + chr = 0x00; + attr = 0x00; + } /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + underline = ((attr & 0x07) == 0x01); + underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -376,8 +380,13 @@ compaq_plasma_poll(void *priv) /* Set intensity bit */ cols[1] = normcols[attr][1]; cols[0] = normcols[attr][0]; - blink = ((attr & 0x80) << 3) + 7 + 16; } + + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + chr_addr |= 0x1000; + /* character underline active and 7th row of pixels in character height being drawn */ if (underline && (sc == 7)) { /* for each pixel in character width */ @@ -385,12 +394,25 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } else { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } + if (attr & 0x03) { + if ((self->port_23c6 >> 5) == 1) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); + } else if ((self->port_23c6 >> 5) == 4) { + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16); + } + } + } ma++; } } @@ -412,13 +434,15 @@ compaq_plasma_poll(void *priv) chr = self->cga.vram[(addr + (x << 1)) & 0x7fff]; /* text attributes */ attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff]; - } else - chr = attr = 0; - + } else { + chr = 0x00; + attr = 0x00; + } /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ - underline = (((self->port_23c6 >> 5) == 2) && (attr & 0x01) && !(attr & 0x06)); + underline = ((attr & 0x07) == 0x01); + underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -439,22 +463,40 @@ compaq_plasma_poll(void *priv) /* Set intensity bit */ cols[1] = normcols[attr][1]; cols[0] = normcols[attr][0]; - blink = ((attr & 0x80) << 3) + 7 + 16; } + /* character address */ + uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; + if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + chr_addr |= 0x1000; + /* character underline active and 7th row of pixels in character height being drawn */ - if (underline && (self->cga.sc == 7)) { + if (underline && (sc == 7)) { /* for each pixel in character width */ for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1]; } else if (drawcursor) { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } else { for (c = 0; c < 8; c++) - buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(fontdatm2[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } + if (attr & 0x03) { + if ((self->port_23c6 >> 5) == 1) + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); + buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black); + } + else if ((self->port_23c6 >> 5) == 4) + for (c = 0; c < 8; c++) { + uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f; + uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f; + uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f; + buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16); + } + } ma++; } } else { @@ -493,6 +535,14 @@ compaq_plasma_poll(void *priv) ink0 = ink1 = black; break; case 1: + if (self->cga.displine & 0x01) { + ink0 = black; + ink1 = black; + } else { + ink0 = amber; + ink1 = black; + } + break; case 2: if (self->cga.displine & 0x01) { ink0 = black; @@ -545,7 +595,7 @@ compaq_plasma_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - /* ogc specific */ + /* Plasma specific */ video_blit_memtoscreen(0, 0, xsize, ysize); frames++; @@ -622,7 +672,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x11; n <= 0xFF; n++) { if ((n & 7) == 0) continue; - if (self->attrmap & 4) { /* Inverse */ + if ((self->port_23c6 >> 5) == 1) { /* Inverse */ blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; } else { /* Normal */ @@ -635,7 +685,7 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) for (n = 0x01; n <= 0x0E; n++) { if (n == 7) continue; - if (self->attrmap & 1) { + if ((self->port_23c6 >> 5) == 1) { blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; blinkcols[n + 128][0] = amber; @@ -678,11 +728,6 @@ compaq_plasma_init(UNUSED(const device_t *info)) { compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t)); - if (compaq_machine_type == COMPAQ_PORTABLEIII) - loadfont_ex("roms/machines/portableiii/K Combined.bin", 11, 0x4bb2); - else - loadfont_ex("roms/machines/portableiii/P.2 Combined.bin", 11, 0x4b49); - cga_init(&self->cga); video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); @@ -691,24 +736,21 @@ compaq_plasma_init(UNUSED(const device_t *info)) self->cga.vram = malloc(0x8000); self->internal_monitor = 1; + self->font_ram = malloc(0x2000); cga_comp_init(self->cga.revision); timer_set_callback(&self->cga.timer, compaq_plasma_poll); timer_set_p(&self->cga.timer, self); mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); + mem_mapping_add(&self->font_ram_mapping, 0xb8000, 0x02000, compaq_plasma_font_read, NULL, NULL, compaq_plasma_font_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); for (int i = 1; i <= 2; i++) { io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); } - io_sethandler(0x03d0, 0x000c, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); - /* Default attribute mapping is 4 */ - self->attrmap = 4; - compaq_plasma_recalcattrs(self); - - self->cga.cgastat = 0xf4; overscan_x = overscan_y = 16; self->cga.rgb_type = device_get_config_int("rgb_type"); @@ -725,6 +767,7 @@ compaq_plasma_close(void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; free(self->cga.vram); + free(self->font_ram); free(self); } From f7c27285825a234b8846af20635ca0e18e796f56 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 05:41:53 +0200 Subject: [PATCH 25/29] Fix the incorrect high intensity attribute bit checking (bit 3 is 0x08, not 0x03!). --- src/machine/m_at_compaq.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index ddd3f2a0c..1d1770b46 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -355,11 +355,12 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } + uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ underline = ((attr & 0x07) == 0x01); - underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -384,7 +385,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -400,7 +401,7 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if (attr & 0x03) { + if (hi_bit) { if ((self->port_23c6 >> 5) == 1) { for (c = 0; c < 8; c++) buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black); @@ -438,11 +439,12 @@ compaq_plasma_poll(void *priv) chr = 0x00; attr = 0x00; } + uint8_t hi_bit = attr & 0x08; /* check if cursor has to be drawn */ drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10)); /* check if character underline mode should be set */ underline = ((attr & 0x07) == 0x01); - underline |= ((self->port_23c6 >> 5) == 2) && (attr & 0x03); + underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit); if (underline) { /* set forecolor to white */ attr = attr | 0x7; @@ -467,7 +469,7 @@ compaq_plasma_poll(void *priv) /* character address */ uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff; - if (((self->port_23c6 >> 5) == 3) && (attr & 0x03)) + if (((self->port_23c6 >> 5) == 3) && hi_bit) chr_addr |= 0x1000; /* character underline active and 7th row of pixels in character height being drawn */ @@ -483,7 +485,7 @@ compaq_plasma_poll(void *priv) buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0]; } - if (attr & 0x03) { + if (hi_bit) { if ((self->port_23c6 >> 5) == 1) for (c = 0; c < 8; c++) { buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black); From 45316f9be0c8e25f5538fda428b6d8574eb488ff Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 06:18:48 +0200 Subject: [PATCH 26/29] Potential fix for MS OS/2. --- src/machine/m_at_compaq.c | 64 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 1d1770b46..98803ca94 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -135,7 +135,10 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - self->cga.vram[addr & 0x7fff] = val; + if (self->port_23c6 & 0x08) + self->font_ram[addr & 0x1fff] = val; + else + self->cga.vram[addr & 0x7fff] = val; compaq_plasma_waitstates(&self->cga); } @@ -146,29 +149,11 @@ compaq_plasma_read(uint32_t addr, void *priv) uint8_t ret; compaq_plasma_waitstates(&self->cga); - ret = (self->cga.vram[addr & 0x7fff]); - return ret; -} - -static void -compaq_plasma_font_write(uint32_t addr, uint8_t val, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - - addr &= 0x1fff; - - self->font_ram[addr] = val; -} -static uint8_t -compaq_plasma_font_read(uint32_t addr, void *priv) -{ - compaq_plasma_t *self = (compaq_plasma_t *) priv; - uint8_t ret = 0x00; - - addr &= 0x1fff; - - ret = self->font_ram[addr]; + if (self->port_23c6 & 0x08) + ret = (self->font_ram[addr & 0x1fff]); + else + ret = (self->cga.vram[addr & 0x7fff]); return ret; } @@ -203,18 +188,20 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x13c6: self->port_13c6 = val; compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0); + /* + For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA; + Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA; + This leads me to believe bit 2 is not relevant to the mode. + */ + if ((val & 0x03) == 0x03) + mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000); + else + mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000); break; case 0x23c6: self->port_23c6 = val; pclog("Write 23c6=%02x.\n", val); - if (val & 0x08) { /* Disable internal CGA */ - mem_mapping_disable(&self->cga.mapping); - mem_mapping_enable(&self->font_ram_mapping); - } else { - mem_mapping_enable(&self->cga.mapping); - mem_mapping_disable(&self->font_ram_mapping); - } compaq_plasma_recalcattrs(self); break; @@ -725,6 +712,15 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) } } +void +compaq_dump(void) +{ + FILE *f = fopen("d:\\86boxnew\\compaq_plasma_vram.dmp", "wb"); + for (int i = 0; i < 65536; i++) + fputc(mem_readb_phys(0x000b0000 + i), f); + fclose(f); +} + static void * compaq_plasma_init(UNUSED(const device_t *info)) { @@ -744,8 +740,10 @@ compaq_plasma_init(UNUSED(const device_t *info)) timer_set_callback(&self->cga.timer, compaq_plasma_poll); timer_set_p(&self->cga.timer, self); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); - mem_mapping_add(&self->font_ram_mapping, 0xb8000, 0x02000, compaq_plasma_font_read, NULL, NULL, compaq_plasma_font_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, + compaq_plasma_read, NULL, NULL, + compaq_plasma_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, self); for (int i = 1; i <= 2; i++) { io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); @@ -768,6 +766,8 @@ compaq_plasma_close(void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; + compaq_dump(); + free(self->cga.vram); free(self->font_ram); free(self); From 9772aeae4de7b83101a82dfd11b96308f3deebe3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 06:21:12 +0200 Subject: [PATCH 27/29] Clean up the excess logging. --- src/machine/m_at_compaq.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 98803ca94..1f5ecdb58 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -201,7 +201,6 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) case 0x23c6: self->port_23c6 = val; - pclog("Write 23c6=%02x.\n", val); compaq_plasma_recalcattrs(self); break; @@ -245,12 +244,10 @@ compaq_plasma_in(uint16_t addr, void *priv) if ((self->cga.cgamode & 0x28) == 0x00) ret |= 0x04; #endif - pclog("Read 13c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x17c6: ret = 0xe6; - pclog("Read 17c6=%02x, mode=%02x.\n", ret, self->cga.cgamode); break; case 0x1bc6: @@ -259,7 +256,6 @@ compaq_plasma_in(uint16_t addr, void *priv) case 0x23c6: ret = self->port_23c6; - pclog("Read 23c6=%02x.\n", ret); break; case 0x27c6: @@ -712,15 +708,6 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) } } -void -compaq_dump(void) -{ - FILE *f = fopen("d:\\86boxnew\\compaq_plasma_vram.dmp", "wb"); - for (int i = 0; i < 65536; i++) - fputc(mem_readb_phys(0x000b0000 + i), f); - fclose(f); -} - static void * compaq_plasma_init(UNUSED(const device_t *info)) { @@ -766,8 +753,6 @@ compaq_plasma_close(void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - compaq_dump(); - free(self->cga.vram); free(self->font_ram); free(self); From dc9101c00c247232fc2a458919c892974bcfc420 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 06:56:52 +0200 Subject: [PATCH 28/29] VL82C480: Remove the incorrect implementation of registers 13h to 18h, fixes the Siemens-Nixdorf D824. --- src/chipset/vl82c480.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 56e9f1d71..6354ac15a 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -37,24 +37,23 @@ typedef struct vl82c480_t { } vl82c480_t; static int -vl82c480_shflags(uint8_t access, uint8_t access2) +vl82c480_shflags(uint8_t access) { int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; - int wp = ((access2 & 0x03) == 0x01); switch (access) { default: case 0x00: - ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); + ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; break; case 0x01: - ret = MEM_READ_EXTANY | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); + ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; break; case 0x02: - ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY); + ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; break; case 0x03: - ret = MEM_READ_INTERNAL | (wp ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL); + ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; break; } @@ -66,7 +65,6 @@ vl82c480_recalc_shadow(vl82c480_t *dev) { uint32_t base; uint8_t access; - uint8_t access2; shadowbios = 0; shadowbios_write = 0; @@ -75,10 +73,9 @@ vl82c480_recalc_shadow(vl82c480_t *dev) for (uint8_t j = 0; j < 8; j += 2) { base = 0x000a0000 + (i << 16) + (j << 13); access = (dev->regs[0x0d + i] >> j) & 3; - access2 = (dev->regs[0x13 + i] >> j) & 3; - mem_set_mem_state(base, 0x4000, vl82c480_shflags(access, access2)); + mem_set_mem_state(base, 0x4000, vl82c480_shflags(access)); shadowbios |= ((base >= 0xe0000) && (access & 0x02)); - shadowbios_write |= ((base >= 0xe0000) && (access & 0x01) && !(access2 & 0x01)); + shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); } } @@ -152,11 +149,9 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv) case 0x07: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); break; - case 0x0d ... 0x18: + case 0x0d ... 0x12: dev->regs[dev->idx] = val; vl82c480_recalc_shadow(dev); - if (dev->idx >= 0x13) - flushmmucache(); break; } } From ddd271f6eee42c875523a10ee19eb1fdf2b8240b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 17 May 2025 21:02:06 +0200 Subject: [PATCH 29/29] Honore the fixed bits of flags when pushing them to the stack, fixes #5093. --- src/codegen_new/codegen_ops_stack.c | 4 ++++ src/cpu/x86_ops_flag.h | 17 ++++------------- src/cpu/x86_ops_flag_2386.h | 17 ++++------------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index fca9c9efa..f93289197 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -390,6 +390,8 @@ ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUS uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); uop_CALL_FUNC(ir, flags_rebuild); sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5); + uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002); uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); SUB_SP(ir, 2); @@ -406,6 +408,8 @@ ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNU uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); uop_CALL_FUNC(ir, flags_rebuild); + uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5); + uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002); if (cpu_CR4_mask & CR4_VME) uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); else if (CPUID) diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index a0fa612a8..7e7324341 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) temp = (cpu_state.flags & ~I_FLAG) | 0x3000; if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; + temp = (temp & 0x7fd5) | 2; PUSH_W(temp); } else { x86gpf(NULL, 0); @@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) } } else { flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); @@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat)) else tempw = cpu_state.eflags & 4; flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); @@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { - x86gpf(NULL, 0); - return 1; - } - tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) - cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; flags_extract(); #ifdef USE_DEBUG_REGS_486 rf_flag_no_clear = 1; diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h index c9a2d5ab2..787b268dc 100644 --- a/src/cpu/x86_ops_flag_2386.h +++ b/src/cpu/x86_ops_flag_2386.h @@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) temp = (cpu_state.flags & ~I_FLAG) | 0x3000; if (cpu_state.eflags & VIF_FLAG) temp |= I_FLAG; + temp = (temp & 0x7fd5) | 2; PUSH_W(temp); } else { x86gpf(NULL, 0); @@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat)) } } else { flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_W(cpu_state.flags); } CLOCK_CYCLES(4); @@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat)) else tempw = cpu_state.eflags & 4; flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2; PUSH_L(cpu_state.flags | (tempw << 16)); CLOCK_CYCLES(4); PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); @@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat)) { uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { - x86gpf(NULL, 0); - return 1; - } - tempw = POP_W(); if (cpu_state.abrt) return 1; - if (!(msw & 1)) - cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; flags_extract(); rf_flag_no_clear = 1;