From 3c4e8c9e4a017dbad54ed206c5eae1dafa1f5540 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Mar 2025 19:46:16 +0900 Subject: [PATCH 01/32] PS55DA2: Fix screen size calculation * Fix screen size calculation in recalctimings. * Set the position of underscore by CRTC reg value. * Optimize text drawing function --- src/video/vid_ps55da2.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index db2035717..81fb1601d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -253,7 +253,7 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -// #define ENABLE_DA2_LOG 1 +#define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG @@ -1850,12 +1850,13 @@ da2_render_text(da2_t *da2) int fg, bg; uint32_t chr_dbcs; int chr_wide = 0; + int colormode = ((da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80); // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { chr = da2->cram[(da2->ma) & DA2_MASK_CRAM]; attr = da2->cram[(da2->ma + 1) & DA2_MASK_CRAM]; // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* IO 3E8h, Index 1Dh */ + if (colormode) /* IO 3E8h, Index 1Dh */ { /* --Parse attribute byte in color mode-- */ bg = 0; /* bg color is always black (the only way to change background color is programming PAL) */ fg = getPS55ForeColor(attr, da2); @@ -1932,24 +1933,24 @@ da2_render_text(da2_t *da2) chr_wide = 0; } /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ - if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) { /* Underscore only in monochrome mode */ + if (da2->sc == da2->crtc[LC_UNDERLINE_LOCATION] && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[fg]]; /* under line (white) */ } /* Column 1 (Vertical Line) */ if (attr & 0x10) { - p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */ + p[0] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */ } if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */ + p[n] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */ } /* Drawing text cursor */ drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ - fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); + int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ + fg = (colormode) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); bg = 0; if (attr & 0x04) { /* Color 0 if reverse */ bg = fg; @@ -2048,8 +2049,8 @@ da2_render_textm3(da2_t *da2) drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { // int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); - // int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ - // fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + // int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ + // fg = (colormode) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; // bg = 0; // if (attr & 0x04) {/* Color 0 if reverse */ // bg = fg; @@ -2217,10 +2218,10 @@ da2_recalctimings(da2_t *da2) da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; - if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { - da2->hdisp--; - da2->dispend -= 29; - } + da2->hdisp -= da2->crtc[LC_START_H_DISPLAY_ENAB]; + /* In the J-DOS setup, you'll see the blank below the screen. It's NOT a bug. */ + da2->dispend -= da2->crtc[LC_START_V_DISPLAY_ENAB]; + da2->dispend++; da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; From abb0670eb06538ee7f836473fc28ebb9e6705920 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:22:38 +0900 Subject: [PATCH 02/32] PS55DA2: remove unused code, update comment --- src/video/vid_ps55da2.c | 56 ++++++----------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 81fb1601d..af8beddb9 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -11,7 +11,6 @@ * Notes: There are some known issues that should be corrected. * - Incorrect foreground text color appears on an active window in OS/2 J1.3. * - Glitches some part of graphics on the Control Panel in OS/2 J2.1 beta. - * - The screen resolution and blanking interval time maybe not correct. * * The code should be tested with following cases. * - Execute MODE 0, 1, 3 and 4 commands in DOS K3.3 to test various video modes. @@ -253,7 +252,7 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 +// #define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG @@ -284,10 +283,8 @@ da2_log(const char *fmt, ...) #endif typedef struct da2_t { - // mem_mapping_t vmapping; mem_mapping_t cmapping; - // uint8_t crtcreg; uint8_t ioctl[16]; uint8_t fctl[32]; uint16_t crtc[128]; @@ -297,7 +294,6 @@ typedef struct da2_t { uint8_t attrc[0x40]; int attraddr, attrff; int attr_palette_enable; - // uint8_t seqregs[64]; int outflipflop; int inflipflop; int iolatch; @@ -312,7 +308,6 @@ typedef struct da2_t { uint32_t gdcla[8]; uint32_t gdcinput[8]; uint32_t gdcsrc[8]; - uint32_t debug_vramold[8]; uint8_t dac_mask, dac_status; int dac_read, dac_write, dac_pos; @@ -335,7 +330,7 @@ typedef struct da2_t { PALETTE vgapal; int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int hdisp, htotal, hdisp_time, rowoffset; int lowres, interlace; int rowcount; double clock; @@ -2190,13 +2185,14 @@ da2_updatevidselector(da2_t *da2) /* INT 10h video modes supported in DOS J4.0 (The DA-2 doesn't have a video BIOS on its card.) Mode Type Colors Text Base Address PELs Render - 3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 725 textm3 + 3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 754 textm3 8 A/N/K 2 80 x 25 E0000h 1040 x 725 text Ah APA 1 78 x 25 A0000h 1024 x 768 color_4bpp Dh APA 16 78 x 25 A0000h 1024 x 768 color_4bpp Eh A/N/K 16 80 x 25 E0000h 1040 x 725 text Fh APA 256 NA A0000h 1024 x 768 color_8bpp 45h(undoc) APA 16 NA A0000h 1040 x 768 color_4bpp + 46h(undoc) APA 16 ? A0000h 1040 x 768 color_4bpp */ void da2_recalctimings(da2_t *da2) @@ -2218,10 +2214,10 @@ da2_recalctimings(da2_t *da2) da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + /* In the video mode 3, you'll see a blank below the screen. It's NOT a bug. */ da2->hdisp -= da2->crtc[LC_START_H_DISPLAY_ENAB]; - /* In the J-DOS setup, you'll see the blank below the screen. It's NOT a bug. */ da2->dispend -= da2->crtc[LC_START_V_DISPLAY_ENAB]; - da2->dispend++; + da2->dispend += 1; da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; @@ -2247,15 +2243,14 @@ da2_recalctimings(da2_t *da2) if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; - da2->hdisp_old = da2->hdisp; if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { da2_log("Set videomode to PS/55 8 bpp graphics.\n"); da2->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_A000; } else { /* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); - da2->vram_display_mask = DA2_MASK_A000; da2->render = da2_render_color_4bpp; + da2->vram_display_mask = DA2_MASK_A000; } } else { /* text mode */ @@ -2269,7 +2264,6 @@ da2_recalctimings(da2_t *da2) da2->vram_display_mask = DA2_MASK_CRAM; } da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; da2->char_width = 13; } // if (!da2->scrblank && da2->attr_palette_enable) @@ -2643,9 +2637,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->mmdbg_vidaddr = addr; //} #endif - cycles -= video_timing_write_b; - da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ addr <<= 3; @@ -2686,27 +2678,13 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; else da2->gdcinput[i] = val; - - // for (int i = 0; i < 8; i++) - // da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ da2_gdcropB(addr, bitmask, da2); - // for (int i = 0; i < 8; i++) - // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], bitmask, da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch - ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; case 1:/* equiv to vga write mode 2 */ - // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - // for (int i = 0; i < 8; i++) - // if (da2->planemask & (1 << i)) - // DA2_vram_w(addr | i, (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask), da2); - // //fprintf(da2->mmdbg_fp, "m1-1"); - // } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); da2_gdcropB(addr, bitmask, da2); - //fprintf(da2->mmdbg_fp, "m1-2"); - // } break; case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) @@ -2718,7 +2696,6 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2_gdcropB(addr, bitmask, da2); break; } - // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); } else { /* mode 3h text */ cycles -= video_timing_write_b; DA2_vram_w(addr, val, da2); @@ -2742,8 +2719,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) #ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_wW %x %d %d %02x\n", addr, addr % (da2->rowoffset * 2) * 8, addr / (da2->rowoffset * 2), val); - // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - //{ + if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { fprintf(da2->mmdbg_fp, "\nW %x %x ", addr, val); for (int i = 0; i <= 0xb; i++) @@ -2756,7 +2732,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; - //} #endif cycles -= video_timing_write_w; @@ -2764,7 +2739,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); da2->changedvram[addr >> 9] = changeframecount; - // da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; for (int i = 0; i < 8; i++) @@ -3025,9 +2999,6 @@ da2_poll(void *priv) da2->cgastat |= 8; x = da2->hdisp; - // if (da2->interlace && !da2->oddeven) da2->lastline++; - // if (da2->interlace && da2->oddeven) da2->firstline--; - wx = x; wy = da2->lastline - da2->firstline; @@ -3044,17 +3015,9 @@ da2_poll(void *priv) changeframecount = da2->interlace ? 3 : 2; da2->vslines = 0; - // if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); - // else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); - // da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; - /* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; - else*/ da2->ma = da2->maback = da2->ma_latch; da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; - - // da2->ma <<= 1; - // da2->maback <<= 1; da2->ca <<= 1; // da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF); @@ -3071,9 +3034,6 @@ da2_poll(void *priv) if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } - // printf("2 %i\n",da2_vsyncstart); - // da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); - // da2_log("r"); } static void From 3380783876290bcb148f7e7573dabe428acd6697 Mon Sep 17 00:00:00 2001 From: flama12333 <143599905+flama12333@users.noreply.github.com> Date: Tue, 25 Mar 2025 21:42:01 -0500 Subject: [PATCH 03/32] Replace MACHINE_PCI with MACHINE_PS2_PCI for pl4600c machine_table.c this will be solved the ps2 mouse not appear on the setting --- 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 9f2d0ce47..62a0e1374 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8902,7 +8902,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, + .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM, .ram = { .min = 1024, From bd8bade3fbe7d48208d717768abca7536522f9c2 Mon Sep 17 00:00:00 2001 From: flama12333 <143599905+flama12333@users.noreply.github.com> Date: Wed, 26 Mar 2025 01:32:24 -0500 Subject: [PATCH 04/32] update machine_table.c --- 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 62a0e1374..aa9bae305 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9358,7 +9358,7 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PCI, + .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, From 0a5fa0da39c12d3f438ea7197943bdf0e2df38e0 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 18 Jan 2025 15:47:41 +0500 Subject: [PATCH 05/32] Add variants of the CH Flightstick Pro and Thrustmaster FCS with rudder pedals (CH Pedals and Thrustmaster RCS respectively) attached --- src/game/gameport.c | 26 +++++++------- src/game/joystick_ch_flightstick_pro.c | 38 ++++++++++++++++++++ src/game/joystick_tm_fcs.c | 48 ++++++++++++++++++++++++++ src/include/86box/gameport.h | 2 ++ 4 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/game/gameport.c b/src/game/gameport.c index 90986a655..8ae1c7d25 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -88,18 +88,20 @@ static const joystick_if_t joystick_none = { static const struct { const joystick_if_t *joystick; } joysticks[] = { - { &joystick_none }, - { &joystick_2axis_2button }, - { &joystick_2axis_4button }, - { &joystick_2axis_6button }, - { &joystick_2axis_8button }, - { &joystick_3axis_2button }, - { &joystick_3axis_4button }, - { &joystick_4axis_4button }, - { &joystick_ch_flightstick_pro }, - { &joystick_sw_pad }, - { &joystick_tm_fcs }, - { NULL } + { &joystick_none }, + { &joystick_2axis_2button }, + { &joystick_2axis_4button }, + { &joystick_2axis_6button }, + { &joystick_2axis_8button }, + { &joystick_3axis_2button }, + { &joystick_3axis_4button }, + { &joystick_4axis_4button }, + { &joystick_ch_flightstick_pro }, + { &joystick_ch_flightstick_pro_ch_pedals }, + { &joystick_sw_pad }, + { &joystick_tm_fcs }, + { &joystick_tm_fcs_rcs }, + { NULL } }; static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL }; diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 6aaaa5dc5..5b240f3f4 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -112,6 +112,26 @@ ch_flightstick_pro_read_axis(UNUSED(void *priv), int axis) } } +static int +ch_flightstick_pro_ch_pedals_read_axis(UNUSED(void *priv), int axis) +{ + if (!JOYSTICK_PRESENT(0, 0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0][0].axis[0]; + case 1: + return joystick_state[0][0].axis[1]; + case 2: + return joystick_state[0][0].axis[3]; + case 3: + return joystick_state[0][0].axis[2]; + default: + return 0; + } +} + static void ch_flightstick_pro_a0_over(UNUSED(void *priv)) { @@ -135,3 +155,21 @@ const joystick_if_t joystick_ch_flightstick_pro = { .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, .pov_names = { "POV" } }; + +const joystick_if_t joystick_ch_flightstick_pro_ch_pedals = { + .name = "CH Flightstick Pro + CH Pedals", + .internal_name = "ch_flightstick_pro_ch_pedals", + .init = ch_flightstick_pro_init, + .close = ch_flightstick_pro_close, + .read = ch_flightstick_pro_read, + .write = ch_flightstick_pro_write, + .read_axis = ch_flightstick_pro_ch_pedals_read_axis, + .a0_over = ch_flightstick_pro_a0_over, + .axis_count = 4, + .button_count = 4, + .pov_count = 1, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Throttle", "Rudder" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { "POV" } +}; diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index 4440b039e..52d77d8fb 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -112,6 +112,36 @@ tm_fcs_read_axis(UNUSED(void *priv), int axis) } } +static int +tm_fcs_rcs_read_axis(UNUSED(void *priv), int axis) +{ + if (!JOYSTICK_PRESENT(0, 0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0][0].axis[0]; + case 1: + return joystick_state[0][0].axis[1]; + case 2: + return joystick_state[0][0].axis[2]; + case 3: + if (joystick_state[0][0].pov[0] == -1) + return 32767; + if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45) + return -32768; + if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135) + return -16384; + if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225) + return 0; + if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315) + return 16384; + return 0; + default: + return 0; + } +} + static void tm_fcs_a0_over(UNUSED(void *priv)) { @@ -135,3 +165,21 @@ const joystick_if_t joystick_tm_fcs = { .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, .pov_names = { "POV" } }; + +const joystick_if_t joystick_tm_fcs_rcs = { + .name = "Thrustmaster FCS + Rudder Control System", + .internal_name = "thrustmaster_fcs_rcs", + .init = tm_fcs_init, + .close = tm_fcs_close, + .read = tm_fcs_read, + .write = tm_fcs_write, + .read_axis = tm_fcs_rcs_read_axis, + .a0_over = tm_fcs_a0_over, + .axis_count = 3, + .button_count = 4, + .pov_count = 1, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Rudder" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { "POV" } +}; diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index c5fc1d192..7928cdd30 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -179,10 +179,12 @@ extern const joystick_if_t joystick_2axis_6button; extern const joystick_if_t joystick_2axis_8button; extern const joystick_if_t joystick_ch_flightstick_pro; +extern const joystick_if_t joystick_ch_flightstick_pro_ch_pedals; extern const joystick_if_t joystick_sw_pad; extern const joystick_if_t joystick_tm_fcs; +extern const joystick_if_t joystick_tm_fcs_rcs; extern int gameport_available(int); extern int gameport_has_config(int); From 99e8d13afa047e3dc7d8aa7afae188e4748055a8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 30 Mar 2024 16:21:41 +0600 Subject: [PATCH 06/32] Implement NEC V20/V30's i8080 emulation mode --- src/cpu/8080.c | 290 ------------- src/cpu/808x.c | 168 +++++++- src/cpu/CMakeLists.txt | 2 +- src/cpu/i8080.c | 826 ++++++++++++++++++++++++++++++++++++++ src/cpu/i8080.h | 35 ++ src/include/86box/i8080.h | 69 ---- 6 files changed, 1025 insertions(+), 365 deletions(-) delete mode 100644 src/cpu/8080.c create mode 100644 src/cpu/i8080.c create mode 100644 src/cpu/i8080.h delete mode 100644 src/include/86box/i8080.h diff --git a/src/cpu/8080.c b/src/cpu/8080.c deleted file mode 100644 index 7a7e7b96c..000000000 --- a/src/cpu/8080.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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. - * - * 8080 CPU emulation. - * - * Authors: Cacodemon345 - * - * Copyright 2022 Cacodemon345 - */ - -#include -#include -#include "cpu.h" -#include <86box/timer.h> -#include <86box/i8080.h> -#include <86box/mem.h> -#include <86box/plat_unused.h> - -static int completed = 1; -static int in_rep = 0; -static int repeating = 0; -static int rep_c_flag = 0; -static int oldc; -static int cycdiff; -#ifdef UNUSED_8080_VARS -static int prefetching = 1; -static int refresh = 0; -static int clear_lock = 0; - -static uint32_t cpu_src = 0; -static uint32_t cpu_dest = 0; -static uint32_t cpu_data = 0; -#endif - -static void -clock_start(void) -{ - cycdiff = cycles; -} - -static void -clock_end(void) -{ - int diff = cycdiff - cycles; - - /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ - tsc += (uint64_t) diff * (xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process(); -} - -static void -i8080_wait(int c, int bus) -{ - cycles -= c; - if (bus < 2) { - clock_end(); - clock_start(); - } -} - -#ifdef UNUSED_8080_FUNCS -static uint8_t -readmemb(uint32_t a) -{ - uint8_t ret; - - i8080_wait(4, 1); - ret = read_mem_b(a); - - return ret; -} - -static uint8_t -ins_fetch(i8080 *cpu) -{ - uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc); - - cpu->pc++; - return ret; -} -#endif - -void -transfer_from_808x(i8080 *cpu) -{ - cpu->hl = BX; - cpu->bc = CX; - cpu->de = DX; - cpu->a = AL; - cpu->flags = cpu_state.flags & 0xFF; - cpu->sp = BP; - cpu->pc = cpu_state.pc; - cpu->oldpc = cpu_state.oldpc; - cpu->pmembase = cs; - cpu->dmembase = ds; -} - -void -transfer_to_808x(i8080 *cpu) -{ - BX = cpu->hl; - CX = cpu->bc; - DX = cpu->de; - AL = cpu->a; - cpu_state.flags &= 0xFF00; - cpu_state.flags |= cpu->flags & 0xFF; - BP = cpu->sp; - cpu_state.pc = cpu->pc; -} - -uint8_t -getreg_i8080(i8080 *cpu, uint8_t reg) -{ - uint8_t ret = 0xFF; - switch (reg) { - case 0x0: - ret = cpu->b; - break; - case 0x1: - ret = cpu->c; - break; - case 0x2: - ret = cpu->d; - break; - case 0x3: - ret = cpu->e; - break; - case 0x4: - ret = cpu->h; - break; - case 0x5: - ret = cpu->l; - break; - case 0x6: - ret = cpu->readmembyte(cpu->dmembase + cpu->sp); - break; - case 0x7: - ret = cpu->a; - break; - } - return ret; -} - -uint8_t -getreg_i8080_emu(i8080 *cpu, uint8_t reg) -{ - uint8_t ret = 0xFF; - switch (reg) { - case 0x0: - ret = CH; - break; - case 0x1: - ret = CL; - break; - case 0x2: - ret = DH; - break; - case 0x3: - ret = DL; - break; - case 0x4: - ret = BH; - break; - case 0x5: - ret = BL; - break; - case 0x6: - ret = cpu->readmembyte(cpu->dmembase + BP); - break; - case 0x7: - ret = AL; - break; - } - return ret; -} - -void -setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val) -{ - switch (reg) { - case 0x0: - CH = val; - break; - case 0x1: - CL = val; - break; - case 0x2: - DH = val; - break; - case 0x3: - DL = val; - break; - case 0x4: - BH = val; - break; - case 0x5: - BL = val; - break; - case 0x6: - cpu->writemembyte(cpu->dmembase + BP, val); - break; - case 0x7: - AL = val; - break; - } -} - -void -setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val) -{ - switch (reg) { - case 0x0: - cpu->b = val; - break; - case 0x1: - cpu->c = val; - break; - case 0x2: - cpu->d = val; - break; - case 0x3: - cpu->e = val; - break; - case 0x4: - cpu->h = val; - break; - case 0x5: - cpu->l = val; - break; - case 0x6: - cpu->writemembyte(cpu->dmembase + cpu->sp, val); - break; - case 0x7: - cpu->a = val; - break; - } -} - -void -interpret_exec8080(UNUSED(i8080 *cpu), uint8_t opcode) -{ - switch (opcode) { - case 0x00: - { - break; - } - } -} - -/* Actually implement i8080 emulation. */ -void -exec8080(i8080 *cpu, int cycs) -{ -#ifdef UNUSED_8080_VARS - uint8_t temp = 0, temp2; - uint8_t old_af; - uint8_t handled = 0; - uint16_t addr, tempw; - uint16_t new_ip; - int bits; -#endif - - cycles += cycs; - - while (cycles > 0) { - cpu->startclock(); - - if (!repeating) { - cpu->oldpc = cpu->pc; - opcode = cpu->fetchinstruction(cpu); - oldc = cpu->flags & C_FLAG_I8080; - i8080_wait(1, 0); - } - completed = 1; - if (completed) { - repeating = 0; - in_rep = 0; - rep_c_flag = 0; - cpu->endclock(); - if (cpu->checkinterrupts) - cpu->checkinterrupts(); - } - } -} diff --git a/src/cpu/808x.c b/src/cpu/808x.c index e3a326503..4ce1fa3b9 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -18,10 +18,13 @@ #include #include #include +#include #include #include #include +#include "i8080.h" + #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" @@ -70,6 +73,9 @@ static int in_rep = 0, repeating = 0, rep_c_flag = 0; static int oldc, clear_lock = 0; static int refresh = 0, cycdiff; +static i8080 emulated_processor; +static bool cpu_md_write_disable = 1; + /* Various things needed for 8087. */ #define OP_TABLE(name) ops_##name @@ -195,6 +201,54 @@ prefetch_queue_get_size(void) { return pfq_size; } +static void set_if(int cond); + +void +sync_from_i8080(void) +{ + AL = emulated_processor.a; + BH = emulated_processor.h; + BL = emulated_processor.l; + CH = emulated_processor.b; + CL = emulated_processor.c; + DH = emulated_processor.d; + DL = emulated_processor.e; + BP = emulated_processor.sp; + + cpu_state.pc = emulated_processor.pc; + cpu_state.flags &= 0xFF00; + cpu_state.flags |= emulated_processor.sf << 7; + cpu_state.flags |= emulated_processor.zf << 6; + cpu_state.flags |= emulated_processor.hf << 4; + cpu_state.flags |= emulated_processor.pf << 2; + cpu_state.flags |= 1 << 1; + cpu_state.flags |= emulated_processor.cf << 0; + set_if(emulated_processor.iff); +} + +void +sync_to_i8080(void) +{ + emulated_processor.a = AL; + emulated_processor.h = BH; + emulated_processor.l = BL; + emulated_processor.b = CH; + emulated_processor.c = CL; + emulated_processor.d = DH; + emulated_processor.e = DL; + emulated_processor.sp = BP; + emulated_processor.pc = cpu_state.pc; + emulated_processor.iff = !!(cpu_state.flags & I_FLAG); + + emulated_processor.sf = (cpu_state.flags >> 7) & 1; + emulated_processor.zf = (cpu_state.flags >> 6) & 1; + emulated_processor.hf = (cpu_state.flags >> 4) & 1; + emulated_processor.pf = (cpu_state.flags >> 2) & 1; + emulated_processor.cf = (cpu_state.flags >> 0) & 1; + + emulated_processor.interrupt_delay = noint; +} + uint16_t get_last_addr(void) @@ -582,6 +636,33 @@ load_seg(uint16_t seg, x86seg *s) s->seg = seg & 0xffff; } +uint8_t fetch_i8080_opcode(UNUSED(void* priv), uint16_t addr) +{ + return readmemb(cs + addr); +} + +uint8_t fetch_i8080_data(UNUSED(void* priv), uint16_t addr) +{ + return readmemb(ds + addr); +} + +void put_i8080_data(UNUSED(void* priv), uint16_t addr, uint8_t val) +{ + writememb(ds, addr, val); +} + +static uint8_t i8080_port_in(UNUSED(void* priv), uint8_t port) +{ + cpu_io(8, 0, port); + return AL; +} + +static void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val) +{ + AL = val; + cpu_io(8, 1, port); +} + void reset_808x(int hard) { @@ -619,6 +700,14 @@ reset_808x(int hard) use_custom_nmi_vector = 0x00; custom_nmi_vector = 0x00000000; + + cpu_md_write_disable = 1; + i8080_init(&emulated_processor); + emulated_processor.write_byte = put_i8080_data; + emulated_processor.read_byte = fetch_i8080_data; + emulated_processor.read_byte_seg = fetch_i8080_opcode; + emulated_processor.port_in = i8080_port_in; + emulated_processor.port_out = i8080_port_out; } static void @@ -994,6 +1083,11 @@ interrupt(uint16_t addr) uint16_t new_cs, new_ip; uint16_t tempf; + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + pclog("CALLN/INT#/NMI#\n"); + } + addr <<= 2; cpu_state.eaaddr = addr; old_cs = CS; @@ -1010,6 +1104,8 @@ interrupt(uint16_t addr) tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; @@ -1020,6 +1116,56 @@ interrupt(uint16_t addr) push(&old_ip); } +/* Ditto, but for breaking into emulation mode. */ +static void +interrupt_brkem(uint16_t addr) +{ + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; + + addr <<= 2; + cpu_state.eaaddr = addr; + old_cs = CS; + access(5, 16); + new_ip = readmemw(0, cpu_state.eaaddr); + wait(1, 0); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + access(6, 16); + new_cs = readmemw(0, cpu_state.eaaddr); + prefetching = 0; + pfq_clear(); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + push(&tempf); + cpu_state.flags &= ~(MD_FLAG); + cpu_md_write_disable = 0; + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); + push(&old_ip); + sync_to_i8080(); + pclog("BRKEM mode\n"); +} + +void +retem_i8080(void) +{ + sync_from_i8080(); + + cpu_state.pc = pop(); + CS = pop(); + cpu_state.flags = pop() | MD_FLAG; + + cpu_md_write_disable = 1; + pclog("RETEM mode\n"); +} + void interrupt_808x(uint16_t addr) { @@ -1771,6 +1917,15 @@ execx86(int cycs) while (cycles > 0) { clock_start(); + if (is_nec && !(cpu_state.flags & MD_FLAG)) { + i8080_step(&emulated_processor); + set_if(emulated_processor.iff); + cycles -= emulated_processor.cyc; + emulated_processor.cyc = 0; + completed = 1; + goto exec_completed; + } + if (!repeating) { cpu_state.oldpc = cpu_state.pc; opcode = pfq_fetchb(); @@ -2344,8 +2499,8 @@ execx86(int cycs) break; case 0xFF: /* BRKEM */ - /* Unimplemented for now. */ - fatal("808x: Unsupported 8080 emulation mode attempted to enter into!"); + interrupt_brkem(pfq_fetchb()); + handled = 1; break; default: @@ -2857,11 +3012,12 @@ execx86(int cycs) break; case 0x9D: /*POPF*/ access(25, 16); - if (is_nec) + if (is_nec && cpu_md_write_disable) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; wait(1, 0); + sync_to_i8080(); break; case 0x9E: /*SAHF*/ wait(1, 0); @@ -3127,13 +3283,15 @@ execx86(int cycs) access(62, 8); set_ip(new_ip); access(45, 8); - if (is_nec) + if (is_nec && cpu_md_write_disable) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; wait(5, 0); noint = 1; nmi_enable = 1; + if (is_nec && !(cpu_state.flags & MD_FLAG)) + sync_to_i8080(); break; case 0xD0: @@ -3659,7 +3817,7 @@ execx86(int cycs) break; } } - +exec_completed: if (completed) { repeating = 0; ovr_seg = NULL; diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 9c1385d4f..dc7f5ac11 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -29,7 +29,7 @@ add_library(cpu OBJECT x86seg_2386.c x87.c x87_timings.c - 8080.c + i8080.c ) if(AMD_K5) diff --git a/src/cpu/i8080.c b/src/cpu/i8080.c new file mode 100644 index 000000000..688923997 --- /dev/null +++ b/src/cpu/i8080.c @@ -0,0 +1,826 @@ +/* + * 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. + * + * Intel 8080 CPU emulation + * + * Authors: Cacodemon345 + * Nicolas Allemand + * + * Copyright (c) 2018 Nicolas Allemand + * Copyright (c) 2024 Cacodemon345 + * + */ + +#include "i8080.h" +#include + +// Changes from upstream: +// Add CALLN and RETEM instructions. +// Add code for instruction fetches. + +// this array defines the number of cycles one opcode takes. +// note that there are some special cases: conditional RETs and CALLs +// add +6 cycles if the condition is met +// clang-format off +static const uint8_t OPCODES_CYCLES[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 0 + 4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 1 + 4, 10, 16, 5, 5, 5, 7, 4, 4, 10, 16, 5, 5, 5, 7, 4, // 2 + 4, 10, 13, 5, 10, 10, 10, 4, 4, 10, 13, 5, 5, 5, 7, 4, // 3 + 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 4 + 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 5 + 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 6 + 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5, // 7 + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8 + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9 + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B + 5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // C + 5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // D + 5, 10, 10, 18, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11, // E + 5, 10, 10, 4, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11 // F +}; +// clang-format on + +static const char* DISASSEMBLE_TABLE[] = {"nop", "lxi b,#", "stax b", "inx b", + "inr b", "dcr b", "mvi b,#", "rlc", "ill", "dad b", "ldax b", "dcx b", + "inr c", "dcr c", "mvi c,#", "rrc", "ill", "lxi d,#", "stax d", "inx d", + "inr d", "dcr d", "mvi d,#", "ral", "ill", "dad d", "ldax d", "dcx d", + "inr e", "dcr e", "mvi e,#", "rar", "ill", "lxi h,#", "shld", "inx h", + "inr h", "dcr h", "mvi h,#", "daa", "ill", "dad h", "lhld", "dcx h", + "inr l", "dcr l", "mvi l,#", "cma", "ill", "lxi sp,#", "sta $", "inx sp", + "inr M", "dcr M", "mvi M,#", "stc", "ill", "dad sp", "lda $", "dcx sp", + "inr a", "dcr a", "mvi a,#", "cmc", "mov b,b", "mov b,c", "mov b,d", + "mov b,e", "mov b,h", "mov b,l", "mov b,M", "mov b,a", "mov c,b", "mov c,c", + "mov c,d", "mov c,e", "mov c,h", "mov c,l", "mov c,M", "mov c,a", "mov d,b", + "mov d,c", "mov d,d", "mov d,e", "mov d,h", "mov d,l", "mov d,M", "mov d,a", + "mov e,b", "mov e,c", "mov e,d", "mov e,e", "mov e,h", "mov e,l", "mov e,M", + "mov e,a", "mov h,b", "mov h,c", "mov h,d", "mov h,e", "mov h,h", "mov h,l", + "mov h,M", "mov h,a", "mov l,b", "mov l,c", "mov l,d", "mov l,e", "mov l,h", + "mov l,l", "mov l,M", "mov l,a", "mov M,b", "mov M,c", "mov M,d", "mov M,e", + "mov M,h", "mov M,l", "hlt", "mov M,a", "mov a,b", "mov a,c", "mov a,d", + "mov a,e", "mov a,h", "mov a,l", "mov a,M", "mov a,a", "add b", "add c", + "add d", "add e", "add h", "add l", "add M", "add a", "adc b", "adc c", + "adc d", "adc e", "adc h", "adc l", "adc M", "adc a", "sub b", "sub c", + "sub d", "sub e", "sub h", "sub l", "sub M", "sub a", "sbb b", "sbb c", + "sbb d", "sbb e", "sbb h", "sbb l", "sbb M", "sbb a", "ana b", "ana c", + "ana d", "ana e", "ana h", "ana l", "ana M", "ana a", "xra b", "xra c", + "xra d", "xra e", "xra h", "xra l", "xra M", "xra a", "ora b", "ora c", + "ora d", "ora e", "ora h", "ora l", "ora M", "ora a", "cmp b", "cmp c", + "cmp d", "cmp e", "cmp h", "cmp l", "cmp M", "cmp a", "rnz", "pop b", + "jnz $", "jmp $", "cnz $", "push b", "adi #", "rst 0", "rz", "ret", "jz $", + "ill", "cz $", "call $", "aci #", "rst 1", "rnc", "pop d", "jnc $", "out p", + "cnc $", "push d", "sui #", "rst 2", "rc", "ill", "jc $", "in p", "cc $", + "ill", "sbi #", "rst 3", "rpo", "pop h", "jpo $", "xthl", "cpo $", "push h", + "ani #", "rst 4", "rpe", "pchl", "jpe $", "xchg", "cpe $", "ill", "xri #", + "rst 5", "rp", "pop psw", "jp $", "di", "cp $", "push psw", "ori #", + "rst 6", "rm", "sphl", "jm $", "ei", "cm $", "ill", "cpi #", "rst 7"}; + +#define SET_ZSP(c, val) \ + do { \ + c->zf = (val) == 0; \ + c->sf = (val) >> 7; \ + c->pf = parity(val); \ + } while (0) + +// memory helpers (the only four to use `read_byte` and `write_byte` function +// pointers) + +// reads a byte from memory +static inline uint8_t i8080_rb(i8080* const c, uint16_t addr) { + return c->read_byte(c->userdata, addr); +} + +// writes a byte to memory +static inline void i8080_wb(i8080* const c, uint16_t addr, uint8_t val) { + c->write_byte(c->userdata, addr, val); +} + +// reads a word from memory +static inline uint16_t i8080_rw(i8080* const c, uint16_t addr) { + return c->read_byte(c->userdata, addr + 1) << 8 | + c->read_byte(c->userdata, addr); +} + +// writes a word to memory +static inline void i8080_ww(i8080* const c, uint16_t addr, uint16_t val) { + c->write_byte(c->userdata, addr, val & 0xFF); + c->write_byte(c->userdata, addr + 1, val >> 8); +} + +// returns the next byte in memory (and updates the program counter) +static inline uint8_t i8080_next_byte(i8080* const c) { + return c->read_byte_seg ? (c->read_byte_seg(c->userdata, c->pc++)) : i8080_rb(c, c->pc++); +} + +// returns the next word in memory (and updates the program counter) +static inline uint16_t i8080_next_word(i8080* const c) { + uint16_t result = 0; + if (c->read_byte_seg) + result = c->read_byte_seg(c, c->pc) | (c->read_byte_seg(c, c->pc + 1) << 8); + else + result = i8080_rw(c, c->pc); + c->pc += 2; + return result; +} + +// paired registers helpers (setters and getters) +static inline void i8080_set_bc(i8080* const c, uint16_t val) { + c->b = val >> 8; + c->c = val & 0xFF; +} + +static inline void i8080_set_de(i8080* const c, uint16_t val) { + c->d = val >> 8; + c->e = val & 0xFF; +} + +static inline void i8080_set_hl(i8080* const c, uint16_t val) { + c->h = val >> 8; + c->l = val & 0xFF; +} + +static inline uint16_t i8080_get_bc(i8080* const c) { + return (c->b << 8) | c->c; +} + +static inline uint16_t i8080_get_de(i8080* const c) { + return (c->d << 8) | c->e; +} + +static inline uint16_t i8080_get_hl(i8080* const c) { + return (c->h << 8) | c->l; +} + +// stack helpers + +// pushes a value into the stack and updates the stack pointer +static inline void i8080_push_stack(i8080* const c, uint16_t val) { + c->sp -= 2; + i8080_ww(c, c->sp, val); +} + +// pops a value from the stack and updates the stack pointer +static inline uint16_t i8080_pop_stack(i8080* const c) { + uint16_t val = i8080_rw(c, c->sp); + c->sp += 2; + return val; +} + +// opcodes + +// returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1 +static inline bool parity(uint8_t val) { + uint8_t nb_one_bits = 0; + for (int i = 0; i < 8; i++) { + nb_one_bits += ((val >> i) & 1); + } + + return (nb_one_bits & 1) == 0; +} + +// returns if there was a carry between bit "bit_no" and "bit_no - 1" when +// executing "a + b + cy" +static inline bool carry(int bit_no, uint8_t a, uint8_t b, bool cy) { + int16_t result = a + b + cy; + int16_t carry = result ^ a ^ b; + return carry & (1 << bit_no); +} + +// adds a value (+ an optional carry flag) to a register +static inline void i8080_add( + i8080* const c, uint8_t* const reg, uint8_t val, bool cy) { + uint8_t result = *reg + val + cy; + c->cf = carry(8, *reg, val, cy); + c->hf = carry(4, *reg, val, cy); + SET_ZSP(c, result); + *reg = result; +} + +// substracts a byte (+ an optional carry flag) from a register +// see https://stackoverflow.com/a/8037485 +static inline void i8080_sub( + i8080* const c, uint8_t* const reg, uint8_t val, bool cy) { + i8080_add(c, reg, ~val, !cy); + c->cf = !c->cf; +} + +// adds a word to HL +static inline void i8080_dad(i8080* const c, uint16_t val) { + c->cf = ((i8080_get_hl(c) + val) >> 16) & 1; + i8080_set_hl(c, i8080_get_hl(c) + val); +} + +// increments a byte +static inline uint8_t i8080_inr(i8080* const c, uint8_t val) { + uint8_t result = val + 1; + c->hf = (result & 0xF) == 0; + SET_ZSP(c, result); + return result; +} + +// decrements a byte +static inline uint8_t i8080_dcr(i8080* const c, uint8_t val) { + uint8_t result = val - 1; + c->hf = !((result & 0xF) == 0xF); + SET_ZSP(c, result); + return result; +} + +// executes a logic "and" between register A and a byte, then stores the +// result in register A +static inline void i8080_ana(i8080* const c, uint8_t val) { + uint8_t result = c->a & val; + c->cf = 0; + c->hf = ((c->a | val) & 0x08) != 0; + SET_ZSP(c, result); + c->a = result; +} + +// executes a logic "xor" between register A and a byte, then stores the +// result in register A +static inline void i8080_xra(i8080* const c, uint8_t val) { + c->a ^= val; + c->cf = 0; + c->hf = 0; + SET_ZSP(c, c->a); +} + +// executes a logic "or" between register A and a byte, then stores the +// result in register A +static inline void i8080_ora(i8080* const c, uint8_t val) { + c->a |= val; + c->cf = 0; + c->hf = 0; + SET_ZSP(c, c->a); +} + +// compares the register A to another byte +static inline void i8080_cmp(i8080* const c, uint8_t val) { + int16_t result = c->a - val; + c->cf = result >> 8; + c->hf = ~(c->a ^ result ^ val) & 0x10; + SET_ZSP(c, result & 0xFF); +} + +// sets the program counter to a given address +static inline void i8080_jmp(i8080* const c, uint16_t addr) { + c->pc = addr; +} + +// jumps to next address pointed by the next word in memory if a condition +// is met +static inline void i8080_cond_jmp(i8080* const c, bool condition) { + uint16_t addr = i8080_next_word(c); + if (condition) { + c->pc = addr; + } +} + +// pushes the current pc to the stack, then jumps to an address +static inline void i8080_call(i8080* const c, uint16_t addr) { + i8080_push_stack(c, c->pc); + i8080_jmp(c, addr); +} + +// calls to next word in memory if a condition is met +static inline void i8080_cond_call(i8080* const c, bool condition) { + uint16_t addr = i8080_next_word(c); + if (condition) { + i8080_call(c, addr); + c->cyc += 6; + } +} + +// returns from subroutine +static inline void i8080_ret(i8080* const c) { + c->pc = i8080_pop_stack(c); +} + +// returns from subroutine if a condition is met +static inline void i8080_cond_ret(i8080* const c, bool condition) { + if (condition) { + i8080_ret(c); + c->cyc += 6; + } +} + +// pushes register A and the flags into the stack +static inline void i8080_push_psw(i8080* const c) { + // note: bit 3 and 5 are always 0 + uint8_t psw = 0; + psw |= c->sf << 7; + psw |= c->zf << 6; + psw |= c->hf << 4; + psw |= c->pf << 2; + psw |= 1 << 1; // bit 1 is always 1 + psw |= c->cf << 0; + i8080_push_stack(c, c->a << 8 | psw); +} + +// pops register A and the flags from the stack +static inline void i8080_pop_psw(i8080* const c) { + uint16_t af = i8080_pop_stack(c); + c->a = af >> 8; + uint8_t psw = af & 0xFF; + + c->sf = (psw >> 7) & 1; + c->zf = (psw >> 6) & 1; + c->hf = (psw >> 4) & 1; + c->pf = (psw >> 2) & 1; + c->cf = (psw >> 0) & 1; +} + +// rotate register A left +static inline void i8080_rlc(i8080* const c) { + c->cf = c->a >> 7; + c->a = (c->a << 1) | c->cf; +} + +// rotate register A right +static inline void i8080_rrc(i8080* const c) { + c->cf = c->a & 1; + c->a = (c->a >> 1) | (c->cf << 7); +} + +// rotate register A left with the carry flag +static inline void i8080_ral(i8080* const c) { + bool cy = c->cf; + c->cf = c->a >> 7; + c->a = (c->a << 1) | cy; +} + +// rotate register A right with the carry flag +static inline void i8080_rar(i8080* const c) { + bool cy = c->cf; + c->cf = c->a & 1; + c->a = (c->a >> 1) | (cy << 7); +} + +// Decimal Adjust Accumulator: the eight-bit number in register A is adjusted +// to form two four-bit binary-coded-decimal digits. +// For example, if A=$2B and DAA is executed, A becomes $31. +static inline void i8080_daa(i8080* const c) { + bool cy = c->cf; + uint8_t correction = 0; + + uint8_t lsb = c->a & 0x0F; + uint8_t msb = c->a >> 4; + + if (c->hf || lsb > 9) { + correction += 0x06; + } + + if (c->cf || msb > 9 || (msb >= 9 && lsb > 9)) { + correction += 0x60; + cy = 1; + } + + i8080_add(c, &c->a, correction, 0); + c->cf = cy; +} + +// switches the value of registers DE and HL +static inline void i8080_xchg(i8080* const c) { + uint16_t de = i8080_get_de(c); + i8080_set_de(c, i8080_get_hl(c)); + i8080_set_hl(c, de); +} + +// switches the value of a word at (sp) and HL +static inline void i8080_xthl(i8080* const c) { + uint16_t val = i8080_rw(c, c->sp); + i8080_ww(c, c->sp, i8080_get_hl(c)); + i8080_set_hl(c, val); +} + +extern void interrupt_808x(uint16_t addr); +extern void retem_i8080(void); +// executes one opcode +static inline void i8080_execute(i8080* const c, uint8_t opcode) { + c->cyc += OPCODES_CYCLES[opcode]; + + // when DI is executed, interrupts won't be serviced + // until the end of next instruction: + if (c->interrupt_delay > 0) { + c->interrupt_delay -= 1; + } + + switch (opcode) { + case 0x7F: c->a = c->a; break; // MOV A,A + case 0x78: c->a = c->b; break; // MOV A,B + case 0x79: c->a = c->c; break; // MOV A,C + case 0x7A: c->a = c->d; break; // MOV A,D + case 0x7B: c->a = c->e; break; // MOV A,E + case 0x7C: c->a = c->h; break; // MOV A,H + case 0x7D: c->a = c->l; break; // MOV A,L + case 0x7E: c->a = i8080_rb(c, i8080_get_hl(c)); break; // MOV A,M + + case 0x0A: c->a = i8080_rb(c, i8080_get_bc(c)); break; // LDAX B + case 0x1A: c->a = i8080_rb(c, i8080_get_de(c)); break; // LDAX D + case 0x3A: c->a = i8080_rb(c, i8080_next_word(c)); break; // LDA word + + case 0x47: c->b = c->a; break; // MOV B,A + case 0x40: c->b = c->b; break; // MOV B,B + case 0x41: c->b = c->c; break; // MOV B,C + case 0x42: c->b = c->d; break; // MOV B,D + case 0x43: c->b = c->e; break; // MOV B,E + case 0x44: c->b = c->h; break; // MOV B,H + case 0x45: c->b = c->l; break; // MOV B,L + case 0x46: c->b = i8080_rb(c, i8080_get_hl(c)); break; // MOV B,M + + case 0x4F: c->c = c->a; break; // MOV C,A + case 0x48: c->c = c->b; break; // MOV C,B + case 0x49: c->c = c->c; break; // MOV C,C + case 0x4A: c->c = c->d; break; // MOV C,D + case 0x4B: c->c = c->e; break; // MOV C,E + case 0x4C: c->c = c->h; break; // MOV C,H + case 0x4D: c->c = c->l; break; // MOV C,L + case 0x4E: c->c = i8080_rb(c, i8080_get_hl(c)); break; // MOV C,M + + case 0x57: c->d = c->a; break; // MOV D,A + case 0x50: c->d = c->b; break; // MOV D,B + case 0x51: c->d = c->c; break; // MOV D,C + case 0x52: c->d = c->d; break; // MOV D,D + case 0x53: c->d = c->e; break; // MOV D,E + case 0x54: c->d = c->h; break; // MOV D,H + case 0x55: c->d = c->l; break; // MOV D,L + case 0x56: c->d = i8080_rb(c, i8080_get_hl(c)); break; // MOV D,M + + case 0x5F: c->e = c->a; break; // MOV E,A + case 0x58: c->e = c->b; break; // MOV E,B + case 0x59: c->e = c->c; break; // MOV E,C + case 0x5A: c->e = c->d; break; // MOV E,D + case 0x5B: c->e = c->e; break; // MOV E,E + case 0x5C: c->e = c->h; break; // MOV E,H + case 0x5D: c->e = c->l; break; // MOV E,L + case 0x5E: c->e = i8080_rb(c, i8080_get_hl(c)); break; // MOV E,M + + case 0x67: c->h = c->a; break; // MOV H,A + case 0x60: c->h = c->b; break; // MOV H,B + case 0x61: c->h = c->c; break; // MOV H,C + case 0x62: c->h = c->d; break; // MOV H,D + case 0x63: c->h = c->e; break; // MOV H,E + case 0x64: c->h = c->h; break; // MOV H,H + case 0x65: c->h = c->l; break; // MOV H,L + case 0x66: c->h = i8080_rb(c, i8080_get_hl(c)); break; // MOV H,M + + case 0x6F: c->l = c->a; break; // MOV L,A + case 0x68: c->l = c->b; break; // MOV L,B + case 0x69: c->l = c->c; break; // MOV L,C + case 0x6A: c->l = c->d; break; // MOV L,D + case 0x6B: c->l = c->e; break; // MOV L,E + case 0x6C: c->l = c->h; break; // MOV L,H + case 0x6D: c->l = c->l; break; // MOV L,L + case 0x6E: c->l = i8080_rb(c, i8080_get_hl(c)); break; // MOV L,M + + case 0x77: i8080_wb(c, i8080_get_hl(c), c->a); break; // MOV M,A + case 0x70: i8080_wb(c, i8080_get_hl(c), c->b); break; // MOV M,B + case 0x71: i8080_wb(c, i8080_get_hl(c), c->c); break; // MOV M,C + case 0x72: i8080_wb(c, i8080_get_hl(c), c->d); break; // MOV M,D + case 0x73: i8080_wb(c, i8080_get_hl(c), c->e); break; // MOV M,E + case 0x74: i8080_wb(c, i8080_get_hl(c), c->h); break; // MOV M,H + case 0x75: i8080_wb(c, i8080_get_hl(c), c->l); break; // MOV M,L + + case 0x3E: c->a = i8080_next_byte(c); break; // MVI A,byte + case 0x06: c->b = i8080_next_byte(c); break; // MVI B,byte + case 0x0E: c->c = i8080_next_byte(c); break; // MVI C,byte + case 0x16: c->d = i8080_next_byte(c); break; // MVI D,byte + case 0x1E: c->e = i8080_next_byte(c); break; // MVI E,byte + case 0x26: c->h = i8080_next_byte(c); break; // MVI H,byte + case 0x2E: c->l = i8080_next_byte(c); break; // MVI L,byte + case 0x36: + i8080_wb(c, i8080_get_hl(c), i8080_next_byte(c)); + break; // MVI M,byte + + case 0x02: i8080_wb(c, i8080_get_bc(c), c->a); break; // STAX B + case 0x12: i8080_wb(c, i8080_get_de(c), c->a); break; // STAX D + case 0x32: i8080_wb(c, i8080_next_word(c), c->a); break; // STA word + + case 0x01: i8080_set_bc(c, i8080_next_word(c)); break; // LXI B,word + case 0x11: i8080_set_de(c, i8080_next_word(c)); break; // LXI D,word + case 0x21: i8080_set_hl(c, i8080_next_word(c)); break; // LXI H,word + case 0x31: c->sp = i8080_next_word(c); break; // LXI SP,word + case 0x2A: i8080_set_hl(c, i8080_rw(c, i8080_next_word(c))); break; // LHLD + case 0x22: i8080_ww(c, i8080_next_word(c), i8080_get_hl(c)); break; // SHLD + case 0xF9: c->sp = i8080_get_hl(c); break; // SPHL + + case 0xEB: i8080_xchg(c); break; // XCHG + case 0xE3: i8080_xthl(c); break; // XTHL + + case 0x87: i8080_add(c, &c->a, c->a, 0); break; // ADD A + case 0x80: i8080_add(c, &c->a, c->b, 0); break; // ADD B + case 0x81: i8080_add(c, &c->a, c->c, 0); break; // ADD C + case 0x82: i8080_add(c, &c->a, c->d, 0); break; // ADD D + case 0x83: i8080_add(c, &c->a, c->e, 0); break; // ADD E + case 0x84: i8080_add(c, &c->a, c->h, 0); break; // ADD H + case 0x85: i8080_add(c, &c->a, c->l, 0); break; // ADD L + case 0x86: + i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0); + break; // ADD M + case 0xC6: i8080_add(c, &c->a, i8080_next_byte(c), 0); break; // ADI byte + + case 0x8F: i8080_add(c, &c->a, c->a, c->cf); break; // ADC A + case 0x88: i8080_add(c, &c->a, c->b, c->cf); break; // ADC B + case 0x89: i8080_add(c, &c->a, c->c, c->cf); break; // ADC C + case 0x8A: i8080_add(c, &c->a, c->d, c->cf); break; // ADC D + case 0x8B: i8080_add(c, &c->a, c->e, c->cf); break; // ADC E + case 0x8C: i8080_add(c, &c->a, c->h, c->cf); break; // ADC H + case 0x8D: i8080_add(c, &c->a, c->l, c->cf); break; // ADC L + case 0x8E: + i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf); + break; // ADC M + case 0xCE: i8080_add(c, &c->a, i8080_next_byte(c), c->cf); break; // ACI byte + + case 0x97: i8080_sub(c, &c->a, c->a, 0); break; // SUB A + case 0x90: i8080_sub(c, &c->a, c->b, 0); break; // SUB B + case 0x91: i8080_sub(c, &c->a, c->c, 0); break; // SUB C + case 0x92: i8080_sub(c, &c->a, c->d, 0); break; // SUB D + case 0x93: i8080_sub(c, &c->a, c->e, 0); break; // SUB E + case 0x94: i8080_sub(c, &c->a, c->h, 0); break; // SUB H + case 0x95: i8080_sub(c, &c->a, c->l, 0); break; // SUB L + case 0x96: + i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0); + break; // SUB M + case 0xD6: i8080_sub(c, &c->a, i8080_next_byte(c), 0); break; // SUI byte + + case 0x9F: i8080_sub(c, &c->a, c->a, c->cf); break; // SBB A + case 0x98: i8080_sub(c, &c->a, c->b, c->cf); break; // SBB B + case 0x99: i8080_sub(c, &c->a, c->c, c->cf); break; // SBB C + case 0x9A: i8080_sub(c, &c->a, c->d, c->cf); break; // SBB D + case 0x9B: i8080_sub(c, &c->a, c->e, c->cf); break; // SBB E + case 0x9C: i8080_sub(c, &c->a, c->h, c->cf); break; // SBB H + case 0x9D: i8080_sub(c, &c->a, c->l, c->cf); break; // SBB L + case 0x9E: + i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf); + break; // SBB M + case 0xDE: i8080_sub(c, &c->a, i8080_next_byte(c), c->cf); break; // SBI byte + + case 0x09: i8080_dad(c, i8080_get_bc(c)); break; // DAD B + case 0x19: i8080_dad(c, i8080_get_de(c)); break; // DAD D + case 0x29: i8080_dad(c, i8080_get_hl(c)); break; // DAD H + case 0x39: i8080_dad(c, c->sp); break; // DAD SP + + case 0xF3: c->iff = 0; break; // DI + case 0xFB: + c->iff = 1; + c->interrupt_delay = 1; + break; // EI + case 0x00: break; // NOP + case 0x76: c->halted = 1; break; // HLT + + case 0x3C: c->a = i8080_inr(c, c->a); break; // INR A + case 0x04: c->b = i8080_inr(c, c->b); break; // INR B + case 0x0C: c->c = i8080_inr(c, c->c); break; // INR C + case 0x14: c->d = i8080_inr(c, c->d); break; // INR D + case 0x1C: c->e = i8080_inr(c, c->e); break; // INR E + case 0x24: c->h = i8080_inr(c, c->h); break; // INR H + case 0x2C: c->l = i8080_inr(c, c->l); break; // INR L + case 0x34: + i8080_wb(c, i8080_get_hl(c), i8080_inr(c, i8080_rb(c, i8080_get_hl(c)))); + break; // INR M + + case 0x3D: c->a = i8080_dcr(c, c->a); break; // DCR A + case 0x05: c->b = i8080_dcr(c, c->b); break; // DCR B + case 0x0D: c->c = i8080_dcr(c, c->c); break; // DCR C + case 0x15: c->d = i8080_dcr(c, c->d); break; // DCR D + case 0x1D: c->e = i8080_dcr(c, c->e); break; // DCR E + case 0x25: c->h = i8080_dcr(c, c->h); break; // DCR H + case 0x2D: c->l = i8080_dcr(c, c->l); break; // DCR L + case 0x35: + i8080_wb(c, i8080_get_hl(c), i8080_dcr(c, i8080_rb(c, i8080_get_hl(c)))); + break; // DCR M + + case 0x03: i8080_set_bc(c, i8080_get_bc(c) + 1); break; // INX B + case 0x13: i8080_set_de(c, i8080_get_de(c) + 1); break; // INX D + case 0x23: i8080_set_hl(c, i8080_get_hl(c) + 1); break; // INX H + case 0x33: c->sp += 1; break; // INX SP + + case 0x0B: i8080_set_bc(c, i8080_get_bc(c) - 1); break; // DCX B + case 0x1B: i8080_set_de(c, i8080_get_de(c) - 1); break; // DCX D + case 0x2B: i8080_set_hl(c, i8080_get_hl(c) - 1); break; // DCX H + case 0x3B: c->sp -= 1; break; // DCX SP + + case 0x27: i8080_daa(c); break; // DAA + case 0x2F: c->a = ~c->a; break; // CMA + case 0x37: c->cf = 1; break; // STC + case 0x3F: c->cf = !c->cf; break; // CMC + + case 0x07: i8080_rlc(c); break; // RLC (rotate left) + case 0x0F: i8080_rrc(c); break; // RRC (rotate right) + case 0x17: i8080_ral(c); break; // RAL + case 0x1F: i8080_rar(c); break; // RAR + + case 0xA7: i8080_ana(c, c->a); break; // ANA A + case 0xA0: i8080_ana(c, c->b); break; // ANA B + case 0xA1: i8080_ana(c, c->c); break; // ANA C + case 0xA2: i8080_ana(c, c->d); break; // ANA D + case 0xA3: i8080_ana(c, c->e); break; // ANA E + case 0xA4: i8080_ana(c, c->h); break; // ANA H + case 0xA5: i8080_ana(c, c->l); break; // ANA L + case 0xA6: i8080_ana(c, i8080_rb(c, i8080_get_hl(c))); break; // ANA M + case 0xE6: i8080_ana(c, i8080_next_byte(c)); break; // ANI byte + + case 0xAF: i8080_xra(c, c->a); break; // XRA A + case 0xA8: i8080_xra(c, c->b); break; // XRA B + case 0xA9: i8080_xra(c, c->c); break; // XRA C + case 0xAA: i8080_xra(c, c->d); break; // XRA D + case 0xAB: i8080_xra(c, c->e); break; // XRA E + case 0xAC: i8080_xra(c, c->h); break; // XRA H + case 0xAD: i8080_xra(c, c->l); break; // XRA L + case 0xAE: i8080_xra(c, i8080_rb(c, i8080_get_hl(c))); break; // XRA M + case 0xEE: i8080_xra(c, i8080_next_byte(c)); break; // XRI byte + + case 0xB7: i8080_ora(c, c->a); break; // ORA A + case 0xB0: i8080_ora(c, c->b); break; // ORA B + case 0xB1: i8080_ora(c, c->c); break; // ORA C + case 0xB2: i8080_ora(c, c->d); break; // ORA D + case 0xB3: i8080_ora(c, c->e); break; // ORA E + case 0xB4: i8080_ora(c, c->h); break; // ORA H + case 0xB5: i8080_ora(c, c->l); break; // ORA L + case 0xB6: i8080_ora(c, i8080_rb(c, i8080_get_hl(c))); break; // ORA M + case 0xF6: i8080_ora(c, i8080_next_byte(c)); break; // ORI byte + + case 0xBF: i8080_cmp(c, c->a); break; // CMP A + case 0xB8: i8080_cmp(c, c->b); break; // CMP B + case 0xB9: i8080_cmp(c, c->c); break; // CMP C + case 0xBA: i8080_cmp(c, c->d); break; // CMP D + case 0xBB: i8080_cmp(c, c->e); break; // CMP E + case 0xBC: i8080_cmp(c, c->h); break; // CMP H + case 0xBD: i8080_cmp(c, c->l); break; // CMP L + case 0xBE: i8080_cmp(c, i8080_rb(c, i8080_get_hl(c))); break; // CMP M + case 0xFE: i8080_cmp(c, i8080_next_byte(c)); break; // CPI byte + + case 0xC3: i8080_jmp(c, i8080_next_word(c)); break; // JMP + case 0xC2: i8080_cond_jmp(c, c->zf == 0); break; // JNZ + case 0xCA: i8080_cond_jmp(c, c->zf == 1); break; // JZ + case 0xD2: i8080_cond_jmp(c, c->cf == 0); break; // JNC + case 0xDA: i8080_cond_jmp(c, c->cf == 1); break; // JC + case 0xE2: i8080_cond_jmp(c, c->pf == 0); break; // JPO + case 0xEA: i8080_cond_jmp(c, c->pf == 1); break; // JPE + case 0xF2: i8080_cond_jmp(c, c->sf == 0); break; // JP + case 0xFA: i8080_cond_jmp(c, c->sf == 1); break; // JM + + case 0xE9: c->pc = i8080_get_hl(c); break; // PCHL + case 0xCD: i8080_call(c, i8080_next_word(c)); break; // CALL + + case 0xC4: i8080_cond_call(c, c->zf == 0); break; // CNZ + case 0xCC: i8080_cond_call(c, c->zf == 1); break; // CZ + case 0xD4: i8080_cond_call(c, c->cf == 0); break; // CNC + case 0xDC: i8080_cond_call(c, c->cf == 1); break; // CC + case 0xE4: i8080_cond_call(c, c->pf == 0); break; // CPO + case 0xEC: i8080_cond_call(c, c->pf == 1); break; // CPE + case 0xF4: i8080_cond_call(c, c->sf == 0); break; // CP + case 0xFC: i8080_cond_call(c, c->sf == 1); break; // CM + + case 0xC9: i8080_ret(c); break; // RET + case 0xC0: i8080_cond_ret(c, c->zf == 0); break; // RNZ + case 0xC8: i8080_cond_ret(c, c->zf == 1); break; // RZ + case 0xD0: i8080_cond_ret(c, c->cf == 0); break; // RNC + case 0xD8: i8080_cond_ret(c, c->cf == 1); break; // RC + case 0xE0: i8080_cond_ret(c, c->pf == 0); break; // RPO + case 0xE8: i8080_cond_ret(c, c->pf == 1); break; // RPE + case 0xF0: i8080_cond_ret(c, c->sf == 0); break; // RP + case 0xF8: i8080_cond_ret(c, c->sf == 1); break; // RM + + case 0xC7: i8080_call(c, 0x00); break; // RST 0 + case 0xCF: i8080_call(c, 0x08); break; // RST 1 + case 0xD7: i8080_call(c, 0x10); break; // RST 2 + case 0xDF: i8080_call(c, 0x18); break; // RST 3 + case 0xE7: i8080_call(c, 0x20); break; // RST 4 + case 0xEF: i8080_call(c, 0x28); break; // RST 5 + case 0xF7: i8080_call(c, 0x30); break; // RST 6 + case 0xFF: i8080_call(c, 0x38); break; // RST 7 + + case 0xC5: i8080_push_stack(c, i8080_get_bc(c)); break; // PUSH B + case 0xD5: i8080_push_stack(c, i8080_get_de(c)); break; // PUSH D + case 0xE5: i8080_push_stack(c, i8080_get_hl(c)); break; // PUSH H + case 0xF5: i8080_push_psw(c); break; // PUSH PSW + case 0xC1: i8080_set_bc(c, i8080_pop_stack(c)); break; // POP B + case 0xD1: i8080_set_de(c, i8080_pop_stack(c)); break; // POP D + case 0xE1: i8080_set_hl(c, i8080_pop_stack(c)); break; // POP H + case 0xF1: i8080_pop_psw(c); break; // POP PSW + + case 0xDB: c->a = c->port_in(c->userdata, i8080_next_byte(c)); break; // IN + case 0xD3: c->port_out(c->userdata, i8080_next_byte(c), c->a); break; // OUT + + case 0x08: + case 0x10: + case 0x18: + case 0x20: + case 0x28: + case 0x30: + case 0x38: break; // undocumented NOPs + + case 0xD9: i8080_ret(c); break; // undocumented RET + + case 0xDD: + case 0xED: + { + if (opcode == 0xED) { + uint8_t data = i8080_next_byte(c); + if (data == 0xED) { + interrupt_808x(i8080_next_byte(c)); + break; + } else if (data == 0xFD) { + retem_i8080(); + break; + } + else { + i8080_call(c, (i8080_next_byte(c) << 8) | data); break; + } + } + } + case 0xFD: i8080_call(c, i8080_next_word(c)); break; // undocumented CALLs + + case 0xCB: i8080_jmp(c, i8080_next_word(c)); break; // undocumented JMP + } +} + +// initialises the emulator with default values +void i8080_init(i8080* const c) { + c->read_byte = NULL; + c->write_byte = NULL; + c->port_in = NULL; + c->port_out = NULL; + c->userdata = NULL; + + c->cyc = 0; + + c->pc = 0; + c->sp = 0; + + c->a = 0; + c->b = 0; + c->c = 0; + c->d = 0; + c->e = 0; + c->h = 0; + c->l = 0; + + c->sf = 0; + c->zf = 0; + c->hf = 0; + c->pf = 0; + c->cf = 0; + c->iff = 0; + + c->halted = 0; + c->interrupt_pending = 0; + c->interrupt_vector = 0; + c->interrupt_delay = 0; +} + +// executes one instruction +void i8080_step(i8080* const c) { + // interrupt processing: if an interrupt is pending and IFF is set, + // we execute the interrupt vector passed by the user. + if (c->interrupt_pending && c->iff && c->interrupt_delay == 0) { + c->interrupt_pending = 0; + c->iff = 0; + c->halted = 0; + + i8080_execute(c, c->interrupt_vector); + } else if (!c->halted) { + i8080_execute(c, i8080_next_byte(c)); + } +} + +// asks for an interrupt to be serviced +void i8080_interrupt(i8080* const c, uint8_t opcode) { + c->interrupt_pending = 1; + c->interrupt_vector = opcode; +} + +// outputs a debug trace of the emulator state to the standard output, +// including registers and flags +void i8080_debug_output(i8080* const c, bool print_disassembly) { + uint8_t f = 0; + f |= c->sf << 7; + f |= c->zf << 6; + f |= c->hf << 4; + f |= c->pf << 2; + f |= 1 << 1; // bit 1 is always 1 + f |= c->cf << 0; + + printf("PC: %04X, AF: %04X, BC: %04X, DE: %04X, HL: %04X, SP: %04X, CYC: %lu", + c->pc, c->a << 8 | f, i8080_get_bc(c), i8080_get_de(c), i8080_get_hl(c), + c->sp, c->cyc); + + printf("\t(%02X %02X %02X %02X)", i8080_rb(c, c->pc), i8080_rb(c, c->pc + 1), + i8080_rb(c, c->pc + 2), i8080_rb(c, c->pc + 3)); + + if (print_disassembly) { + printf(" - %s", DISASSEMBLE_TABLE[i8080_rb(c, c->pc)]); + } + + printf("\n"); +} + +#undef SET_ZSP diff --git a/src/cpu/i8080.h b/src/cpu/i8080.h new file mode 100644 index 000000000..43406e43e --- /dev/null +++ b/src/cpu/i8080.h @@ -0,0 +1,35 @@ +#ifndef I8080_I8080_H_ +#define I8080_I8080_H_ + +#include +#include +#include + +typedef struct i8080 { + // memory + io interface + uint8_t (*read_byte)(void*, uint16_t); // user function to read from memory + void (*write_byte)(void*, uint16_t, uint8_t); // same for writing to memory + uint8_t (*read_byte_seg)(void*, uint16_t); // user function to read from memory (Code segment) + uint8_t (*port_in)(void*, uint8_t); // user function to read from port + void (*port_out)(void*, uint8_t, uint8_t); // same for writing to port + void* userdata; // user custom pointer + + unsigned long cyc; // cycle count + + uint16_t pc, sp; // program counter, stack pointer + uint8_t a, b, c, d, e, h, l; // registers + // flags: sign, zero, half-carry, parity, carry, interrupt flip-flop + bool sf : 1, zf : 1, hf : 1, pf : 1, cf : 1, iff : 1; + bool halted : 1; + + bool interrupt_pending : 1; + uint8_t interrupt_vector; + uint8_t interrupt_delay; +} i8080; + +void i8080_init(i8080* const c); +void i8080_step(i8080* const c); +void i8080_interrupt(i8080* const c, uint8_t opcode); +void i8080_debug_output(i8080* const c, bool print_disassembly); + +#endif // I8080_I8080_H_ diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h deleted file mode 100644 index 9a25b5d1b..000000000 --- a/src/include/86box/i8080.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - * - * 8080 CPU emulation (header). - * - * - * - * Authors: Cacodemon345 - * - * Copyright 2022 Cacodemon345 - */ - -#include - -typedef struct i8080 { - union { - uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */ - struct { - uint8_t a; - uint8_t flags; - }; - }; - union { - uint16_t bc; - struct { - uint8_t b; - uint8_t c; - }; - }; - union { - uint16_t de; - struct { - uint8_t d; - uint8_t e; - }; - }; - union { - uint16_t hl; - struct { - uint8_t h; - uint8_t l; - }; - }; - uint16_t pc; - uint16_t sp; - uint16_t oldpc; - uint16_t ei; - uint32_t pmembase; - uint32_t dmembase; /* Base from where i8080 starts. */ - uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */ - uint16_t *cpu_flags; - void (*writemembyte)(uint32_t, uint8_t); - uint8_t (*readmembyte)(uint32_t); - void (*startclock)(void); - void (*endclock)(void); - void (*checkinterrupts)(void); - uint8_t (*fetchinstruction)(void *); -} i8080; - -#define C_FLAG_I8080 (1 << 0) -#define P_FLAG_I8080 (1 << 2) -#define AC_FLAG_I8080 (1 << 4) -#define Z_FLAG_I8080 (1 << 6) -#define S_FLAG_I8080 (1 << 7) From 2b107725bdc9a30f94d4af0b55483c37047744aa Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 20:17:13 +0600 Subject: [PATCH 07/32] Custom NMI handling for i8080 emulation --- src/cpu/808x.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 4ce1fa3b9..c07e583ae 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1179,6 +1179,11 @@ custom_nmi(void) uint16_t new_cs, new_ip; uint16_t tempf; + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + pclog("NMI# (CUTSOM)\n"); + } + cpu_state.eaaddr = 0x0002; old_cs = CS; access(5, 16); @@ -1196,6 +1201,8 @@ custom_nmi(void) tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; From 929a9fb25e4a6ce86dfa81305e63e4267545d444 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 26 Mar 2025 19:30:21 +0500 Subject: [PATCH 08/32] Network settings page redesign Co-Authored-By: cold-brewed <47337035+cold-brewed@users.noreply.github.com> --- src/qt/qt_settingsnetwork.cpp | 61 +++- src/qt/qt_settingsnetwork.ui | 606 ++++++++++++++++++---------------- 2 files changed, 369 insertions(+), 298 deletions(-) diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 2aa3705fd..a0acd7a3f 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -35,25 +35,58 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) for (int i = 0; i < NET_CARD_MAX; ++i) { auto *nic_cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); auto *net_type_cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + + auto *intf_label = findChild(QString("interfaceLabel%1").arg(i + 1)); auto *intf_cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + auto *conf_btn = findChild(QString("pushButtonConf%1").arg(i + 1)); +// auto *net_type_conf_btn = findChild(QString("pushButtonNetTypeConf%1").arg(i + 1)); + + auto *vde_socket_label = findChild(QString("socketVDELabel%1").arg(i + 1)); auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); - int netType = net_type_cbox->currentData().toInt(); - bool adaptersEnabled = netType == NET_TYPE_NONE - || netType == NET_TYPE_SLIRP - || netType == NET_TYPE_VDE - || (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0); + auto *option_list_label = findChild(QString("optionListLabel%1").arg(i + 1)); + auto *option_list_line = findChild(QString("optionListLine%1").arg(i + 1)); intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP); - nic_cbox->setEnabled(adaptersEnabled); - int netCard = nic_cbox->currentData().toInt(); - if ((i == 0) && (netCard == NET_INTERNAL)) - conf_btn->setEnabled(adaptersEnabled && machine_has_flags(machineId, MACHINE_NIC) && - device_has_config(machine_get_net_device(machineId))); - else - conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt())); - socket_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_VDE); + conf_btn->setEnabled(network_card_has_config(nic_cbox->currentData().toInt())); +// net_type_conf_btn->setEnabled(network_type_has_config(netType)); + + // Option list label and line + option_list_label->setVisible(false); + option_list_line->setVisible(false); + + + // VDE + vde_socket_label->setVisible(false); + socket_line->setVisible(false); + + // PCAP + intf_cbox->setVisible(false); + intf_label->setVisible(false); + + // Don't enable anything unless there's a nic selected + if(nic_cbox->currentData().toInt() != 0) { + // Then only enable as needed based on network type + switch (net_type_cbox->currentData().toInt()) { + case NET_TYPE_VDE: + // option_list_label->setText("VDE Options"); + option_list_label->setVisible(true); + option_list_line->setVisible(true); + + vde_socket_label->setVisible(true); + socket_line->setVisible(true); + break; + case NET_TYPE_PCAP: + // option_list_label->setText("PCAP Options"); + option_list_label->setVisible(true); + option_list_line->setVisible(true); + + intf_cbox->setVisible(true); + intf_label->setVisible(true); + break; + } + } } } @@ -154,7 +187,7 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) } model->removeRows(0, removeRows); - cbox->setCurrentIndex(net_cards_conf[i].net_type); + cbox->setCurrentIndex(cbox->findData(net_cards_conf[i].net_type)); selectedRow = 0; diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index 8f1eb5a79..741b60648 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -36,20 +36,7 @@ Network Card #1 - - - - - 0 - 0 - - - - Mode - - - - + 30 @@ -63,32 +50,6 @@ - - - - 0 - 0 - - - - Interface - - - - - - - 30 - - - - 0 - 0 - - - - - @@ -101,23 +62,40 @@ - - - - 30 + + + + Qt::Vertical + + + 20 + 40 + + + + + + - + 0 0 - - QComboBox::AdjustToContents + + Mode - + + + + Qt::Horizontal + + + + @@ -130,21 +108,74 @@ + + + + Options + + + - + + + + 0 + 0 + + + + Interface + + + + + VDE Socket - + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 30 + + + + 127 - + + + + + 0 + 0 + + + + + + + + + Network Card #2 + + + Qt::Vertical @@ -157,13 +188,26 @@ - - - - - Network Card #2 - - + + + + + 0 + 0 + + + + Interface + + + + + + + Options + + + @@ -177,7 +221,7 @@ - + 30 @@ -190,33 +234,21 @@ - - - - - 0 - 0 - - + + - Interface + VDE Socket - - - - 30 - - - - 0 - 0 - + + + + Qt::Horizontal - + @@ -229,7 +261,20 @@ - + + + + + 0 + 0 + + + + Configure + + + + 30 @@ -245,40 +290,19 @@ - - - - Configure + + + + + + + + 0 + 0 + - - - - VDE Socket - - - - - - - 127 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -286,6 +310,69 @@ Network Card #3 + + + + 30 + + + + 0 + 0 + + + + + + + + VDE Socket + + + + + + + Options + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 30 + + + + + + + + 0 + 0 + + + + Interface + + + + + + + Qt::Horizontal + + + @@ -299,75 +386,7 @@ - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Interface - - - - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Adapter - - - - - - - 30 - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - - + @@ -380,21 +399,33 @@ - - + + + + + 0 + 0 + + - VDE Socket + Adapter - - - - 127 + + + + + + + + 0 + 0 + - + Qt::Vertical @@ -414,6 +445,13 @@ Network Card #4 + + + + Options + + + @@ -427,102 +465,7 @@ - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Interface - - - - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Adapter - - - - - - - 30 - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - - - - - - 0 - 0 - - - - Configure - - - - - - - 127 - - - - - - - VDE Socket - - - - + Qt::Vertical @@ -535,6 +478,101 @@ + + + + VDE Socket + + + + + + + + 0 + 0 + + + + Adapter + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Interface + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 30 + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Configure + + + + + + + + + + + 0 + 0 + + + + From ad4e90e345308cdd186e3e5ce368aa11f1d41d0c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 23:01:09 +0600 Subject: [PATCH 09/32] Finally fix RETEM --- src/cpu/808x.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index c07e583ae..ac23cd99a 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1158,11 +1158,20 @@ retem_i8080(void) { sync_from_i8080(); - cpu_state.pc = pop(); - CS = pop(); - cpu_state.flags = pop() | MD_FLAG; + prefetching = 0; + pfq_clear(); + + set_ip(pop()); + load_cs(pop()); + cpu_state.flags = pop(); + + emulated_processor.iff = !!(cpu_state.flags & I_FLAG); cpu_md_write_disable = 1; + + noint = 1; + nmi_enable = 1; + pclog("RETEM mode\n"); } @@ -3298,7 +3307,7 @@ execx86(int cycs) noint = 1; nmi_enable = 1; if (is_nec && !(cpu_state.flags & MD_FLAG)) - sync_to_i8080(); + sync_to_i8080(); break; case 0xD0: From abbae5efd2b1732ceefb7af11effa757bfe5f034 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 23:18:36 +0600 Subject: [PATCH 10/32] Cleanups --- src/cpu/808x.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index ac23cd99a..e98b7de3d 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -229,6 +229,8 @@ sync_from_i8080(void) void sync_to_i8080(void) { + if (!is_nec) + return; emulated_processor.a = AL; emulated_processor.h = BH; emulated_processor.l = BL; @@ -1085,7 +1087,7 @@ interrupt(uint16_t addr) if (!(cpu_state.flags & MD_FLAG) && is_nec) { sync_from_i8080(); - pclog("CALLN/INT#/NMI#\n"); + x808x_log("CALLN/INT#/NMI#\n"); } addr <<= 2; @@ -1150,7 +1152,7 @@ interrupt_brkem(uint16_t addr) access(41, 16); push(&old_ip); sync_to_i8080(); - pclog("BRKEM mode\n"); + x808x_log("BRKEM mode\n"); } void @@ -1172,7 +1174,7 @@ retem_i8080(void) noint = 1; nmi_enable = 1; - pclog("RETEM mode\n"); + x808x_log("RETEM mode\n"); } void From 209b29a2390e343a31fe2890fa9b4ef3616e3ad2 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Mar 2025 00:55:33 +0900 Subject: [PATCH 11/32] PS55DA2: cleanup, change func scope remove unused variables, change funcs declaration scope, reformat debug code --- src/video/vid_ps55da2.c | 172 +++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 91 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index af8beddb9..158629226 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -29,7 +29,6 @@ #include #include #include -#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> @@ -40,7 +39,6 @@ #include <86box/mca.h> #include <86box/rom.h> #include <86box/plat.h> -#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_ps55da2.h> #include <86box/vid_svga.h> @@ -256,8 +254,9 @@ #endif #ifdef ENABLE_DA2_LOG +// # define ENABLE_DA2_DEBUGIO 1 // # define ENABLE_DA2_DEBUGBLT 1 -# define ENABLE_DA2_DEBUGVRAM 1 +// # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; @@ -276,6 +275,11 @@ da2_log(const char *fmt, ...) #else # define da2_log(fmt, ...) #endif +#ifdef ENABLE_DA2_DEBUGIO +# define da2_iolog da2_log +#else +# define da2_iolog(fmt, ...) +#endif #ifdef ENABLE_DA2_DEBUGBLT # define da2_bltlog da2_log #else @@ -302,9 +306,6 @@ typedef struct da2_t { int fctladdr; int crtcaddr; - uint32_t decode_mask; - uint32_t vram_max; - uint32_t gdcla[8]; uint32_t gdcinput[8]; uint32_t gdcsrc[8]; @@ -317,13 +318,8 @@ typedef struct da2_t { uint8_t plane_mask; - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; + int writemode, readplane; uint8_t planemask; - uint32_t charseta, charsetb; uint8_t egapal[16]; uint32_t pallook[512]; @@ -357,13 +353,9 @@ typedef struct da2_t { /* Attribute Buffer E0000-E0FFFh (4 KB) */ uint8_t *cram; - /* (cram size - 1) >> 3 = 0xFFF */ - // uint32_t cram_display_mask; /* APA Buffer A0000-BFFFFh (128 KB) */ uint8_t *vram; - /* xxh */ uint8_t *changedvram; - /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; int fullchange; @@ -374,7 +366,6 @@ typedef struct da2_t { card should not attempt to display anything */ int override; - /* end VGA compatible regs*/ struct { int enable; @@ -431,13 +422,13 @@ typedef struct da2_t { int old_pos2; } da2_t; -void da2_recalctimings(da2_t *da2); -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); -void da2_bitblt_exec(void *p); -void da2_updatevidselector(da2_t *da2); -void da2_reset_ioctl(da2_t *da2); -static void da2_reset(void *priv); -uint16_t rightRotate(uint16_t data, uint8_t count); +static void da2_recalctimings(da2_t *da2); +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); +static void da2_bitblt_exec(void *p); +static void da2_updatevidselector(da2_t *da2); +static void da2_reset_ioctl(da2_t *da2); +static void da2_reset(void *priv); +static uint16_t rightRotate(uint16_t data, uint8_t count); typedef union { uint32_t d; @@ -449,7 +440,7 @@ typedef struct { } pixel32; /* safety read for internal functions */ -uint32_t +static uint32_t DA2_vram_r(uint32_t addr, da2_t *da2) { if (addr & ~DA2_MASK_VRAM) @@ -457,7 +448,7 @@ DA2_vram_r(uint32_t addr, da2_t *da2) return da2->vram[addr]; } /* safety write for internal functions */ -void +static void DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) { if (addr & ~DA2_MASK_VRAM) @@ -466,7 +457,7 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) return; } /* write pixel data with rop (Note: bitmask must be in big endian) */ -void +static void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) { uint32_t writepx[8]; @@ -516,7 +507,7 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s } } -void +static void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2) { pixel32 srcpx; @@ -554,7 +545,7 @@ Param Desc 33 Size W 35 Size H */ -void +static void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; @@ -568,7 +559,7 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } -void +static void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; @@ -655,7 +646,7 @@ IBMJtoSJIS(uint16_t knj) return knj; } #endif -void +static void da2_bitblt_load(da2_t *da2) { uint32_t value32; @@ -892,7 +883,7 @@ da2_bitblt_load(da2_t *da2) } } } -void +static void da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; @@ -1099,7 +1090,7 @@ da2_bitblt_exec(void *p) break; } } -void +static void da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; @@ -1116,7 +1107,7 @@ da2_bitblt_dopayload(void *priv) } } -void +static void da2_out(uint16_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; @@ -1142,7 +1133,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->dac_pos = 0; break; case 0x3C9: /* Data */ - // da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); + // da2_iolog("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); da2->dac_status = 0; da2->fullchange = changeframecount; switch (da2->dac_pos) { @@ -1171,11 +1162,11 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->ioctladdr = val; break; case LS_DATA: - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); if (da2->ioctladdr > 0xf) return; if (da2->ioctl[da2->ioctladdr & 15] != val) - da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); + da2_iolog("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); oldval = da2->ioctl[da2->ioctladdr]; da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { @@ -1192,15 +1183,15 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->fctladdr = val; break; case LF_DATA: - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); if (da2->fctladdr > 0x1f) return; if (da2->fctl[da2->fctladdr & 0x1f] != val) - da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); + da2_iolog("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) { - da2_log("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); } break; case LC_INDEX: @@ -1210,7 +1201,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) if (da2->crtcaddr > 0x1f) return; if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) - da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); if (!(da2->crtc[da2->crtcaddr] ^ val)) return; switch (da2->crtcaddr) { @@ -1261,7 +1252,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) } break; case LV_PORT: - // da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); if (!da2->attrff) { // da2->attraddr = val & 31; da2->attraddr = val & 0x3f; @@ -1270,14 +1261,14 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->attr_palette_enable = val & 0x20; da2_recalctimings(da2); } - // da2_log("set attraddr: %X\n", da2->attraddr); + // da2_iolog("set attraddr: %X\n", da2->attraddr); } else { if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) da2->fullchange = changeframecount; if (da2->attrc[da2->attraddr & 0x3f] != val) - da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); + da2_iolog("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); da2->attrc[da2->attraddr & 0x3f] = val; - // da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); + // da2_iolog("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) da2->fullchange = changeframecount; if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { @@ -1325,12 +1316,12 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->attrc[da2->attraddr & 0x3f] = val; break; case LG_INDEX: - da2_log("DA2 Out addr %03X val %02X\n", addr, val); + da2_iolog("DA2 Out addr %03X val %02X\n", addr, val); da2->gdcaddr = val; break; case LG_DATA: - // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); - da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_iolog("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + da2_iolog("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; switch (da2->gdcaddr & 0x1f) { case LG_READ_MAP_SELECT: @@ -1350,7 +1341,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LG_COMMAND: break; case LG_SET_RESET_2: - da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + da2_iolog("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); return; } break; @@ -1358,12 +1349,12 @@ da2_out(uint16_t addr, uint16_t val, void *p) // da2->gdcreg[5] = val & 0xff; // break; default: - da2_log("DA2? Out addr %03X val %02X\n", addr, val); + da2_iolog("DA2? Out addr %03X val %02X\n", addr, val); break; } } -uint16_t +static uint16_t da2_in(uint16_t addr, void *p) { da2_t *da2 = (da2_t *) p; @@ -1431,17 +1422,17 @@ da2_in(uint16_t addr, void *p) // if (da2->bitblt.indata) /* for OS/2 J1.3 command prompt scrolling */ // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { - // da2_log("exec:%x\n", da2->bitblt.exec); + // da2_iolog("exec:%x\n", da2->bitblt.exec); temp |= 0x01; /* wait (bit 3 + bit 0) ? need verify */ // if (!da2->bitblt.timer.enabled) //{ - // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); + // da2_iolog("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } if (da2->bitblt.indata) temp |= 0x08; #ifdef ENABLE_DA2_DEBUGMONWAIT - da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); + da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); #endif } break; @@ -1474,7 +1465,7 @@ da2_in(uint16_t addr, void *p) temp = da2->cgastat; } else temp = da2->attrc[da2->attraddr]; - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ break; case LG_INDEX: @@ -1482,10 +1473,10 @@ da2_in(uint16_t addr, void *p) break; case LG_DATA: temp = da2->gdcreg[da2->gdcaddr & 0x1f]; - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); break; } - // da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } /* @@ -1499,11 +1490,11 @@ da2_in(uint16_t addr, void *p) * out b(idx), in b, in b(data) * out b(idx), in w(data) */ -void +static void da2_outb(uint16_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; - // da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + // da2_iolog("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); da2->inflipflop = 0; switch (addr) { case LS_DATA: @@ -1533,7 +1524,7 @@ da2_outb(uint16_t addr, uint8_t val, void *p) void da2_outw(uint16_t addr, uint16_t val, void *p) { - da2_log("DA2 Outw addr %03X val %04X\n", addr, val); + da2_iolog("DA2 Outw addr %03X val %04X\n", addr, val); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -1553,8 +1544,8 @@ da2_outw(uint16_t addr, uint16_t val, void *p) da2->outflipflop = 0; break; case 0x3EC: - // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_log(" "); + // da2_iolog("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_iolog(" "); // val = rightRotate(val, 8); // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); @@ -1580,12 +1571,12 @@ da2_outw(uint16_t addr, uint16_t val, void *p) break; case AC_REG: /* no register is revealed */ - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); da2->reg3ee[val & 0x0f] = val >> 8; break; } } -uint8_t +static uint8_t da2_inb(uint16_t addr, void *p) { uint8_t temp; @@ -1615,10 +1606,10 @@ da2_inb(uint16_t addr, void *p) da2->inflipflop = 0; break; } - // da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -uint16_t +static uint16_t da2_inw(uint16_t addr, void *p) { uint16_t temp; @@ -1626,11 +1617,11 @@ da2_inw(uint16_t addr, void *p) da2->inflipflop = 0; da2->outflipflop = 0; temp = da2_in(addr, da2); - da2_log("DA2 Inw addr %03X val %04X\n", addr, temp); + da2_iolog("DA2 Inw addr %03X val %04X\n", addr, temp); return temp; } /* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */ -uint8_t +static uint8_t da2_in_ISR(uint16_t addr, void *p) { da2_t *da2 = (da2_t *) p; @@ -1642,15 +1633,15 @@ da2_in_ISR(uint16_t addr, void *p) da2->cgastat ^= 0x30; temp = da2->cgastat; } - // da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -void +static void da2_out_ISR(uint16_t addr, uint8_t val, void *p) { // da2_t* da2 = (da2_t*)p; - da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); } /* @@ -1754,7 +1745,7 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. */ /* Get character line pattern from jfont rom or gaiji volatile memory */ -uint32_t +static uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void *p) { da2_t *da2 = (da2_t *) p; @@ -1792,14 +1783,14 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *p) } /* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ -uint8_t +static int8_t IRGBtoBGRI(uint8_t attr) { attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1); return attr >>= 4; } /* Get the foreground color from the attribute byte */ -uint8_t +static uint8_t getPS55ForeColor(uint8_t attr, da2_t *da2) { uint8_t foreground = ~attr & 0x08; /* 0000 1000 */ @@ -1811,7 +1802,7 @@ getPS55ForeColor(uint8_t attr, da2_t *da2) return foreground; } -void +static void da2_render_blank(da2_t *da2) { int x, xx; @@ -2062,7 +2053,7 @@ da2_render_textm3(da2_t *da2) } } -void +static void da2_render_color_4bpp(da2_t *da2) { int changed_offset = da2->ma >> 9; @@ -2111,7 +2102,7 @@ da2_render_color_4bpp(da2_t *da2) } } -void +static void da2_render_color_8bpp(da2_t *da2) { int changed_offset = da2->ma >> 9; @@ -2160,7 +2151,7 @@ da2_render_color_8bpp(da2_t *da2) } } -void +static void da2_updatevidselector_tick(void *priv) { da2_t *da2 = (da2_t *) priv; @@ -2176,7 +2167,7 @@ da2_updatevidselector_tick(void *priv) } } -void +static void da2_updatevidselector(da2_t *da2) { timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); @@ -2194,7 +2185,7 @@ da2_updatevidselector(da2_t *da2) 45h(undoc) APA 16 NA A0000h 1040 x 768 color_4bpp 46h(undoc) APA 16 ? A0000h 1040 x 768 color_4bpp */ -void +static void da2_recalctimings(da2_t *da2) { double crtcconst; @@ -2298,8 +2289,7 @@ da2_recalctimings(da2_t *da2) da2->dispofftime = TIMER_USEC; da2_log("da2 horiz total %i display end %i vidclock %f\n", da2->crtc[0], da2->crtc[1], da2->clock); da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); - da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); - + da2_log("da2 dispon %lu dispoff %lu on(us) %f off(us) %f\n",da2->dispontime, da2->dispofftime, (double)da2->dispontime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0, (double)da2->dispofftime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0); // da2_log("da2->render %08X\n", da2->render); } @@ -2334,14 +2324,14 @@ da2_mapping_update(da2_t *da2) } } -uint8_t +static uint8_t da2_mca_read(int port, void *p) { da2_t *da2 = (da2_t *) p; return da2->pos_regs[port & 7]; } -void +static void da2_mca_write(int port, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; @@ -2702,7 +2692,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->fullchange = 2; } } -uint16_t +static uint16_t rightRotate(uint16_t data, uint8_t count) { return (data >> count) | (data << (sizeof(data) * 8 - count)); @@ -2875,7 +2865,7 @@ da2_code_readw(uint32_t addr, void *p) return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); } -void +static void da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) { if (wx != xsize || wy != ysize) { @@ -2894,7 +2884,7 @@ da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) video_bpp = 8; } -void +static void da2_poll(void *priv) { da2_t *da2 = (da2_t *) priv; @@ -3090,7 +3080,7 @@ static uint8_t ps55_palette_color[64][3] = { { 0x3F, 0x15, 0x15 }, { 0x3F, 0x15, 0x3F }, { 0x3F, 0x3F, 0x15 }, { 0x3F, 0x3F, 0x3F } }; -void +static void da2_reset_ioctl(da2_t *da2) { da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ @@ -3204,7 +3194,7 @@ da2_available(void) return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } -void +static void da2_close(void *p) { da2_t *da2 = (da2_t *) p; @@ -3292,7 +3282,7 @@ da2_close(void *p) free(da2); } -void +static void da2_speed_changed(void *p) { da2_t *da2 = (da2_t *) p; @@ -3300,7 +3290,7 @@ da2_speed_changed(void *p) da2_recalctimings(da2); } -void +static void da2_force_redraw(void *p) { da2_t *da2 = (da2_t *) p; From da855e02b4219bdda33325c0caa557ffc4ee2c99 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Mar 2025 01:30:00 +0900 Subject: [PATCH 12/32] PS55DA2: Fix video switcher Fix an issue that the screen is resized repeatedly when booting OS/2. --- src/video/vid_ps55da2.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 158629226..98db5f9fa 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1242,7 +1242,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_VERTICAL_SYNC_START: case LC_V_DISPLAY_ENABLE_END: case LC_START_VERTICAL_BLANK: - case LC_END_VERTICAL_BLANK: + case LC_START_H_DISPLAY_ENAB: + case LC_START_V_DISPLAY_ENAB: case LC_VIEWPORT_PRIORITY: da2->fullchange = changeframecount; da2_recalctimings(da2); @@ -2158,10 +2159,12 @@ da2_updatevidselector_tick(void *priv) if (da2->ioctl[LS_MODE] & 0x02) { /* VGA passthrough mode */ da2->override = 1; + timer_disable(&da2->timer); svga_set_override(da2->mb_vga, 0); da2_log("DA2 selector: VGA\n"); } else { svga_set_override(da2->mb_vga, 1); + timer_enable(&da2->timer); da2->override = 0; da2_log("DA2 selector: DA2\n"); } @@ -2310,12 +2313,10 @@ da2_mapping_update(da2_t *da2) io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); mem_mapping_enable(&da2->cmapping); mem_mapping_enable(&da2->mmio.mapping); - timer_enable(&da2->timer); timer_enable(&da2->bitblt.timer); } else { da2_log("DA2 disable registers\n"); timer_disable(&da2->bitblt.timer); - timer_disable(&da2->timer); mem_mapping_disable(&da2->cmapping); mem_mapping_disable(&da2->mmio.mapping); io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); From 93f3e9f339361dbdecc2fbc0a87c9b7c31e9dd97 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Mar 2025 19:10:20 +0100 Subject: [PATCH 13/32] Keyboard: Actually reset everything in keyboard_init() and call it in pc_reset_hard_init() as well. --- src/device/keyboard.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 58d5a4724..a00968cf7 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -113,7 +113,17 @@ static scconvtbl scconv55_8a[18 + 1] = void keyboard_init(void) { + num_lock = 0; + caps_lock = 0; + scroll_lock = 0; + shift = 0; + memset(recv_key, 0x00, sizeof(recv_key)); + memset(recv_key_ui, 0x00, sizeof(recv_key)); + memset(oldkey, 0x00, sizeof(recv_key)); +#if 0 + memset(key_delay, 0x00, sizeof(recv_key)); +#endif keyboard_scan = 1; scan_table = NULL; From ffd00e4527f56f429b8c826343c0de08f166ef6b Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Mar 2025 19:14:01 +0100 Subject: [PATCH 14/32] Forgot 86box.c. --- src/86box.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/86box.c b/src/86box.c index dbf58a70e..2b6e1ba9f 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1293,6 +1293,8 @@ pc_reset_hard_init(void) * modules that are. */ + keyboard_init(); + /* Reset the IDE and SCSI presences */ other_ide_present = other_scsi_present = 0; From cec630fa756874bdf2ccc4a6fb3b733df2b4ad52 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 03:26:28 +0100 Subject: [PATCH 15/32] JEGA: Use colors based on a photo of the real OKI IF386AX when the LCD is in use to tell it apart more easily, and reset all devices on port 65h reset, fixes Trantor SCSI BIOS not finding any devices after such a reset. --- src/video/vid_jega.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 36cf04077..d8994916f 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -770,6 +770,8 @@ if386_p6x_read(uint16_t port, void *priv) Bit 4: Shutdown? (caused by POST rebooting and POWER OFF command in DOS 3.21) Bit 3: ? */ +static uint32_t lcd_cols[8] = { 0x001024, 0x747d8a, 0x8c96a4, 0xa0abbb, + 0xb1bece, 0xc0cee0, 0xceddf0, 0xdbebff }; static void if386_p6x_write(uint16_t port, uint8_t val, void *priv) { @@ -793,19 +795,31 @@ if386_p6x_write(uint16_t port, uint8_t val, void *priv) } else { /* Monochrome LCD */ for (int c = 0; c < 256; c++) { int cval = 0; +#ifdef SIMPLE_BW if (c & 0x0f) cval = ((c & 0x0e) * 0x10) + 0x1f; pallook64[c] = makecol32(cval, cval, cval); pallook16[c] = makecol32(cval, cval, cval); +#else + if (c & 0x3f) { + cval = (c & 0x10) >> 2; + cval |= (c & 0x06) >> 1; + } + pallook64[c] = lcd_cols[cval]; + cval = 0; + if (c & 0x0f) + cval = (c & 0x0e) >> 1; + pallook16[c] = lcd_cols[cval]; +#endif } } jega_recalctimings(jega); } else if (p65idx == 0x05) { - if (val & 0x10) + if (val & 0x10) { /* Power off (instead this call hardware reset here) */ + device_reset_all(DEVICE_ALL); resetx86(); - /* Actually, power off - we have a function for that! */ - // plat_power_off(); + } } } return; From 8a8ed6004383dbe271f6b7db01c0d29baeaeec11 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 03:29:11 +0100 Subject: [PATCH 16/32] EGA: Send monochrome attributes through the EGA palette lookup like the real hardware also does. --- src/video/vid_ega_render.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index dd393e4b6..261474742 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -181,6 +181,7 @@ ega_render_text(ega_t *ega) p[xx] = ega->mdacols[attr][attrblink][1]; else p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))]; + p[xx] = ega->pallook[ega->egapal[p[xx] & 0x0f]]; } else p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; } @@ -189,9 +190,6 @@ ega_render_text(ega_t *ega) p += charwidth; } ega->ma &= 0x3ffff; - - if (monoattrs) - video_process_8(ega->hdisp + ega->scrollcache, ega->displine); } } From 63222b70db1e8ad5f1d651d6dce8e6c3a511d50b Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 06:16:05 +0100 Subject: [PATCH 17/32] Added the OKIVGA/H-2 (JVGA/H). --- src/include/86box/vid_ega.h | 9 +- src/include/86box/vid_svga.h | 5 + src/include/86box/vid_vga.h | 15 +- src/video/vid_ega.c | 2 +- src/video/vid_jega.c | 354 ++++++++++++++++++++++++----------- src/video/vid_svga.c | 5 +- src/video/vid_table.c | 1 + src/video/vid_vga.c | 45 +++-- 8 files changed, 293 insertions(+), 143 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 5ac5c24e3..0e28820ff 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -144,10 +144,10 @@ typedef struct ega_t { uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr); void (*render)(struct ega_t *svga); - /*If set then another device is driving the monitor output and the EGA - card should not attempt to display anything */ - void (*render_override)(void *priv); - void *priv_parent; + /* If set then another device is driving the monitor output and the EGA + card should not attempt to display anything. */ + void (*render_override)(void *priv); + void * priv_parent; } ega_t; #endif @@ -159,6 +159,7 @@ extern const device_t atiega800p_device; extern const device_t iskra_ega_device; extern const device_t et2000_device; extern const device_t jega_device; +extern const device_t jvga_device; #endif extern int update_overscan; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index afff6e211..068774eac 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -310,6 +310,11 @@ typedef struct svga_t { void * ext8514; void * clock_gen8514; void * xga; + + /* If set then another device is driving the monitor output and the EGA + card should not attempt to display anything. */ + void (*render_override)(void *priv); + void * priv_parent; } svga_t; extern void ibm8514_set_poll(svga_t *svga); diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index 26b5a7f71..54a1d0690 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -25,14 +25,19 @@ typedef struct vga_t { svga_t svga; - rom_t bios_rom; + rom_t bios_rom; } vga_t; -extern void vga_out(uint16_t addr, uint8_t val, void *priv); +extern void vga_out(uint16_t addr, uint8_t val, void *priv); extern uint8_t vga_in(uint16_t addr, void *priv); -void vga_disable(void* p); -void vga_enable(void* p); -int vga_isenabled(void* p); +extern void vga_init(const device_t *info, vga_t *vga, int enabled); + +extern void vga_disable(void* p); +extern void vga_enable(void* p); + +extern int vga_isenabled(void* p); + +extern video_timings_t timing_vga; #endif /*VIDEO_VGA_H*/ diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 16a3552ad..17b3fb593 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -780,7 +780,7 @@ ega_poll(void *priv) ega->y_add *= ega->vres + 1; for (y = 0; y <= ega->vres; y++) { /* Render scanline */ - if(ega->render_override) + if (ega->render_override) ega->render_override(ega->priv_parent); else ega->render(ega); diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index d8994916f..af20444dd 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -34,6 +34,8 @@ #include <86box/device.h> #include <86box/video.h> #include <86box/vid_ega.h> +#include <86box/vid_svga.h> +#include <86box/vid_vga.h> /* JEGA internal registers */ #define RPESL 0x09 /* End Scan Line */ @@ -63,6 +65,8 @@ #define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN" #define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" #define IF386_PATH_VBIOS "roms/machines/if386sx/OKI_IF386SX_VBIOS.bin" +#define JVGA_PATH_BIOS "roms/video/jega/OKI_JVGT(AXVGAH)_BIOS_011993.BIN" +#define JVGA_PATH_FONTDBCS "roms/video/jega/JWPCE.FNT" #define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ #define DBCS16_CHARS 0x2c10 #define DBCS16_FILESIZE (DBCS16_CHARS * 16 * 2) @@ -96,29 +100,31 @@ jega_log(const char *fmt, ...) static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; typedef struct jega_t { - rom_t bios_rom; - ega_t ega; - uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */ - uint8_t regs[0x31]; - uint8_t egapal[16]; - uint8_t attrregs[32]; - uint8_t attraddr; - uint8_t attrff; - uint8_t attr_palette_enable; + rom_t bios_rom; + ega_t ega; + vga_t vga; + uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */ + uint8_t regs[0x31]; + uint8_t egapal[16]; + uint8_t attrregs[32]; + uint8_t attraddr; + uint8_t attrff; + uint8_t attr_palette_enable; uint32_t *pallook; - int con; - int cursoron; - int cursorblink_disable; - int ca; - int font_index; - int sbcsbank_inv; - int attr3_sbcsbank; - int start_scan_lower; - int start_scan_upper; - int start_scan_count; - uint8_t *vram; - uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */ - uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */ + int is_vga; + int con; + int cursoron; + int cursorblink_disable; + int ca; + int font_index; + int sbcsbank_inv; + int attr3_sbcsbank; + int start_scan_lower; + int start_scan_upper; + int start_scan_count; + uint8_t * vram; + uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */ + uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */ } jega_t; static void jega_recalctimings(void *priv); @@ -127,16 +133,16 @@ static void jega_recalctimings(void *priv); #define FONTX_LEN_FN 8 typedef struct { - char id[FONTX_LEN_ID]; - char name[FONTX_LEN_FN]; - unsigned char width; - unsigned char height; - unsigned char type; + char id[FONTX_LEN_ID]; + char name[FONTX_LEN_FN]; + uint8_t width; + uint8_t height; + uint8_t type; } fontx_h; typedef struct { - uint16_t start; - uint16_t end; + uint16_t start; + uint16_t end; } fontx_tbl; extern uint32_t pallook16[256]; @@ -147,22 +153,32 @@ static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr static uint16_t SJIS_to_SEQ(uint16_t sjis) { - uint32_t chr1 = (sjis >> 8) & 0xff; - uint32_t chr2 = sjis & 0xff; - if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2)) return INVALIDACCESS16; - chr1 -= 0x81; - if (chr1 > 0x5E) chr1 -= 0x40; - chr2 -= 0x40; - if (chr2 > 0x3F) chr2--; - chr1 *= 0xBC; - return (chr1 + chr2); + uint32_t chr1 = (sjis >> 8) & 0xff; + uint32_t chr2 = sjis & 0xff; + + if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2)) + return INVALIDACCESS16; + + chr1 -= 0x81; + + if (chr1 > 0x5e) + chr1 -= 0x40; + + chr2 -= 0x40; + + if (chr2 > 0x3f) + chr2--; + + chr1 *= 0xbc; + + return (chr1 + chr2); } static uint8_t dbcs_read(uint16_t sjis, int index, void *priv) { jega_t *jega = (jega_t *) priv; int seq = SJIS_to_SEQ(sjis); - if (seq >= DBCS16_CHARS || index >= 32) + if ((seq >= DBCS16_CHARS) || (index >= 32)) return INVALIDACCESS8; return jega->jfont_dbcs_16[seq * 32 + index]; } @@ -171,7 +187,7 @@ static void dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) { jega_t *jega = (jega_t *) priv; int seq = SJIS_to_SEQ(sjis); - if (seq >= DBCS16_CHARS || index >= 32) + if ((seq >= DBCS16_CHARS) || (index >= 32)) return; jega->jfont_dbcs_16[seq * 32 + index] = val; } @@ -180,38 +196,81 @@ dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) { void jega_render_text(void *priv) { - jega_t *jega = (jega_t *) priv; - if (jega->ega.firstline_draw == 2000) - jega->ega.firstline_draw = jega->ega.displine; - jega->ega.lastline_draw = jega->ega.displine; + jega_t * jega = (jega_t *) priv; +#ifdef USE_DOUBLE_WIDTH_AND_LINE_CHARS + uint8_t * seqregs = jega->is_vga ? jega->vga.svga.seqregs : + jega->ega.seqregs; + uint8_t * attrregs = jega->is_vga ? jega->vga.svga.attrregs : + jega->ega.attrregs; +#endif + uint8_t * crtc = jega->is_vga ? jega->vga.svga.crtc : + jega->ega.crtc; + uint8_t * vram = jega->is_vga ? jega->vga.svga.vram : + jega->ega.vram; + int * firstline_draw = jega->is_vga ? &jega->vga.svga.firstline_draw : + &jega->ega.firstline_draw; + int * lastline_draw = jega->is_vga ? &jega->vga.svga.lastline_draw : + &jega->ega.lastline_draw; + int * displine = jega->is_vga ? &jega->vga.svga.displine : + &jega->ega.displine; + int * fullchange = jega->is_vga ? &jega->vga.svga.fullchange : + &jega->ega.fullchange; + int * blink = jega->is_vga ? &jega->vga.svga.blink : + &jega->ega.blink; + int * x_add = jega->is_vga ? &jega->vga.svga.x_add : + &jega->ega.x_add; + int * y_add = jega->is_vga ? &jega->vga.svga.y_add : + &jega->ega.y_add; + int * sc = jega->is_vga ? &jega->vga.svga.sc : + &jega->ega.sc; + int * hdisp = jega->is_vga ? &jega->vga.svga.hdisp : + &jega->ega.hdisp; + int * scrollcache = jega->is_vga ? &jega->vga.svga.scrollcache : + &jega->ega.scrollcache; + uint32_t *ma = jega->is_vga ? &jega->vga.svga.ma : + &jega->ega.ma; + uint8_t mask = jega->is_vga ? jega->vga.svga.dac_mask : 0xff; - if (jega->ega.fullchange) { - // const bool doublewidth = ((jega->ega.seqregs[1] & 8) != 0); - const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */ - // const bool attrlinechars = (jega->ega.attrregs[0x10] & 4); - const bool crtcreset = ((jega->ega.crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0); - const int charwidth = 8; - const bool blinked = jega->ega.blink & 0x10; - uint32_t *p = &buffer32->line[jega->ega.displine + jega->ega.y_add][jega->ega.x_add]; - bool chr_wide = false; - int sc_wide = jega->ega.sc - jega->start_scan_count; - const bool cursoron = (blinked || jega->cursorblink_disable) - && (jega->ega.sc >= jega->regs[RCCSL]) && (jega->ega.sc <= jega->regs[RCCEL]); - uint32_t chr_first; - uint32_t attr_basic; - int fg; - int bg; + if (*firstline_draw == 2000) + *firstline_draw = *displine; + *lastline_draw = *displine; - for (int x = 0; x < (jega->ega.hdisp + jega->ega.scrollcache); x += charwidth) { - uint32_t addr = jega->ega.remap_func(&jega->ega, jega->ega.ma) & jega->ega.vrammask; + if (*fullchange) { +#ifdef USE_DOUBLE_WIDTH_AND_LINE_CHARS + const bool doublewidth = ((seqregs[1] & 8) != 0); + const bool attrlinechars = (attrregs[0x10] & 4); +#endif + const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */ + const bool crtcreset = ((crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0); + const int charwidth = 8; + const bool blinked = *blink & 0x10; + uint32_t *p = &buffer32->line[*displine + *y_add][*x_add]; + bool chr_wide = false; + int sc_wide = *sc - jega->start_scan_count; + const bool cursoron = (blinked || jega->cursorblink_disable) && + (*sc >= jega->regs[RCCSL]) && (*sc <= jega->regs[RCCEL]); + uint32_t chr_first; + uint32_t attr_basic; + int fg; + int bg; - int drawcursor = ((jega->ega.ma == jega->ca) && cursoron); + for (int x = 0; x < (*hdisp + *scrollcache); x += charwidth) { + uint32_t addr = 0; + + if (jega->is_vga) { + if (!jega->vga.svga.force_old_addr) + addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.ma) & + jega->vga.svga.vram_display_mask; + } else + addr = jega->ega.remap_func(&jega->ega, *ma) & jega->ega.vrammask; + + int drawcursor = ((*ma == jega->ca) && cursoron); uint32_t chr; uint32_t attr; if (!crtcreset) { - chr = jega->ega.vram[addr]; - attr = jega->ega.vram[addr + 1]; + chr = vram[addr]; + attr = vram[addr + 1]; } else chr = attr = 0; if (chr_wide) { @@ -222,13 +281,13 @@ jega_render_text(void *priv) /* Bold | 2x width | 2x height | U/L select | R/L select | - | - | - */ attr_ext = attr; if ((attr_ext & 0x30) == 0x30) - sc_wide = jega->ega.sc - jega->start_scan_lower; /* Set top padding of lower 2x character */ + sc_wide = *sc - jega->start_scan_lower; /* Set top padding of lower 2x character */ else if ((attr_ext & 0x30) == 0x20) - sc_wide = jega->ega.sc - jega->start_scan_upper; /* Set top padding of upper 2x character */ + sc_wide = *sc - jega->start_scan_upper; /* Set top padding of upper 2x character */ else - sc_wide = jega->ega.sc - jega->start_scan_count; + sc_wide = *sc - jega->start_scan_count; } - if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && jega->ega.sc <= jega->regs[RPESL]) { + if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && *sc <= jega->regs[RPESL]) { chr_first <<= 8; chr |= chr_first; /* Vertical wide font (Extended Attribute) */ @@ -269,7 +328,7 @@ jega_render_text(void *priv) if (attr_basic & 0x20) { /* vertical line */ p[0] = fg; } - if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ + if ((*sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ for (int xx = 0; xx < charwidth * 2; xx++) p[xx] = fg; } @@ -298,13 +357,13 @@ jega_render_text(void *priv) /* Parse attribute as EGA */ /* BInt/Blink | BR | BG | BB | Int/Group | R | G | B */ if (drawcursor) { - bg = jega->pallook[jega->egapal[attr & 0x0f]]; - fg = jega->pallook[jega->egapal[attr >> 4]]; + bg = jega->pallook[jega->egapal[attr & 0x0f] & mask]; + fg = jega->pallook[jega->egapal[attr >> 4] & mask]; } else { - fg = jega->pallook[jega->egapal[attr & 0x0f]]; - bg = jega->pallook[jega->egapal[attr >> 4]]; + fg = jega->pallook[jega->egapal[attr & 0x0f] & mask]; + bg = jega->pallook[jega->egapal[attr >> 4] & mask]; if ((attr & 0x80) && attrblink) { - bg = jega->pallook[jega->egapal[(attr >> 4) & 7]]; + bg = jega->pallook[jega->egapal[(attr >> 4) & 7] & mask]; if (blinked) fg = bg; } @@ -325,32 +384,35 @@ jega_render_text(void *priv) // charaddr ^= 0x100; charaddr *= 19; - uint32_t dat = jega->jfont_sbcs_19[charaddr + jega->ega.sc]; + uint32_t dat = jega->jfont_sbcs_19[charaddr + *sc]; for (int xx = 0; xx < charwidth; xx++) p[xx] = (dat & (0x80 >> xx)) ? fg : bg; if (attr_basic & 0x20) { /* vertical line */ p[0] = fg; } - if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ + if ((*sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ for (int xx = 0; xx < charwidth; xx++) p[xx] = fg; } p += charwidth; } } - jega->ega.ma += 4; + *ma += 4; } - jega->ega.ma &= 0x3ffff; + *ma &= 0x3ffff; } } static void jega_out(uint16_t addr, uint8_t val, void *priv) { - jega_t *jega = (jega_t *) priv; - uint16_t chr; + jega_t *jega = (jega_t *) priv; + uint8_t pal4to16[16] = { 0, 7, 0x38, 0x3f, 0, 3, 4, 0x3f, 0, 2, 4, 0x3e, 0, 3, 5, 0x3f }; + uint16_t chr; + // jega_log("JEGA Out %04X %02X(%d) %04X:%04X\n", addr, val, val, cs >> 4, cpu_state.pc); + switch (addr) { case 0x3c0: case 0x3c1: @@ -367,9 +429,19 @@ jega_out(uint16_t addr, uint8_t val, void *priv) jega->attrregs[jega->attraddr & 31] = val; if (jega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { + if (!jega->is_vga) jega->egapal[c] = jega->attrregs[c] & 0x3f; + else if (jega->attrregs[0x10] & 0x80) + jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4); + else if (jega->vga.svga.ati_4color) + jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + else + jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4); } - jega->ega.fullchange = changeframecount; + if (jega->is_vga) + jega->vga.svga.fullchange = changeframecount; + else + jega->ega.fullchange = changeframecount; } } jega->attrff ^= 1; @@ -395,12 +467,17 @@ jega_out(uint16_t addr, uint8_t val, void *priv) switch (jega->regs_index) { case RMOD1: /* if the value is changed */ - // if (jega->regs[jega->regs_index] != val) { - if (val & 0x40) - jega->ega.render_override = NULL; - else - jega->ega.render_override = jega_render_text; - // } + if (jega->is_vga) { + if (val & 0x40) + jega->vga.svga.render_override = NULL; + else + jega->vga.svga.render_override = jega_render_text; + } else { + if (val & 0x40) + jega->ega.render_override = NULL; + else + jega->ega.render_override = jega_render_text; + } break; case RDAGS: switch (val & 0x03) { @@ -470,8 +547,14 @@ jega_out(uint16_t addr, uint8_t val, void *priv) default: break; } - if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */ - ega_out(addr, val, &jega->ega); + + /* Accessing to Slave EGA is redirected to Master in AX-1. */ + if (jega->regs[RMOD1] & 0x0c) { + if (jega->is_vga) + vga_out(addr, val, &jega->vga); + else + ega_out(addr, val, &jega->ega); + } } static uint8_t @@ -480,6 +563,7 @@ jega_in(uint16_t addr, void *priv) jega_t *jega = (jega_t *) priv; uint8_t ret = INVALIDACCESS8; uint16_t chr; + switch (addr) { case 0x3b5: case 0x3d5: @@ -515,8 +599,13 @@ jega_in(uint16_t addr, void *priv) case 0x3da: jega->attrff = 0; default: - if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave is redirected to Master in AX-1. */ - ret = ega_in(addr, &jega->ega); + /* Accessing to Slave is redirected to Master in AX-1. */ + if (jega->regs[RMOD1] & 0x0c) { + if (jega->is_vga) + ret = vga_in(addr, &jega->vga); + else + ret = ega_in(addr, &jega->ega); + } break; } // jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc); @@ -619,19 +708,29 @@ LoadFontxFile(const char *fn, void *priv) } static void -jega_commoninit(void *priv) +jega_commoninit(const device_t *info, void *priv, int vga) { jega_t *jega = (jega_t *) priv; - for (int c = 0; c < 256; c++) { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + jega->is_vga = vga; + if (vga) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); + vga_init(info, &jega->vga, 1); + jega->vga.svga.priv_parent = jega; + jega->pallook = jega->vga.svga.pallook; + } else { + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + } + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); + jega->pallook = pallook64; + ega_init(&jega->ega, 9, 0); + ega_set_type(&jega->ega, EGA_SUPEREGA); + jega->ega.priv_parent = jega; + mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, + ega_read, NULL, NULL, ega_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, &jega->ega); } - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); - jega->pallook = pallook64; - ega_init(&jega->ega, 9, 0); - ega_set_type(&jega->ega, EGA_SUPEREGA); - jega->ega.priv_parent = jega; - mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); /* I/O 3DD and 3DE are used by Oki if386 */ io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); jega->regs[RMOD1] = 0x48; @@ -646,7 +745,21 @@ jega_standalone_init(const device_t *info) memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); LoadFontxFile(JEGA_PATH_FONTDBCS, jega); - jega_commoninit(jega); + jega_commoninit(info, jega, 0); + + return jega; +} + +static void * +jvga_standalone_init(const device_t *info) +{ + jega_t *jega = calloc(1, sizeof(jega_t)); + + rom_init(&jega->bios_rom, JVGA_PATH_BIOS, 0xc0000, 0x8000, 0x7fff, 0, 0); + memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); + LoadFontxFile(JVGA_PATH_FONTDBCS, jega); + + jega_commoninit(info, jega, 1); return jega; } @@ -693,9 +806,15 @@ jega_close(void *priv) } pclog("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); #endif - if (jega->ega.eeprom) - free(jega->ega.eeprom); - free(jega->ega.vram); + + if (jega->is_vga) + svga_close(&jega->vga.svga); + else { + if (jega->ega.eeprom) + free(jega->ega.eeprom); + free(jega->ega.vram); + } + free(jega); } @@ -703,8 +822,13 @@ static void jega_recalctimings(void *priv) { jega_t *jega = (jega_t *) priv; - ega_recalctimings(&jega->ega); + + if (jega->is_vga) + svga_recalctimings(&jega->vga.svga); + else + ega_recalctimings(&jega->ega); } + static void jega_speed_changed(void *priv) { @@ -733,6 +857,20 @@ const device_t jega_device = { .config = NULL }; +const device_t jvga_device = { + .name = "OKIVGA/H-2 (JVGA/H)", + .internal_name = "jvga", + .flags = DEVICE_ISA, + .local = 0, + .init = jvga_standalone_init, + .close = jega_close, + .reset = NULL, + .available = jega_standalone_available, + .speed_changed = jega_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + static uint8_t p65idx = 0; // static uint8_t p3de_idx = 0; static uint8_t p65[6]; @@ -834,7 +972,7 @@ if386jega_init(const device_t *info) memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); LoadFontxFile(JEGA_PATH_FONTDBCS, jega); - jega_commoninit(jega); + jega_commoninit(info, jega, 0); io_sethandler(0x0063, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); io_sethandler(0x0065, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 1fd2460bd..c7a65120f 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1174,7 +1174,10 @@ svga_do_render(svga_t *svga) } if (!svga->override) { - svga->render(svga); + if (svga->render_override) + svga->render_override(svga->priv_parent); + else + svga->render(svga); svga->x_add = (svga->monitor->mon_overscan_x >> 1); svga_render_overscan_left(svga); diff --git a/src/video/vid_table.c b/src/video/vid_table.c index be26d9e18..b90d7c3e4 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -96,6 +96,7 @@ video_cards[] = { { .device = &genius_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &nga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &ogc_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &jvga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &oti037c_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &oti067_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &oti077_device, .flags = VIDEO_FLAG_TYPE_NONE }, diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 97889e007..0a0fbd8e1 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -31,7 +31,8 @@ #include <86box/vid_svga.h> #include <86box/vid_vga.h> -static video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; +video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; + static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; @@ -135,8 +136,23 @@ int vga_isenabled(void* p) return svga->vga_enabled; } +void +vga_init(const device_t *info, vga_t *vga, int enabled) +{ + svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ + NULL, + vga_in, vga_out, + NULL, + NULL); + + vga->svga.bpp = 8; + vga->svga.miscout = 1; + + vga->svga.vga_enabled = enabled; +} + static void * -vga_init(const device_t *info) +vga_standalone_init(const device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -145,16 +161,7 @@ vga_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); - svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); - - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); - - vga->svga.bpp = 8; - vga->svga.miscout = 1; + vga_init(info, vga, 0); return vga; } @@ -171,17 +178,7 @@ ps1vga_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa); - svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); - - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); - - vga->svga.bpp = 8; - vga->svga.miscout = 1; - vga->svga.vga_enabled = 1; + vga_init(info, vga, 1); return vga; } @@ -223,7 +220,7 @@ const device_t vga_device = { .internal_name = "vga", .flags = DEVICE_ISA, .local = 0, - .init = vga_init, + .init = vga_standalone_init, .close = vga_close, .reset = NULL, .available = vga_available, From 47febdf1969b5532ee6be6c321b802e5ff19fd02 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 06:42:11 +0100 Subject: [PATCH 18/32] JVGA: Read CRTC registers from VGA rather than EGA, fixes Wolfenstein 3D. --- src/video/vid_jega.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index af20444dd..745c76e24 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -29,6 +29,7 @@ #include <86box/pic.h> #include <86box/pit.h> #include <86box/plat.h> +#include <86box/plat_fallthrough.h> #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> @@ -592,12 +593,18 @@ jega_in(uint16_t addr, void *priv) break; } jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc); - } else if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */ - ret = ega_in(addr, &jega->ega); + } else if (jega->regs[RMOD1] & 0x0c) { + /* Accessing to Slave EGA is redirected to Master in AX-1. */ + if (jega->is_vga) + ret = vga_in(addr, &jega->vga); + else + ret = ega_in(addr, &jega->ega); + } break; case 0x3ba: case 0x3da: jega->attrff = 0; + fallthrough; default: /* Accessing to Slave is redirected to Master in AX-1. */ if (jega->regs[RMOD1] & 0x0c) { From 8f6f21b57e14b370a7e8cae4cb5930d2efe6ea11 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 06:54:45 +0100 Subject: [PATCH 19/32] IBM VGA: Re-add the forgotten (S)VGA I/O handlers. --- src/video/vid_vga.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 0a0fbd8e1..8289fd4cb 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -154,8 +154,7 @@ vga_init(const device_t *info, vga_t *vga, int enabled) static void * vga_standalone_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *vga = calloc(1, sizeof(vga_t)); rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); @@ -163,6 +162,8 @@ vga_standalone_init(const device_t *info) vga_init(info, vga, 0); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + return vga; } @@ -170,8 +171,7 @@ vga_standalone_init(const device_t *info) void * ps1vga_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *vga = calloc(1, sizeof(vga_t)); if (info->flags & DEVICE_MCA) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca); @@ -180,6 +180,8 @@ ps1vga_init(const device_t *info) vga_init(info, vga, 1); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + return vga; } From 6366ff758082d16430bbbf5e81d9845ba8270985 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 08:09:51 +0100 Subject: [PATCH 20/32] JEGA: Fix two uninitialized variables. --- src/video/vid_jega.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 745c76e24..3d1cfe476 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -250,9 +250,9 @@ jega_render_text(void *priv) int sc_wide = *sc - jega->start_scan_count; const bool cursoron = (blinked || jega->cursorblink_disable) && (*sc >= jega->regs[RCCSL]) && (*sc <= jega->regs[RCCEL]); + uint32_t attr_basic = 0; uint32_t chr_first; - uint32_t attr_basic; - int fg; + int fg = 0; int bg; for (int x = 0; x < (*hdisp + *scrollcache); x += charwidth) { From 94cf5d59a2b919cfb5e916e8d715708ff138f54e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Mar 2025 22:35:56 +0600 Subject: [PATCH 21/32] host_x86_MOV8_REG_ABS: Avoid more fatals --- src/codegen_new/codegen_backend_x86-64_ops.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index c70112c86..fc6c1b492 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -723,7 +723,11 @@ host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ codegen_addlong(block, ram_offset); } else { - fatal("host_x86_MOV8_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x41, 0x8a, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/ } } void From dd0e6261337df4384df3bb94ffe691bcd67307be Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Mar 2025 01:18:37 +0600 Subject: [PATCH 22/32] Set LC_NUMERIC to "C" in program startup For whatever fucking reason, glibc's functions dealing with decimal numbers apparently can only accept either commas or dots in strings, but not both. Meanwhile, both Windows and macOS have no apparent issues accepting both. I will never understand why they decided to even consider such behaviour acceptable, especially since those ARE used for parsing decimal numbers in many programs, but I guess it's their own version of Not Invented Here syndrome that they (or anyone else) can't be bothered to deal with. This is not how good C standard libraries are written, at all. --- src/qt/qt_main.cpp | 3 +++ src/utils/ini.c | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 2e0ce33e0..2ef797bd1 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -94,6 +94,8 @@ extern int qt_nvr_save(void); bool cpu_thread_running = false; } +#include + void qt_set_sequence_auto_mnemonic(bool b); #ifdef Q_OS_WINDOWS @@ -525,6 +527,7 @@ main(int argc, char *argv[]) QApplication app(argc, argv); QLocale::setDefault(QLocale::C); + setlocale(LC_NUMERIC, "C"); #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); diff --git a/src/utils/ini.c b/src/utils/ini.c index f5dfdef46..e23f83670 100644 --- a/src/utils/ini.c +++ b/src/utils/ini.c @@ -756,8 +756,9 @@ double ini_section_get_double(ini_section_t self, const char *name, double def) { section_t *section = (section_t *) self; - const entry_t *entry; - double value = 0; + entry_t *entry; + double value = 0; + int res = 0; if (section == NULL) return def; @@ -766,7 +767,17 @@ ini_section_get_double(ini_section_t self, const char *name, double def) if (entry == NULL) return def; - sscanf(entry->data, "%lg", &value); + res = sscanf(entry->data, "%lg", &value); + if (res == EOF || res <= 0) { + int i = 0; + for (i = 0; i < strlen(entry->data); i++) { + if (entry->data[i] == ',') { + entry->data[i] = '.'; + entry->wdata[i] = L'.'; + } + } + (void)sscanf(entry->data, "%lg", &value); + } return value; } From f422a9ce3dc14edf75b6c12d793c829a82db3f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:11:26 +0100 Subject: [PATCH 23/32] qt: implement authentic icon grayscaling --- src/qt/qt_styleoverride.cpp | 40 +++++++++++++++++++++++++++++++++++++ src/qt/qt_styleoverride.hpp | 4 ++++ 2 files changed, 44 insertions(+) diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index 60a7162a5..0bade8fa6 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #ifdef Q_OS_WINDOWS #include @@ -66,3 +69,40 @@ StyleOverride::polish(QWidget *widget) qobject_cast(widget)->view()->setMinimumWidth(widget->minimumSizeHint().width()); } } + +QPixmap +StyleOverride::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const +{ + if (iconMode != QIcon::Disabled) { + return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option); + } + + auto image = pixmap.toImage(); + + for (int y = 0; y < image.height(); y++) { + for (int x = 0; x < image.width(); x++) { + // checkerboard transparency + if (((x ^ y) & 1) == 0) { + image.setPixelColor(x, y, Qt::transparent); + continue; + } + + auto color = image.pixelColor(x, y); + + // convert to grayscale using the NTSC formula + auto avg = 0.0; + avg += color.blueF() * 0.114; + avg += color.greenF() * 0.587; + avg += color.redF() * 0.299; + + color.setRedF(avg); + color.setGreenF(avg); + color.setBlueF(avg); + + image.setPixelColor(x, y, color); + + } + } + + return QPixmap::fromImage(image); +} diff --git a/src/qt/qt_styleoverride.hpp b/src/qt/qt_styleoverride.hpp index c04d01a12..840aa6ad6 100644 --- a/src/qt/qt_styleoverride.hpp +++ b/src/qt/qt_styleoverride.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include class StyleOverride : public QProxyStyle { public: @@ -14,6 +17,7 @@ public: QStyleHintReturn *returnData = nullptr) const override; void polish(QWidget *widget) override; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const override; }; #endif From c00c432398dd2d1a7f0c2bfe20a5f9756867e894 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 00:10:39 +0100 Subject: [PATCH 24/32] EGA: Fix colors in mono mode and attribute registers, fixes #5395. --- src/video/vid_ega.c | 11 +++++++---- src/video/vid_ega_render.c | 10 +++++++--- src/video/vid_jega.c | 15 ++++++++------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 17b3fb593..f002ef999 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -112,10 +112,13 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->fullchange = changeframecount; if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { - if (ega->attrregs[0x10] & 0x80) - ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); - else - ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); + if (ega->chipset) { + if (ega->attrregs[0x10] & 0x80) + ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); + else + ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); + } else + ega->egapal[c] = ega->attrregs[c] & 0x3f; } ega->fullchange = changeframecount; } diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 261474742..10667084a 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -172,15 +172,19 @@ ega_render_text(ega_t *ega) uint32_t dat = ega->vram[charaddr + (ega->sc << 2)]; dat <<= 1; - if ((chr & ~0x1F) == 0xC0 && attrlinechars) + if (((chr & ~0x1f) == 0xc0) && attrlinechars) dat |= (dat >> 1) & 1; for (int xx = 0; xx < charwidth; xx++) { if (monoattrs) { + int bit = (dat & (0x100 >> (xx >> dwshift))) ? 1 : 0; + int blink = (!drawcursor && (attr & 0x80) && attrblink && blinked); if ((ega->sc == ega->crtc[0x14]) && ((attr & 7) == 1)) - p[xx] = ega->mdacols[attr][attrblink][1]; + p[xx] = ega->mdacols[attr][blink][1]; else - p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))]; + p[xx] = ega->mdacols[attr][blink][bit]; + if (drawcursor) + p[xx] ^= ega->mdacols[attr][0][1]; p[xx] = ega->pallook[ega->egapal[p[xx] & 0x0f]]; } else p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 3d1cfe476..11c9cbf8d 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -430,14 +430,15 @@ jega_out(uint16_t addr, uint8_t val, void *priv) jega->attrregs[jega->attraddr & 31] = val; if (jega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { - if (!jega->is_vga) + if (jega->is_vga) { + if (jega->attrregs[0x10] & 0x80) + jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4); + else if (jega->vga.svga.ati_4color) + jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + else + jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4); + } else jega->egapal[c] = jega->attrregs[c] & 0x3f; - else if (jega->attrregs[0x10] & 0x80) - jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4); - else if (jega->vga.svga.ati_4color) - jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; - else - jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4); } if (jega->is_vga) jega->vga.svga.fullchange = changeframecount; From ed4a312f4f6dec174a848dfa13bee8d9cc551976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:13:23 +0100 Subject: [PATCH 25/32] Remove support for icon sets --- src/config.c | 11 ----- src/include/86box/86box.h | 1 - src/qt/qt.c | 2 - src/qt/qt_machinestatus.cpp | 44 ++++++++--------- src/qt/qt_mediamenu.cpp | 18 +++---- src/qt/qt_progsettings.cpp | 62 ------------------------ src/qt/qt_progsettings.hpp | 3 -- src/qt/qt_progsettings.ui | 72 ++++++---------------------- src/qt/qt_settings.cpp | 2 +- src/qt/qt_settingsfloppycdrom.cpp | 10 ++-- src/qt/qt_settingsharddisks.cpp | 2 +- src/qt/qt_settingsotherremovable.cpp | 8 ++-- src/unix/unix.c | 1 - 13 files changed, 57 insertions(+), 179 deletions(-) diff --git a/src/config.c b/src/config.c index 2e6a5460f..8ff7d548c 100644 --- a/src/config.c +++ b/src/config.c @@ -192,12 +192,6 @@ load_general(void) else if (mouse_sensitivity > 2.0) mouse_sensitivity = 2.0; - p = ini_section_get_string(cat, "iconset", NULL); - if (p != NULL) - strcpy(icon_set, p); - else - strcpy(icon_set, ""); - enable_discord = !!ini_section_get_int(cat, "enable_discord", 0); open_dir_usr_path = ini_section_get_int(cat, "open_dir_usr_path", 0); @@ -2038,11 +2032,6 @@ save_general(void) ini_section_set_string(cat, "language", buffer); } - if (!strcmp(icon_set, "")) - ini_section_delete_var(cat, "iconset"); - else - ini_section_set_string(cat, "iconset", icon_set); - if (enable_discord) ini_section_set_int(cat, "enable_discord", enable_discord); else diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index c58d595c5..61de69cf3 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -118,7 +118,6 @@ extern int vid_resize; /* (C) allow resizing */ extern int invert_display; /* (C) invert the display */ extern int suppress_overscan; /* (C) suppress overscans */ extern uint32_t lang_id; /* (C) language code identifier */ -extern char icon_set[256]; /* (C) iconset identifier */ extern int scale; /* (C) screen scale factor */ extern int dpi_scale; /* (C) DPI scaling of the emulated screen */ extern int vid_api; /* (C) video renderer */ diff --git a/src/qt/qt.c b/src/qt/qt.c index a9a6460eb..ecf4b964b 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -35,8 +35,6 @@ qt_nvr_save(void) return nvr_save(); } -char icon_set[256] = ""; /* name of the iconset to be used */ - int plat_vidapi(const char *api) { diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index a00cc032b..eff29a232 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -176,24 +176,24 @@ static const QString pixmap_empty_active = QStringLiteral("_empty_active"); void PixmapSetEmpty::load(const QString &basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); } void PixmapSetActive::load(const QString &basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); } void PixmapSetEmptyActive::load(QString basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); - empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); - empty_active = ProgSettings::loadIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); + normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + empty_active = QIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); } } @@ -202,21 +202,21 @@ struct MachineStatus::States { States(QObject *parent) { - pixmaps.cartridge.load("/cartridge%1.ico"); - pixmaps.cassette.load("/cassette%1.ico"); - pixmaps.floppy_disabled.normal = ProgSettings::loadIcon(QStringLiteral("/floppy_disabled.ico")).pixmap(pixmap_size); + pixmaps.cartridge.load(":/settings/qt/icons/cartridge%1.ico"); + pixmaps.cassette.load(":/settings/qt/icons/cassette%1.ico"); + pixmaps.floppy_disabled.normal = QIcon(":/settings/qt/icons/floppy_disabled.ico").pixmap(pixmap_size); pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal; - pixmaps.floppy_525.load("/floppy_525%1.ico"); - pixmaps.floppy_35.load("/floppy_35%1.ico"); - pixmaps.cdrom.load("/cdrom%1.ico"); - pixmaps.zip.load("/zip%1.ico"); - pixmaps.mo.load("/mo%1.ico"); - pixmaps.hd.load("/hard_disk%1.ico"); - pixmaps.net.load("/network%1.ico"); - pixmaps.sound = ProgSettings::loadIcon("/sound.ico").pixmap(pixmap_size); - pixmaps.soundMuted = ProgSettings::loadIcon("/sound_mute.ico").pixmap(pixmap_size); + pixmaps.floppy_525.load(":/settings/qt/icons/floppy_525%1.ico"); + pixmaps.floppy_35.load(":/settings/qt/icons/floppy_35%1.ico"); + pixmaps.cdrom.load(":/settings/qt/icons/cdrom%1.ico"); + pixmaps.zip.load(":/settings/qt/icons/zip%1.ico"); + pixmaps.mo.load(":/settings/qt/icons/mo%1.ico"); + pixmaps.hd.load(":/settings/qt/icons/hard_disk%1.ico"); + pixmaps.net.load(":/settings/qt/icons/network%1.ico"); + pixmaps.sound = QIcon(":/settings/qt/icons/sound.ico").pixmap(pixmap_size); + pixmaps.soundMuted = QIcon(":/settings/qt/icons/sound_mute.ico").pixmap(pixmap_size); cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; @@ -511,7 +511,7 @@ MachineStatus::refresh(QStatusBar *sbar) config_save(); if (d->sound) d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); - + muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); }); } @@ -697,7 +697,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); if (muteUnmuteAction) muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); - + connect(d->sound.get(), &ClickableLabel::clicked, this, [this](QPoint pos) { this->soundMenu->popup(pos - QPoint(0, this->soundMenu->sizeHint().height())); }); diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index fdea16c2a..f7abebdf1 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -154,10 +154,10 @@ MediaMenu::refresh(QMenu *parentMenu) MachineStatus::iterateCDROM([this, parentMenu](int i) { auto *menu = parentMenu->addMenu(""); cdromMutePos = menu->children().count(); - menu->addAction(ProgSettings::loadIcon("/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); menu->addSeparator(); - menu->addAction(ProgSettings::loadIcon("/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false); - menu->addAction(ProgSettings::loadIcon("/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false); menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { cdromImageHistoryPos[slot] = menu->children().count(); @@ -170,7 +170,7 @@ MediaMenu::refresh(QMenu *parentMenu) for (const auto &letter : driveLetters) { auto drive = QString("%1:\\").arg(letter); if (GetDriveType(drive.toUtf8().constData()) == DRIVE_CDROM) - menu->addAction(ProgSettings::loadIcon("/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false); } menu->addSeparator(); #endif // Q_OS_WINDOWS @@ -666,7 +666,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cdromImageHistoryPos[slot]]); if (fn.left(8) == "ioctl://") { - menu_icon = ProgSettings::loadIcon("/cdrom_host.ico"); + menu_icon = QIcon(":/settings/qt/icons/cdrom_host.ico"); #ifdef Q_OS_WINDOWS menu_item_name = tr("Host CD/DVD Drive (%1)").arg(fn.right(2)).toUtf8().constData(); #else @@ -674,7 +674,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) #endif } else { fi.setFile(fn); - menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico"); + menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico"); menu_item_name = fn.isEmpty() ? tr("previous image").toUtf8().constData() : fn.toUtf8().constData(); } imageHistoryUpdatePos->setIcon(menu_icon); @@ -727,7 +727,7 @@ MediaMenu::cdromUpdateMenu(int i) auto childs = menu->children(); auto *muteMenu = dynamic_cast(childs[cdromMutePos]); - muteMenu->setIcon(ProgSettings::loadIcon((cdrom[i].sound_on == 0) ? "/cdrom_unmute.ico" : "/cdrom_mute.ico")); + muteMenu->setIcon(QIcon((cdrom[i].sound_on == 0) ? ":/settings/qt/icons/cdrom_unmute.ico" : ":/settings/qt/icons/cdrom_mute.ico")); muteMenu->setText((cdrom[i].sound_on == 0) ? tr("&Unmute") : tr("&Mute")); auto *imageMenu = dynamic_cast(childs[cdromImagePos]); @@ -740,13 +740,13 @@ MediaMenu::cdromUpdateMenu(int i) menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(name.length() - 8)); #endif name2 = menu_item_name; - menu_icon = ProgSettings::loadIcon("/cdrom_host.ico"); + menu_icon = QIcon(":/settings/qt/icons/cdrom_host.ico"); } else { QFileInfo fi(cdrom[i].image_path); menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : name.toUtf8().constData(); name2 = name; - menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico"); + menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico"); } imageMenu->setIcon(menu_icon); imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), menu_item_name.toUtf8().constData())); diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index ce6c21dd6..2fd108186 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -36,71 +36,16 @@ extern "C" { #include <86box/rom.h> } -static QMap iconset_to_qt; extern MainWindow *main_window; ProgSettings::CustomTranslator *ProgSettings::translator = nullptr; QTranslator *ProgSettings::qtTranslator = nullptr; -QString -ProgSettings::getIconSetPath() -{ - if (iconset_to_qt.isEmpty()) { - // Always include default bundled icons - iconset_to_qt.insert("", ":/settings/qt/icons"); - // Walk rom_paths to get the candidates - for (rom_path_t *emu_rom_path = &rom_paths; emu_rom_path != nullptr; emu_rom_path = emu_rom_path->next) { - // Check for icons subdir in each candidate - QDir roms_icons_dir(QString(emu_rom_path->path) + "/icons"); - if (roms_icons_dir.isReadable()) { - auto dirList = roms_icons_dir.entryList(QDir::AllDirs | QDir::Executable | QDir::Readable); - for (auto &curIconSet : dirList) { - if (curIconSet == "." || curIconSet == "..") { - continue; - } - iconset_to_qt.insert(curIconSet, (roms_icons_dir.canonicalPath() + '/') + curIconSet); - } - } - } - } - return iconset_to_qt[icon_set]; -} - -QIcon -ProgSettings::loadIcon(QString file) -{ - (void) getIconSetPath(); - if (!QFile::exists(iconset_to_qt[icon_set] + file)) - return QIcon(iconset_to_qt[""] + file); - return QIcon(iconset_to_qt[icon_set] + file); -} ProgSettings::ProgSettings(QWidget *parent) : QDialog(parent) , ui(new Ui::ProgSettings) { ui->setupUi(this); - (void) getIconSetPath(); - ui->comboBox->setItemData(0, ""); - ui->comboBox->setCurrentIndex(0); - for (auto i = iconset_to_qt.begin(); i != iconset_to_qt.end(); i++) { - if (i.key() == "") - continue; - QFile iconfile(i.value() + "/iconinfo.txt"); - iconfile.open(QFile::ReadOnly); - QString friendlyName; - QString iconsetinfo(iconfile.readAll()); - iconfile.close(); - if (iconsetinfo.isEmpty()) - friendlyName = i.key(); - else - friendlyName = iconsetinfo.split('\n')[0]; - ui->comboBox->addItem(friendlyName, i.key()); - if (strcmp(icon_set, i.key().toUtf8().data()) == 0) { - ui->comboBox->setCurrentIndex(ui->comboBox->findData(i.key())); - } - } - ui->comboBox->setItemData(0, '(' + tr("Default") + ')', Qt::DisplayRole); - ui->comboBoxLanguage->setItemData(0, 0xFFFF); for (auto i = lcid_langcode.begin(); i != lcid_langcode.end(); i++) { if (i.key() == 0xFFFF) @@ -129,7 +74,6 @@ ProgSettings::ProgSettings(QWidget *parent) void ProgSettings::accept() { - strcpy(icon_set, ui->comboBox->currentData().toString().toUtf8().data()); lang_id = ui->comboBoxLanguage->currentData().toUInt(); open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; confirm_exit = ui->checkBoxConfirmExit->isChecked() ? 1 : 0; @@ -161,12 +105,6 @@ ProgSettings::~ProgSettings() delete ui; } -void -ProgSettings::on_pushButton_released() -{ - ui->comboBox->setCurrentIndex(0); -} - #ifdef Q_OS_WINDOWS /* Return the standard font name on Windows, which is overridden per-language to prevent CJK fonts with embedded bitmaps being chosen as a fallback. */ diff --git a/src/qt/qt_progsettings.hpp b/src/qt/qt_progsettings.hpp index 642b2002d..b4e59e02d 100644 --- a/src/qt/qt_progsettings.hpp +++ b/src/qt/qt_progsettings.hpp @@ -14,8 +14,6 @@ class ProgSettings : public QDialog { public: explicit ProgSettings(QWidget *parent = nullptr); ~ProgSettings(); - static QString getIconSetPath(); - static QIcon loadIcon(QString file); #ifdef Q_OS_WINDOWS static QString getFontName(uint32_t lcid); #endif @@ -56,7 +54,6 @@ public: protected slots: void accept() override; private slots: - void on_pushButton_released(); void on_pushButtonLanguage_released(); void on_horizontalSlider_valueChanged(int value); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index f7b32ce84..d3ebf8c85 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -29,21 +29,14 @@ QLayout::SizeConstraint::SetFixedSize - + Default - - - - Icon set: - - - - + Qt::Orientation::Horizontal @@ -56,7 +49,7 @@ - + 30 @@ -68,7 +61,7 @@ - + <html><head/><body><p>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.</p></body></html> @@ -78,14 +71,7 @@ - - - - Default - - - - + Qt::Orientation::Horizontal @@ -98,14 +84,14 @@ - + Default - + 10 @@ -127,21 +113,21 @@ - + Language: - + Ask for confirmation before saving settings - + Qt::Orientation::Horizontal @@ -151,63 +137,35 @@ - + Inhibit multimedia keys on Windows - - - - false - - - 30 - - - - (Default) - - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - + Mouse sensitivity: - + Ask for confirmation before hard resetting - + Ask for confirmation before quitting - + Display hotkey message when entering full-screen mode diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index 471558e22..19a537652 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -95,7 +95,7 @@ SettingsModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: return tr(pages.at(index.row()).toUtf8().data()); case Qt::DecorationRole: - return QIcon(QString("%1/%2.ico").arg(ProgSettings::getIconSetPath(), page_icons[index.row()])); + return QIcon(QString(":/settings/qt/icons/%1.ico").arg(page_icons[index.row()])); case Qt::SizeHintRole: return QSize(-1, fontHeight * 2); default: diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index cc58d3cde..52d737ae6 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -46,11 +46,11 @@ setFloppyType(QAbstractItemModel *model, const QModelIndex &idx, int type) { QIcon icon; if (type == 0) - icon = ProgSettings::loadIcon("/floppy_disabled.ico"); + icon = QIcon(":/settings/qt/icons/floppy_disabled.ico"); else if (type >= 1 && type <= 6) - icon = ProgSettings::loadIcon("/floppy_525.ico"); + icon = QIcon(":/settings/qt/icons/floppy_525.ico"); else - icon = ProgSettings::loadIcon("/floppy_35.ico"); + icon = QIcon(":/settings/qt/icons/floppy_35.ico"); model->setData(idx, QObject::tr(fdd_getname(type))); model->setData(idx, type, Qt::UserRole); @@ -64,12 +64,12 @@ setCDROMBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint switch (bus) { case CDROM_BUS_DISABLED: - icon = ProgSettings::loadIcon("/cdrom_disabled.ico"); + icon = QIcon(":/settings/qt/icons/cdrom_disabled.ico"); break; case CDROM_BUS_ATAPI: case CDROM_BUS_SCSI: case CDROM_BUS_MITSUMI: - icon = ProgSettings::loadIcon("/cdrom.ico"); + icon = QIcon(":/settings/qt/icons/cdrom.ico"); break; } diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index e679dafa5..ded50ac34 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -81,7 +81,7 @@ addRow(QAbstractItemModel *model, hard_disk_t *hd) QString busName = Harddrives::BusChannelName(hd->bus_type, hd->channel); model->setData(model->index(row, ColumnBus), busName); - model->setData(model->index(row, ColumnBus), ProgSettings::loadIcon("/hard_disk.ico"), Qt::DecorationRole); + model->setData(model->index(row, ColumnBus), QIcon(":/settings/qt/icons/hard_disk.ico"), Qt::DecorationRole); model->setData(model->index(row, ColumnBus), hd->bus_type, DataBus); model->setData(model->index(row, ColumnBus), hd->bus_type, DataBusPrevious); model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannel); diff --git a/src/qt/qt_settingsotherremovable.cpp b/src/qt/qt_settingsotherremovable.cpp index 1a6dceacb..8a810a4fb 100644 --- a/src/qt/qt_settingsotherremovable.cpp +++ b/src/qt/qt_settingsotherremovable.cpp @@ -46,11 +46,11 @@ setMOBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t QIcon icon; switch (bus) { case MO_BUS_DISABLED: - icon = ProgSettings::loadIcon("/mo_disabled.ico"); + icon = QIcon(":/settings/qt/icons/mo_disabled.ico"); break; case MO_BUS_ATAPI: case MO_BUS_SCSI: - icon = ProgSettings::loadIcon("/mo.ico"); + icon = QIcon(":/settings/qt/icons/mo.ico"); break; default: @@ -81,11 +81,11 @@ setZIPBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_ QIcon icon; switch (bus) { case ZIP_BUS_DISABLED: - icon = ProgSettings::loadIcon("/zip_disabled.ico"); + icon = QIcon(":/settings/qt/icons/zip_disabled.ico"); break; case ZIP_BUS_ATAPI: case ZIP_BUS_SCSI: - icon = ProgSettings::loadIcon("/zip.ico"); + icon = QIcon(":/settings/qt/icons/zip.ico"); break; default: diff --git a/src/unix/unix.c b/src/unix/unix.c index 81312d25d..c41aee2a4 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -73,7 +73,6 @@ static int exit_event = 0; static int fullscreen_pending = 0; uint32_t lang_id = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US uint32_t lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US -char icon_set[256] = ""; /* name of the iconset to be used */ static const uint16_t sdl_to_xt[0x200] = { [SDL_SCANCODE_ESCAPE] = 0x01, From 8b72c84c028effa55f4751f25da0c51ec1603ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Sat, 29 Mar 2025 00:13:10 +0100 Subject: [PATCH 26/32] Use indicator overlays for status bar icons --- src/qt/CMakeLists.txt | 3 + src/qt/icons/active.ico | Bin 0 -> 9622 bytes src/qt/icons/cartridge_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/cassette_active.ico | Bin 9622 -> 0 bytes src/qt/icons/cassette_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/cassette_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/cdrom_active.ico | Bin 9622 -> 0 bytes src/qt/icons/cdrom_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/cdrom_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/disabled.ico | Bin 0 -> 9622 bytes src/qt/icons/floppy_35_active.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_35_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_35_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_525_active.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_525_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_525_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/hard_disk_active.ico | Bin 9622 -> 0 bytes src/qt/icons/mo_active.ico | Bin 9622 -> 0 bytes src/qt/icons/mo_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/mo_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/network_active.ico | Bin 9622 -> 0 bytes src/qt/icons/network_empty.ico | Bin 6950 -> 0 bytes src/qt/icons/sound_mute.ico | Bin 9622 -> 0 bytes src/qt/icons/zip_active.ico | Bin 9622 -> 0 bytes src/qt/icons/zip_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/zip_empty_active.ico | Bin 9622 -> 0 bytes src/qt/qt_iconindicators.cpp | 33 +++++++++++ src/qt/qt_iconindicators.hpp | 15 +++++ src/qt/qt_machinestatus.cpp | 72 +++++++++++++---------- src/qt_resources.qrc | 25 +------- 30 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 src/qt/icons/active.ico delete mode 100644 src/qt/icons/cartridge_empty.ico delete mode 100644 src/qt/icons/cassette_active.ico delete mode 100644 src/qt/icons/cassette_empty.ico delete mode 100644 src/qt/icons/cassette_empty_active.ico delete mode 100644 src/qt/icons/cdrom_active.ico delete mode 100644 src/qt/icons/cdrom_empty.ico delete mode 100644 src/qt/icons/cdrom_empty_active.ico create mode 100644 src/qt/icons/disabled.ico delete mode 100644 src/qt/icons/floppy_35_active.ico delete mode 100644 src/qt/icons/floppy_35_empty.ico delete mode 100644 src/qt/icons/floppy_35_empty_active.ico delete mode 100644 src/qt/icons/floppy_525_active.ico delete mode 100644 src/qt/icons/floppy_525_empty.ico delete mode 100644 src/qt/icons/floppy_525_empty_active.ico delete mode 100644 src/qt/icons/hard_disk_active.ico delete mode 100644 src/qt/icons/mo_active.ico delete mode 100644 src/qt/icons/mo_empty.ico delete mode 100644 src/qt/icons/mo_empty_active.ico delete mode 100644 src/qt/icons/network_active.ico delete mode 100644 src/qt/icons/network_empty.ico delete mode 100644 src/qt/icons/sound_mute.ico delete mode 100644 src/qt/icons/zip_active.ico delete mode 100644 src/qt/icons/zip_empty.ico delete mode 100644 src/qt/icons/zip_empty_active.ico create mode 100644 src/qt/qt_iconindicators.cpp create mode 100644 src/qt/qt_iconindicators.hpp diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 90ea218af..e6e45fc25 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -194,6 +194,9 @@ add_library(ui STATIC qt_openglshaderconfig.hpp qt_openglshaderconfig.cpp qt_openglshaderconfig.ui + + qt_iconindicators.hpp + qt_iconindicators.cpp ) if(RTMIDI) diff --git a/src/qt/icons/active.ico b/src/qt/icons/active.ico new file mode 100644 index 0000000000000000000000000000000000000000..9569a3962ba1d76f735492b689bfd8fd1cd95839 GIT binary patch literal 9622 zcmeHMy-ve05Wb2Egc#`1p<6RD@&uPeF)|>`_t`ncazmBG zNh+1Q>f-q4?(8r2-N_Z1$W&%CL0QPdROD7f=JQa0Jr#LD+hP&wkLM!y7a~Ow>d%n- zz}PFu;1wD|I|^ArE|VPOmD{RvvWBd3(9=u@WJr*%e$>-c$D!r9%5n~VAzVwCf3x-L zD9R{no0Wz@1_Ex2&G-&pN6b3g8xZ{r+>Q4)^jD-O_^6&p&v;yRRb8DOJwxFPQg=Io z94Ycf)q5A6rY{dae!UXIbjx<~v$`AjEmPJ$D-8idU^E2W*Ntw;;wX zq|kB=*0^#!Uk1;y%yfFbZ75OD6yxt|l~z9-1B5VuoiJNr4V12GRP zz$>ukVQXGojz^j=#pM{*gT4CrqH`H)9#u@!d@C+>PJP7abOq2&+MD}nFXz$s91dx} zjqM>YF#FB--ZA3Ov)E=2VC+$yKdzrtV(^zA@|%P{Dy%=q^!=pnXdY_Q&#CO|+hnai zwH24O1Fg{zFa!(%L%whyl-?KNnvdAYnk+U;VoXO7gcOl==lnAsd^bt`yvy=sEOrr+3BP(YCsn@n@wlqcC{Kr6(O#` z41Qy}tOtr71OFDWnd2Wni^Zag6@>4(3tsWt>f;tc_>L7Qy)dv3;unM;(|3IQ;1`6i zBJbj#n86bN^oo2f=H!nJi#hpQ9cbcsYybF(q3?e?Z`x{~H*hje-H5tn@#g7`)1@;@gOQEWeM_`sXQZ`seJ}~4lY<$obu~`xy-<(Bkm&Avx zwFSK|@iFHtPVsr0&U>|cfqq)tm-^Ybpljk|Pg}$me6L)=EA>Msg=*kK=gThQqb|AV z7j4_<`Lxz^s=3(-x^qjf(DF@xoLk@ZE}ikvhgyuf$gN9CF6uxRO81@ZyP6>HzzuO( zom?9Iz_7=#@k6JO7)s)2Mx+qmCGjJhvd#K2#&6H!7=6t3kJZHTk8%I-?WFLS_fM)e ztk>)xW?Txfjhr{`gI9WmPAQhm|5Drg5i&=Q oP2FBeH&~kT?`Ox@+M{37fBLp744SNre@%1qcfEd6oPPxV2L@}=i2wiq diff --git a/src/qt/icons/cassette_active.ico b/src/qt/icons/cassette_active.ico deleted file mode 100644 index 32fca20b4bb41aefbd3a03a22c94f0098882b7fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHMJ#*YP5QQe5crq^JLWMi4OqqXRSN_|c0 zTj1fAAViTo>c$_!4Q`3WzV{YO5Q(ZcU5Fpgu9=}oh9_^Gp? zPtIStg#A8Ouz9ZD_n1$K@ip6<;?mgc0)Cz=&tVCUd`Y);jtR@xPyd-z zY1Ep7ab8EAMme7W2)9-rCob=69TzU}=vX!M_1B#A$VCnFBM&~e*@@LLV+vR1r;klI z@oB6%+JYV7_c?g1_-g*%nq2?$3RF?<$Y92lM`KeduRTd90fQc-fk|wf8P^ zI80wPS!U;Gs}`yO?FxNz?Hl@r4gKdJeR?i3KR=dVR`Zk2{SEr!^44og!_QOC#yP)3 z^b40bVcA;#f#wSO&2{A*ERkEjRG&#TK)!houxoF0ovt1?b7?vfXCLst_<<1uUNCV$n1Df84o44e1a z7;`<#2=c+NzjK(Ax_rbaSLI(@KQH~BFKZB2uru`iT8L+EH*rbdV|wcb-o{Q}TrJC3 zzZS!aBU?W&{o?D=nhQ6_`1I!K8|%uo!DT#}4~a+XYidY)fvt0tcF}SAy}1QibMcm& z(=RnXg7z1=e$--a4VT8-wcVlOuKv6RkJ-xkM-ugQdbBaM@7sL^zT*nu1;kVQ0|+l8 XF7Ps9gO>@LlWygDfUo_M0vpc%8S%6om&VLP9htQl#9Hl1E6z8*B{~;xV?QA->Y?@%=w{Y>zF6@F<*w)6-zM2yae8co9N4J8Se$k3;xiw)68wfBPha z*H1%OEE@g2<=t59Gt03vD8~`LouvYtC%wstzS*fdcBS{z}iH7a(?WJ zA=c+&2l0bSr4BJ5F(7u3JoV=oBnHF|Vo&?)cvr2QKg}T~tzYuPXz9bPTfDp7ME&k(!4ZlUy(Bx~l4WSwO|5qJ74;o4DU-zmmMO zJ!+P?0`YpYqp=u|V#N63RDe_c44RJ#t7KNUvDb@grs^cJYG` zwa~$wy^9|tuh8MS{djJ@vUllOj&=pw zXU&%3RC*YDf9LXzXS;9eSiJq-rVFymP8@!EU`JOjG5AV)E)F}W()7Uw(xWeu2U53- zKQUvmi$8p+jh@3?To-?A)FM|rG$($LICKzu%HR8l!4A^X>p2eMMJ*pgE$kl2qZfYc z((zF%r(^f%^Ss}BwET&k3RC_%R zzt-gJi@ADT^C!IGJwh(M(Mw3YdgvUR{82CI)87Bsa<%b;^Z>n`o*s#pJ(q)>+%(5* z0Y7$hxTBK~cK8R+PpurnsgEC?`Piv- z`gYAfb+25#hdRIJ*1DUt=b!uXP?(;7jt`B^63qYe3Ow8u(EaYkzC&EvcZj87H4$F= H9_YUTai}4j diff --git a/src/qt/icons/cassette_empty_active.ico b/src/qt/icons/cassette_empty_active.ico deleted file mode 100644 index e1bf61f612a9628a4416efa842d21d04911c7f65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeI1y^b736oqSz0U-iAFp{&~&>?TYk`Oy^$2dYfMu!gl2o9}5GAS9uLu_t|93g&| z1=$qmRQK0YQ`0pwJ=43A@!nDInR{>Db8c1lRJVFVI0<*d{rf?97QVe3!dD@L2M;>` zhmS&drP#xVo&W5U5We{|gtN2Gf2q1(H1?5d^i>R9ToBGxccewtb4;a*p;awM$CGoI z*S3kOu_?3qn5Q4xwr#4Zp*3su)GU|F!~v%95=i+i^{HX^CM#>gZ4Z?7(s|Ms6QPrrGOQ~Pl3yKM1it=>;DUT75;ZHx{0rTm5bW*sl&=jMGz+fCYU zykFU#Ymb`Ae7?%#Q0mp*({{fheuI+i%Tua)q?{@@(Np40rfagNJ5d5qc$aN&a~F3wb+Av~^S zEHQjIJ!EWLIo{)lfpCGuK{W77%ysF5G1L+-HOjdCvbN^$ijx=TuzvJ273nkYkGUL* zd4GIA7CqNnJ8lKy)fX}TdK%;FdvWpNUTn?_e0-|=)%UtzeLaFd`f^w^-?#J#9X{8= zee0>7rLV!#{wUrY=aSjjpV;q?7HIpuk9|Hz=eqeECZl?rSn8imjkK3$x^;gd|J2|2 z*83qd>idVAzRNu>t%H(l@rnJH9J~BO`d{nMlaUFkxJ{$4<@^mCrN%BF4fEyZxO(DkT{5D>DPL2UvQOU;38fk zb!d?%Zl4@nHJ^BiWnGz<#?U`w=fb>yf4A0L+|0wAtk>LVYV+IBn;Sd!+rR(U6^QZU z82|ks#y2N1UWIt^IK;)v5F7BxiJrIa=(+1d;X>Gq;)P!%jF_Lp&UBpX;5n@Ii_4oc z|3=E=Ce%C4R@&vU>gT%pSZVUSk|X_eeazc~xNVyC?vMMJyNBcS-H+`soTAO@sK$D; z?Au4^r%C&~$!hmNdaUJro$r0_EAy{$6W`jy5&GNapXRh>UC3YO{L$EjlX}p4XgjJO62n7sz8vja|Oymi1u{%yA#g z)e`hU4Bt5&8$FmSkJo&()-dDCbOsG#HBRy%J%eT3a_&{OhKzT-RzsZHyvBs&iR05d zKK0;8e)9a`sv$k?lc!H=@TtWw^Tc-{JYdPA_%Q!62RHGlNIh8ATe_Aj$Ik7eJ2wBh zwQ79t>-;@$ue)qG|NJg*3iI>N_nXFU32y)1uE6`d0(t>)s(%3KWyEW}j9BVr#PVdZ iXhYM4u#V?_-1y>7(>(c1?LzF2>?fsDdX?V1N$Bs>Z?97NDW&xGtzUooDy6?L_U@fu z|M7K7zkZX_{k>m*MBLx-{SGlW1%i*GOFtrRXB*+SWpk)u7!z%r8c_U0ydjw5PZ)?} zW30@tJ*J!sk66M8vF^vCH+UH@uk2jMCZ4+8$2xea--u_vG`P<&^4$38=b|CQ+O_Eq zu@wf#J->kOTC9%b<9y~&Z0S`SI8}a;Pw~Xc=2{E4N6Rn9Mt+<#&SEo;>2eLGkuGep zR?;<#r5`^bH;d%~tzale>EfK3MZ2alhLe15y<(YRCtjKqQ|gm3Ogm%M3P#P{#v4xL zRy_NhZ{)7xRnHjHJI^@6D}BfJ>1G@+r*S+(*pLl0*jwXx8r*a}z>juj%1GyZ{4rT!W#`*4rGfTeh08jjakwJtdu zaX8p|(>LcTtkQGbvFbfwF^p@Bc?pl_9i7W~;9^W`5wD$F)prcfp3i&m+MF7FdOnpr zCQQ}R>Vj0(>w~x%7OG<(Vn!oaZdJ{xO)cXUU95EeUMjIT(LBd^&Q>rZ9&xFG^ZB!e zSFj8bF)dcXbF>!AbQqWGYISz;gqd?U%*?-pmvN@L5u?{~{R3RCMb_u}ZR51q8Mj(r zj;*xM>0x|IcjG0!#&?z5fS#6UkB!;f9p>-g|6q1W@5d*6e|^Sx7r(dg3Z1@(>3i!J zyh~r%sJ&-|TN+=diZzN0fOFqH8FxV6nsYAW6Weg+`;1hEFU*N;I^*0D#|F0HBfjuV zsP$QoV*y*a6wGVzGqz*Yb#b*O*)<-;CpJvj>ZMzK8NUV}!K)lugWq$Wk*#xG_30|s zU$H$7&84y@d~dAeV0pTKdFQnn5Ub%Zz4EPhwC#IhwaxAa4B8$In8GeS=la-Un%`T< z%i>#nUbnUjKj+-W{>S+I9$Be zDosKM!pi$m#OFDijkVa?4aU*ICP!{9=InY2yTj3HC&dgej%{HFj)EPuuj22;4ji^7 zs99{4e#e}zr7-sPT$i5hh#x=Pj?d`^?_Q_z5qd7LGi)e!8q*J0^WPi8*nk+>85oyz z3yjzH9`}rQvhjnzhutUqZW5;Vuz|n0e0fvdmU=Pt<~4V$k2S`k#D zW18E`F5ZSy{NiSB{E^p3>Z3Hdj&&8}Uf_-6(!hM#Ovl!dI@UBC}a&u5vq)&DE`bIoZWy+*@}^AFs+HAr*m8F}UX zCybo`ss{P`{j2-<*dB~~Uw937R|9<~-uC%bG%VGD<7`|n!zUIoZEU%>Ao)0d%dKn2 z27a#@uegaP{v8@j=Q?-LfLzGa8abnhKaMS(Pqi1%Qa{yn2}|Su6Mnuk94dwr&Aq+BUvUF5)PQ@pZDl``Tz9~#2J*9M|K~W1WzEBNIj8Sb2j^5C z0cTT#xEp@`d{Fpi8lagU=}H2mV7)jVUk9_Kb+LvQZq$~SP!SM^~Z`Ew2S za8tn%e(Gi`eUH0Y1J5<)=6M(H@Uz?8H^xopm4-HV^0TQvS+8SH+%MrT`7d$1f=0sv z_Z9hDE?eA{hMK#VyK1^?4fb*`Xs|uUyhHB0`Hyl(4Yntcp}3FmJFh?Egn3O*4cRvH zpEzI6+tV7fNK@7KVphh+$8Y(^oZHVS-8|!01y3;iJ|bOU=WGLd*ol^I&MDnq@TVbo hMdKLehU~}wY$NFgGq>~x_8mAL!1dn#;Q@bJ`Ul!N$y5LU diff --git a/src/qt/icons/cdrom_empty.ico b/src/qt/icons/cdrom_empty.ico deleted file mode 100644 index 45580999cc66d4d9a75aed03ff9fc268592a28d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmciIF>d5W5Cu>gSQs#zY_P$G3LW|g8~Fx=LOC*g2}24U`Uo31ut$KEI`Zlgy2J#| zln9XMYL4D)tA}MU7lbL#;Vp-Gmqp{FiER)xuJ1;6R$V;^tAe zKmS=n@3?B=R4om@Fl)@!wlrwT*LZ(64BM+=xH%n$&1GO8xEY2%@Uq~|=ehhgc(=j7 z`!o#YJ`=Z_@qSb8S7rPb_o!zK`Wfy!tVshNqeYu$M)@fm%JZf?clz^T zyZIE)sq=VF6+8>P8v5J7y9&qnE|0&B=h=Nc*B;_|SDst(3f+AlKb~7Z#=G>obJ0bjRFPa&7i0h&9T3nCXjI{Mn8?N!lnt9&R#+&oNX`%k*^=%HPJX%~e z8JGCA2QJK7=JHUyh2gOuYM>hPAU?Sk#qly${0=vxnwqj0pfC2X=1_XKF28el z8B1M`&8)*-J?R@i>(o8T;lic+4IZQu+Is24aA4N97xFEnH`o7jwRzUsj`?P7@wNTa zn?hRI<2AJT@qo0UJ;$X3Q z_pi%%@9N{d>k;_e!PcWln*XnKI~fy zU+$0;^8V)Q!#Q^CM!DXS((zN?+0#6G>p|U1df~Bzxd-0xIXx_S%4ctJ-td?nXskth zj?WW{uj#>h)GQ&s9(clBKi2~-m}^_}wchHddeAR#sHTOPN2kRXj~@0T*U*G&mN4rq z@SofxGM6{Zd0rVauQiXw@BL|HE^jE0Uule5;&@9~PQX$PZ&-Pj@_IbGhowGw>$Nsb z$72smdh$`b_#TbB!dolH_R#TI!qP93In?VKy|rAtIp4?JtFOQE{^INBZ7*YuvpwLu zX4SQ@>{%;EOWwTIgFJ7jK4YzubF^CVs&?Fu%;ycWPF3IK+C0y-YoB+#Vb+Nr_Jb$P zTyx$nO+1JP#l!gEI$Grw;lImDxdw}kkW<-s9sT0EgV zExfgOU^o%r!4rz}hOgVY?Gtv_@Qe#dAZi`ETW-j(O8dFNjB(8A20 zn-B5*&iD@seSiKCU;Nzn{n=f7@pIevr`z}-B0i5e-E2002KIrM{pn4=x!P{}v)jPC c&v+X1%k2iQp!&d~S9FVh@!9=DM0~IGAARs@lmGw# diff --git a/src/qt/icons/cdrom_empty_active.ico b/src/qt/icons/cdrom_empty_active.ico deleted file mode 100644 index a48371bd7b0e0775308bacc103eb0cfb7bb16f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmchdzi!+{5XSdxCq|IME*!v}Rl3X@ka`{J6OoRG%XTSNr+2tNdpA^C>JPFUA2f?%O(~}Us4I#XE z(e(fLG=$$J_VQ)ZfBRVoKYkv<*;&(nCwYGh_qF6mQxuxGKv+xOf+MwDi`wSwNmW&q zxi>dA8Iv4J`t9nf$*Cllv(f1^d@dR}S8}pel6?NDPODMM#a}(g^0kPP#u9(8K|f<# zLoP&q53 zuYuv~IAb7M?Vbt5$pztwM#mxMbBU7+YAy#H(EAcMxhLzRI&koZOB@txFPA#-1--^t zZb<_z#w{MdNon^>N?ZAe)YS)!U#E0krxdpmSB!$!GA_6i+@Gg(c%PEqXXJL1?>BnC z(&JaTN8RCIO)P5LpG9fr$vT7W8g`!@K0|y4hXhBps)75-z%FpHO3z;kT}=M;NX5CPkFRG z$`E_l$o212w^c1RIfh9@KBC=%8`-r5-QP;p~d~v zkL$G^%F`GJIcU)*m$*lGqQg9p3~+s2Q<_6s_$<|;hOQ{nKog`ckX&%6E+co+^qOdZ zOSBM1(<9?UnBIJq4p*U~Mq|^D5PcO^W-A2BTp8UY=JMX_xU*Fr}kB zziv0pb4y;K!HRl>YBl6x2Zk|y!{)bFn)nuEBoezd_sO}Su!s_bxWAv5NsSPx!0lr5~@iF@34#*P9-tasMX|jHD5Hy&z`OLxd zsC*xzevomYvQ{T`d!FHU`?bCEyKTgN* zR_X9Ar2U(ac7j{MT2bQlpN~?!{3O-4wP0-UXF>VGU@Ko7GD*fW}{s-$;LL7A5pNuU+zrKEdaE;r&+jv&u?avSO%=X9Id(!WD zbSaH@vPyXXAz#tUzdcnKe3{$3kz(2r9yxTprV|IzRsc!P|?H=p5r zugg64*BBaqw9xj5H)uTl{i~~?RENg((6z!xMQE2W=LnBly|L+c_xx<+eyFeWo_vp{ zrWxLpq4!oPcJTSro2ydsm_ng8+L|zMrDbA8|E`v0Sp_;`a} zM{4K}G(gX#k9SEE9taO4F2=omG}jxR*F@VRJn&_CMdUdF)u#X|^1h;~9#`Q{Y70+*0_2#cf z@#5bv>dm2!7yFp;T=05V%l8tomM7mG(h#Vco{^ebf5Abcb zv43%2ln(<7{jnw_QwiiOvlES`K1E;70?@1y@tMmzJeo-I-=Nq%~!8!B1elI@z{?-uK65>Uxn2F z&LIu2@ei{tKIgYN$91&*JoqU`K77_X=G^75XD~H?q7m0{*fura9BkrKJcr@Z(w|E# zZ*Oy97o1XoQh`!||F;6F_f&u1QT=s*JJtzw3%!6|LC>R~glA>Kg1dr$1M$-Q=@W9^f`Ee{Nda#zG#MbEv|v#O?-tKN%aV&vDi%qjdTE?h4E) z=D<4Stbyn5w$lYJlfyn|!qcRY_%l6&eSQ)qTp@?Vwq JIG=Iz}toO8oO=RdsSt3*)t*=xs1<@uh9F0xv!vuCJ@GcRB{KsOc~HWN95-x8B9V5LrxSwfWu_sqwetg`!M|aIOGa- zSfG9XAr3H1pY7dlmy{O$rTo;-@w4A-FdsDz&i)erfe!tK&~NX5jo;hGxhee?8+1-d zpX=BlS$^(?oH*Q+KKsb6dkwLT>-|2%oRWTO4->0bUv{_ci?l*U*E4h0bH?6{EUmOuYXrkZF`r2 zcKjheFb$9GTIs>#{!ZEC`+D&nyM46Ze2#r#zh94*_*pDfm-C3=_de&Z$MZQQ)h5>xJk_84BmP6g zvv?Nl!<6H5iE&KDEbikx69vLokXyv!Gf@izs<3ACY~?sU%LMdk65wf&WYCjZ}z8ZVwCW8+>Gn3E9a(h zuTf{??`&AYQ^Zf*8ESozT{(RAo86j!r+r*&ALL+gwcuNxuhp7+>7VmqF1}(-IL3R% zzyDwBU&MzTl!o|YTKb;F^*8;Nn)AIVFusCp=G!|w`8!C>oBy%- z&-ir3Ao2b!+5e2!n*6o(&W)Q5YLC5VuC{gMJid26|19<2V|zQSUu|OCA>=CY=ltvG zCr>Qi#}dD{dDV8qJ(f21_}MeJ*?-!(c5%Mf*5BKCs&;YxBU?{l!-MCq{jO{s&&0Ci zKgWE`?QS%uj_;O++ruB8nu5XV^{C{T3CkRhYTj(vnoeFM+!RP-qG9+HQ2eZo#i97w%NU}2$bN_B^RN1Ke`I(>Cpwgl3^cGT*IuS5$^#wk`kwC4i>~|o z`vV#1@S!7Rf4vSmy1W_)b95?=XK>xv$B&|UKUoJ=_IX*?n@wFWPr=8!);=Tc#`hcT zS315)k4lV#+z8*Pb4MKXl~~`gboh~1A9yCeRkibeRlOb(-lZPB={@Mt_}OoIMlRyZ zkbmtv9_uxR-o!Ec_u%*S<>xQdU+X75Jc3QV4(%^>bk6!iXD+7v<9#`X*5=Ur0gtZ9 zPe&5rAMy_xJgZgVb+vt^^z+qfO>MpkjSpK1Xw)K>KcJ9yEozEdQG^fM@&H9r&M-O^+zpejm&oyUg z^j;5N=*`%e{g(}tp*aT0&A*-hP{(Z@g}OLCKVJXjk9_7L@~Qm8GZlyGf2vO8Q~vWl z=OVhnA^)-4<*SZ*8*vKl@Kk$XzP`@K_|jJ$my^1A2^4e2{zBQtn+Fxp!RxAN@USA$IQM z$33jn50~+ge9uJeQtOU$Cd8T6?B)2b+o^FX$&$wMqP}jg2Rl5B;E+j_&^)KXPB0)GP^{{RswRxWe!t?OzRWQ5^zdaA(rx3#H*ZugXY>2ZY=1N#`)Lt+xk0!xzf9|*E{D=hySp?^<35|ZcC44N z3yt~GV;p=x-QK!yXH7v5(0qK{nLmGu)5i$={oZ|c;BMECBP!>b|6}IgZu`93?bh=j zVC3LL>>sa#@jod)^{^P!4?oq4`ER#<9Y!AT0ed~QR#@U7^E#1l0kOl+OosgEPDO<$ z4nE9f4Y9*-ntvkm`YXQl)*OjR49W391~$#L`_y%F5M$I2@?rkOy1BVI@IhXZ|N6R* zK|bcdn3$RzzrpL6A0BnwpXfpP-oNX*w&}Xcw#WfW-kQA1;9b}0oU!A^&l{arY9H;4 z%Cv*pm|box-BS1P%;U(p6XJO^>>c(Hdr&!uMSXX>z4O{7XNixSh4UnHE*;xb;^8*L zn4;;H_>Fsf{j4$1`Cp8u0lb^L&a~|MF~6K%x@lJ$>}Pd4 z@qX6FXe>_J$Jn!Vx33+KkrrKP`qiAT->akw|?Yk%_AsQ+D*Z_l+B#~ z-hIb)6z|c)`{CNS_hYSF=ox=>@GC|9bNsP+DCYP-G+*|t7Q=` z_z_2rsSca@b4KkshWlmw&O&bdK*`C2EFBXIc^V6S%5h@9${$~B8N;QH@1W@u|)ORM2-!zb~*%^m$UwvcGQ_s5U!$sGA4qf#=9HQjXyIpHo+4xkv^XITj z%X4L&=deZ}F4tRjpPAb^dihMdvZrwZ^#V_QP8;77*uRc_zQ*#TJ#rzBxbU030UmqS zTKs;Y_~hhyYl`S5c~ubBAY4lCJ#KHY9jE!$ev5~3n9e_r1M?s6u?ycp%$R2dQ1d<` zzeO77Pi~K6@>8)WH#LbhpyuQTi{@W4_ay(*{Qm>jUl*}t4aBu4H#PP@Ywy%`e_(fB z{?+rZX#Lw9_^u~TYIeHJ{(6n+j4S)@(dKV~Jg;gSYe7Cxa&_t~7kD58&ze7V(4=Cn z12i%5$t%-Gx&9W%=bu4xgEEB&GO+kNY2iB!QA|@`C53&{J&Oi z;{Ma;&%SslGT#(S<}X|8YDEb5G-yuGH-?q2Us_N>ZZJRJ+2>lqG>SZs#wzcmP)dTSEZ+yGzegFUf diff --git a/src/qt/icons/floppy_525_active.ico b/src/qt/icons/floppy_525_active.ico deleted file mode 100644 index e19baa8a2094ca6d155472f1efa9c38a706e80a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHLy>b*W4A#L7KSPl#Qly}`k}^-ggoepuP%)G|!j@DS9wQYsWga3AkSAbxgGHa# z-<{TL@2+?ExCG8O!nSPblO+6$dHac`5{@@HC5jGg*xmYI7_fUhtIQVZw>oQ269R^*YlUidmkTK-u$Nasqsc0 z8{;ATcz-+}E1%1)G4j|`RaG)S4=oS<9v@@x1CP(WzDLsZ&AF!G(fBk}x$)|*u1Q>v z`)Av_MxD`eWAz603hlers6^Z4g09UT)Bdr&Vd??>9pW9t8ua9H#rqv&$f2pW?hhCT z(5E^F>m2PohJDBIpN~DyY=LqAFvdgnA!hI~8}^$l;_1lvBjT%iI{FwN-ych#<#A)9 z<*T>JkH^~QW%|aY`iAagi9YPj)pOc>(%1gZz%TF#d-{(&`i;H!AI2%d9gF!Xp5G&K zrg^%j%8iZxRo6)IS~Oq1IKyC2FwNbk>BIyRfCc70;KL!7V< zokMqsvGe_|=5@btO+5_$n4%xL(bV$%59gX_e~Es@82w$Pe@gT}b^nyukG-TmA6e`R z^9OnnD>j>lJhEhR{{TDeAC>>Av!y%6fId&igQfH{r{exG>4$9zAGQ7-nPWd?1BPLd zm+MRXlhe`1pQ0aimei*kYo+?JA2ppcRMSuTyYCnulgH#A*utFP`-*dKvmbl=G43PO zv($Qy@AvvU$#K=xOV)&1-fDe(?+EjFPip=_>>ak%%~wi%hgJBG%WfN|GljDN&--NV zm~S&ZV(YuI`^E%&dDpQIm_v8o=SSbTg`0YTRlzRBrL9Zh_+znB`2?d(4Ln>NomQ!doLHljEoMk_VYwt5OTAJCWxPA}@dM M33KpE+j=8^0H9Cz?*IS* diff --git a/src/qt/icons/floppy_525_empty.ico b/src/qt/icons/floppy_525_empty.ico deleted file mode 100644 index 8fa6c6b87c333dee1e85e39c68e15470471d3305..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeI0J8soL6ov;WLP9htQlz{kB}+)f4lGKj5F4Q8mXs_Z1qE`Xq>U(0HjzyPiH;_X zIlrARapwAX9?lDNN4olb9{+ib@7Qt(&%#dF-3^AT@Np-EHz9<*y+J;G9>THd_V)+* z%Zm^`ybNKr8szWB`)$6jjANG;VbB|d1LIAs?n+mSVZC1W+)}i>9h`56hkXnWJ6oy~ zgeM)>9vA)D*;yY0RJdF&c|mx}PdxH~_<-oax%{#zHY<*SEW4KezK93vgOXe4IJ=unvoF82BBgcqc8FK??(LYrE@gBo{!d~4)Mw?)zKh^jQ$O5XR4wGm z<>bzixFz$41Ey*!sh^l&st^3O^@rf?L&^M!!Ca9̾*+C%wh#r8qFsUQ0__F`QSLFHI?z27l6Oh}OKa8qsG~MkEg#;J z{)qvW_OPUXa)PDzFuZO5_5Xin2yXZPu;?6Ia{n{y+S$X?{m*qSilY_#586$A>^GL} j`$J>jA=-RAZ`z}awt4%fX-_T(l-!uUD30Yl{?Yyg5+_;a diff --git a/src/qt/icons/floppy_525_empty_active.ico b/src/qt/icons/floppy_525_empty_active.ico deleted file mode 100644 index 703d2a64f6d3a3a3ac6726d3411e84959eccd8e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHLF>ll`6!ujG2{E)oD|O>WMt;JvFn6fc5hldQ!c0a+e!>k5l}~C{#84eS;&$dD zF~QO$ywAyZaeQ%XCsz(cjnXf+-}}Dzo*gHgQWLeW4iA;!RK3|(>V;D3=&0&{eyG%? zjGdfR{SS|ndi_|b>9p!!h~E#feJVb3D-6}RfSQS4M=R^G6oid?S=XW{tZxKMRfsRI znuk80=5x!@iQuVL9UtRh+(eEe zKHmF?IW&K~udh#^lxBWV>e+$CRgLWHw=#cwRqA&y<$Wcn!?=)nytm{NT0N7C@2ywz zE#1*t&xp(q>BGmpAVZ$4I>3>2vK)o*_*cU{__C&<<-Avt^w0A#yx~|5N;|L27Mihx+qAgs?&L z=d01pao0}k2l73&SL(A#X)aW$PgNT+el7Fw#qQb&>I&rt10z2i=sx^z?048y0-4Fh z@2~ja0)ex+B4j(^p$kPor&p8I4ZHk$n2a*^>ky2vl} zIq!{4xb6Gj)eGGt4vAr#`S*R7h*JAsqmT4Q=bxp`Na`52vi`!ATzgL+`Hzj^U(bK+ z{@;22b`dl7z?Swu_l?DzJ=o|EKL4nV)Y04+LeGMINaPRJ%k|G)f05%m#A@>oW8i+E z9uecXc#eXHad0e#A?;QS=+s&*lwtBy7p4R9hg+~wBZfk7XZgppN9G@1e@QB)&G{ku zyT0B6*qAsU!!h}j8}ZjMWNEwpjDur;3aN|ubNBzYVnqEI$576p{`4D@KRJlGIgH7l zn#9~Sq~Cr1!}mXHNW5SFdDb~NX8*I+Lu*ez?0?>;B7D$%`)YJ^+_!W4TAv*oGvCvC tHZi794JuXjiJV_f%;MXgKL2@au5OJ!|E101#%R6L^1FnfPRGkH<~P>c0FM9w diff --git a/src/qt/icons/hard_disk_active.ico b/src/qt/icons/hard_disk_active.ico deleted file mode 100644 index 9946a7f2e14e25dccc12b695f445fa2a63e96706..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeI1zm6P55QqC@3xpilfdglE2@;{-07pCrx&R^Z21FYY@(2zHECOQ4mc-9t3F$)Q z&;eqouV+7BUAt#@W_I^X;6Bw>cURZ%S6$P8X7@_DC=bh%CnfY%`Tk)k-;`3GJ{{Y? ze^$zG(f91x*#7B@Qoegs%GK4_eieRy$JnpJC#r!k_J=Aj!tcm3guk*BYABoVRYn{! z#O&+vp@jGCA2@+=eSLjU;N0i`%gdL;X0xe6y_LEC_}$#xRIcrITXASp7o!^Eqvl~3 zKYolsEc8*tA-?LvyhE6`^VeT4ebDq_#~&Xw?L+?fF7;=;F}HcB@&EY8BtLdJ<#j&T zzWj9u3yfa;jA=2zv0n^x(9R#sr9%E$z+kNrd_Q&>{)#8|=P<;Qin+{_%|(68 z^@DRJj+=Vka9&Yeh&jB#RM9Z-R&$B?xnyC1oEgpShYFE?m^I$xFJ!V|N_q74`JeE!eD6BGX|^ebSRGy1IO{E?Sq1WfQk>OCR%F~+snA89!D;h3x3;j$&#&wdn;a{%kvQLt#9L9`V7VApY^F|?wn2U&#B#d zJBq|J@538z$C@=w9_He+4?X+xo^1DgwjG1-SyTgz58Lv= zvlbsL&tSFqo~7^{gHPOIQjB(nE#A}T@G>4Vr!Fw@ww3Nx!dC73l=3~ z(=WcZiV;}gWpPdR;x{%ij&ObNyevcOsCY~?)LD>-fPdQ4{TUdB&xhgP2gC5sMZ9~B zXLfk_>=$YLwwlVCRzcHF)v_+ntW=xNp@3;9oF8Fi!&4c_s&fGV}-F^pN z!k=TvT)7T!=Eeu<@oJkpf5)Tq^T_o)hPwM|pU&g*`RiQnLmOXy2X5zb?lv*VANp+H y_4myq^BaS?xepEJr}A+#5I;a%#y^1K$A~u%HvCjD%E^NY?6M7c6ZoF#=>GtO+SvmD diff --git a/src/qt/icons/mo_active.ico b/src/qt/icons/mo_active.ico deleted file mode 100644 index 06b788b4d533b13cbf947d59592360fc02d4c612..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmchbJCYPf5Qb|b2qF|Rgn@ylH8FJrEY5+Y;BklDHZg$EF=X-ZbPnJgxxb|IB)H52aj{N9DnYx|$arF^!&XU}T;{V%2b z`D-cH*R}n(`Tc8ipPP?W4Wag1QC^te$}?O4Ifm0L14H#(I{swSWj43ZpY8eft@=`8 zZ{K#qhsQh)f8ZE~^Drp?k00mx)2Dg<`Lmj}xBLwQAP_3n*RS)8fd|GB|L!Y(eB|5w zX-h*TGODZ}-RPi<7_^(Y4}NCMUBoYcv{l^|~-@NH-y@(&J#0qcYu1j0<SPw9WS8E`h++W-+7U|&QH+>cZ z!PGT{C)p;R=4LDs0%qiEb2stg{ER7$snmPP-;eDb)#FKXiFGQ!+wgDQrcjUlTXkVj z^4_vf=<u5&JI z_^6}b#>frNhWeU6u!J4;gCjiNv*BHPHa>XhhL7At4so}>v-C%Nx<^79}e1Z#CJ3IE7so6z7Xjj=N{pMNq&fB?On|n#(6MJU}bauj1OMK7Y;GR_lx@J zBWBw8VLaj<;mem8&M`Q^;GAcCv}jywjD90*=72B$SX#bL!f#ld?UO-gGu(*X>pJV&oA9fi zOWmXTrc-JC&MnT-SB%EMH`~q6y&{ty_C40_8Dixz)Z>5X$o%OXd;Gf3#HliIqv7KG z+(F_Sm1t<+cPDWxJBJ*Q49}hOflE8)BlD;D@5A4@#Yf!m!>PW^AIDD3eTsjTpM3>C zInMkK5kDN-Z`bCgTQbXG}#=AOe( z{145KR%v7nE@{dM1+VN(qkoNBb}Gi<1)58DtLoYqSs5A32F( z)E@COmo=t@lY3v>(jh!B#itT&7+PiEfg=r!YY*AlF3!LB;kxhh{rf?C)^LoUJtzIj z1KO|_qrRQiN|z6Y@`ncM$Kq#>_%k;cm|^7Kton^J{OyWvw7?zr%_#rkr&P?8;-)k# z@$q{n8vVYeBmfKyZfQ8i&phIXNBoid6n^{_2O1)G<5}!K>4l$h@}-h`{Bw?k3LT=T zdemU{$n)1%Gh_}ok*4#o=1+HoG}Y(+^zDr+FJAMB)OcJkqvb z$LD9AR-*e>o~BvWv_`wrG9RSLqcl?k7YB|s%|~axt6XYs#XRTp=^3Hj)M=bEU-r_Z z1?AV~!-2Ts^f)%39_R5??bLN%H`Bh;&B?u|dIH?P$aX~LXOfBAR~M_TIV%%>;O=Mv1i zxaNDf{Jwuq{n0&|7rT%>R+MTxBbuO)(`!=^pRt6-*nz<#m%0di>?`+ zn$hd5iJ|8+Q9Y4vov*yFaNXNt&zd|h_0%~wKMlRKp?vb>=kt55HtN~ZHb1>OH(t}u zSe`a-sGdltJoxH?*^?ewrz2m|eB{LGA%^>~s4!^V5QQVQQOSeLg=8zG9eKG%_!y zGoN2Aaio>rr_4{A|GAj`uQ9(ppnccQKmSBMkk$z8J)a-fc{~;ML9@;0m-7sX^%S>e z>Bj=ifM>t8`Q=iZr|%g)&w1g~7FRtr)yzYiCcfDGsf{-++)0IU=^>_xSMyb0YU8UH z#~f2|EB*y zaJj(Sh_gP9mwLC;_ppoZ^P&Iw9(G+nT#k>$^VMnpRot8x$XonxVfoO``(_k-rbamG z%lnOQU5-(WmgfY@L+>@}W>X*GDf`nLX{0xvKC_H=JY|2HBQ%3LZ)gT}So@cM9XTJ) z7V_qms6X|~axz}=c5mq2!t@kpU!I4uPA|RoN{x(@r$2eQKi@hBYI@aDJ2f-bpZQU| zwm&X!C=YohswdjfHL&9;`{xWiX+in)9>w$hN4>luuhf(u>DXW2+WuJ+^B!sAnL#{4 zyi@k4vE_|NTMR#Ee;Olgb+|Pvo&W3p_Hd897Sesm{_a7&v=X<@J-(gh&%atCZ`z|7 zM)}mkn_vIrhdqLQ{d?a^5zOM zxx!Fc)89^YZrA**7FyB!IC*|3*Qt@T^^+_o|mQtQS-^YJ{S<0U^ z_u|Dq{_U$$e)+nTmoNA6+uHX}t^Ka{)WgcK&sQi{weQHbo7RqDto3_qS+Cc#9&y55 zS=V0s#G~fp$B&Hz{&92D;)b;+w%UF87d(58wirfmy?_6{^?v&FsbOdy>yO^HUXea* zTqpYV($`DB#S=#}QvbB`P-XS-3~`A0aQ^i5-sNUJwLpy1xs9=Nk9dT*toQo(&8=2m zyri$jxg4S1C4Kz3V!rTKw}v?TbvzJ<8LqFdXB>Lf2f1TwP%osfzVDUO3+2tQkS}U7 zUQf>@%2B@2l8;ukWZM+w6SS zx?^#yE$xloJUGMyJiL3>mD4`)>v4WFy6+m+-gYeyZ==Ie@a{QVQ5enK`5s$*KVj_n zg3CRW{fXOsTYEmo-;ApbaGGy4BQE$k{+u^lvv``h4c`4Z^`6B6UFR0Zxlg+}`)eVG z1M-Pe4CUjpW)3w_tvGA6>s^WP^#1f%I~Qs8{&0Ceiur+g9T)B1AMd9ybJFhp;mza->nzN)-vLR*`NNh6$ePo;6H?{7PIBNSnWb_wvUW$!lU3v0;;J&@@Tu&Ne==p@VoIZzo484QK@H5H1 zO~bPm-0fcMIrH(Pk^PEC+)d*G{F+=dE zuZMU1j=Kj#5Yb_%`InRGa^~d~YELVg7xh8jdjE2sA+esQ4KH<@ zArI=zx8z?gbJO%a!{<3I^|-~co;j`YgBz!MG5?ucT^qO-1iFZwdKdh1cc zhc#%9%q<@EEphXO8;&$^sLL4ZBhFmQuX^#wzq+bX9G}AL>GuG2IhKdPyQ$Lz>&(r`9n)!QI#Qb!+?SxFvInC_Ja{|@D_O7Yi z?VeuJ&AISVJ)ATDNOPtgL)=e4I`6!L^8B<$c#*bqaX1Hy9!6R@fAP6r(9iFp|8xGV z<$C-4%Jb&Dc_Z zY2zMw80GOmb^ZL-GSZgM9&pL4hx(xUrTKBVAMT5^A?=Jy^Yb<8pKJ`$(tH1O7(^4yjBW-!}>(AQq z$L6P%5f?3Uz&t;#j9vYm`PE*k&6D}_^~MW%t$6E!FEx;tbLYR0Hmy@=PF|tB`A_l0 z*m~9GSUw{y_0T!Z^*Qe9i{o?gI{n_DZb+UlB}BnSjV@dv2}>+`@VEt z|56yJV>-3SA9wG_=vl`y{)l|K@`3E0jFV*2r3WeKFo1 z-||)&j&H16;$8Fk({tr;9=Q_q58FguN2jOJ<{%)esvKW2rbqa5hq{dsQ4?@ zjnFIbYR`yATHhK*bfAp`Py69tl2s3C{yEmUN8c4ct)Cv?1H*X}&$z1k+XVibo14h{ z!-o&Ol{)ZO3~*NJSS)_zj~~lS!SI>pm^^mzX;mzXKixHyQG=1H3BHi6i0Fo<-Mo&u{5`TkpuQ_AmFaB|exq z@6;#vYihwlV!!e;rsuZdZ+PsFbJjdtV-tfoc5019--+2IUI&9X^38aGCBLB15a+So zuJFLA+C`s@g#|}uqxx=7IWvyO(>+Ub_}p8^t+T`<*rneG#s_m9M)qesVy3?z9*WoU zh<=jqL+~8CWE)Q|ZS9!&bzECr1>ecf>KWdD2gOBwK&EH6M z5A-{$dp_1%&F?Pyp5I&g2wlFB`uEm%`Ye4Ui8B?}IyowzL4v%Yn<5#au@tOOKu@%4FMddxj?J(}xBfM3P;~YFYgu~dv4*_G7 zRxbB^b3K9Ga?ki0kM2&M!%c5E2jZ~^zD2EAhA*3P&uhjs2iS~992J{f2LWT7_`KO` zT;D4=oW}r~2FAxOeXfAp_ex;{mNBsjZZ^#L#QQs_zlRzhoADXXz!n@c{K@xR<5R<^ zPY2?+ydqcn<-F~8U)p>jf4>5E@wteg@~SbT=NogcZO$U^^LQ}=PQS0Qfp6aYnag9Z z)jW(z9Ma;uc)RErm49dcnO$-7zErFf(P;Y*`zv2*d54X0d%tFW{8`OC?e8J{U{O3a z#>}%SPp{chWmHNXO?T#YcZd@<+*5%kdaW+c&{8*chC3FcX6Yg)(xlVZzVc@B1a|K1Fqkx6Qbl#=)sLbMxG(HLX79F7Z0A z6~CB+pXz+})o$WvEx2XDobnrgUH|cWPwgu`Kq{_tS(n3_0ZYYgw|se^}p@WALk<0^XtGTw7m&J4nFE z=ep}S_v0Yq6y#bCu?c49p`IugdXk;pUzO9h`cpyE^69>mPj_SO%1BN$LrAn7^^dH-s#(e+) diff --git a/src/qt/icons/network_empty.ico b/src/qt/icons/network_empty.ico deleted file mode 100644 index 4a1a102846ea018ba6d899b5352dd9fbdcfce858..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6950 zcmeHLJ#Q015S{qj1WO4@kuoJEKY@xW1qIUsq z+(bghdow$GXI~r%I^cF?&+dHf>{@wmHzEhplcOVn9La~i$U6}^IkEX@Ao2;i(^H#& z!F+Kja&~6(k0X)UE0NcTK?;Fd^FZuvM_BCm_*l-*&*k#+Qf9N6q-iQwS66a~J5*p}fFns2#BrfZ_;>&<0p;3`NHk z6Rn_TXMQSU080XbTKje(lI0>vBC^UvzCvb@oJUDJ{Q!GOx-E&bfM&&8;`MXQ@wJYt z#MJxy`xaN9JGj=?p1{9-0v!NYfUvO+2(MAuQD7P1o9NmhZkn~L3Mx5A!)*{l_Y0s$ z+$LzU$7RgVmOv=iV`nIrQ@=4&LdgYeWlYA}sWe~p@bC`QTAxPh*Ff{?(7n1^XK)z< z=mS}J5dDV0=s-B8wqgP;nX1a?k&sn|TT1hds&ccIJo^lse-E5D`8~Ul2c6$+>1i*L zwPf?P6w{_$E!T?wxRT2oeEyUN+Pii9dD=mH0{`y`7`TW1``wlR78yY>#O)Y3N~AP& zR;H?}okspu`kQp8< zoL4djZ*fjZ|2bp|Swfakt}x$V{+O4_V`o_UEk3`?W4E`r?f-~yZf$E%pgn=c3D`TL zp*984ukmLbsQQ^*nI7&P-Y3gp<>h1?Pxh@OlghB}cL$3zEvF41wqn~b_)&21G9$ejCDZIQ>v=*26#ghPljYEDIX#e8XsoIL2O1w6shHVQQzD)w z>)RVtv+PIwW_NDxI1$iN@9VCvdhd15-pqPr=O%8??e9Cq z1NY&cbGMyyH*SRaPp>%lqsDID4D&Bub?$@LoI5xO^Y69p56yi`Yjmg#A+F#KweGyF zEK7-MY)p^By+dDHbLd#2?s<9((G6%GsHMc_-5hDHfE zj>d5jeXF+yFZvqtd+5_=-D+t$2Xi>cQ{;T2P#97}4zrX^huZt|d7J0reQt7;yDgK~X1Y9Wo{rqBraTdITIc;y+;IpxD#LdsMSiBy_d{0t; zj90cpO0Mb5zKSW^g5eX()^rSxKe*UU-PUs z?bKNYV=(9H=JedHkDLQ8koyowejl0u_ho9}(k0HsBkNJz%B_(XX8MU9+&L#)idF+Qt5he zIFV|8U5dMJN>x>|c=t?}4_?ShUnHy*~s4w zvs>TlGQE7hOW&`fZFI&tbpMuXE%p$PZOJEee{9v><$-GhHoAlU{t|8W4;R{CupeIo zG)m=(`_}J1XVIz6S)mEyDXa$%>0Z&aXlNbx2CoSh`^_=;Kt6Fi7=KseEU2q7*)RL* z)25a@=BWprCFjmHuz0)Wzpry`=D8Lg+Kj^^aH0Vxb5I$RYeXLPV4g?356$V&{o6IQ zd~F`_5JKZV@x?yjWDcT9K6%U|^~7UGJPL&&9J|gzvy**Omm_(^nS;bZjXTC5`v$3H z-yr$Mv7_~!OREe{v_ax%gDrwf2%v?wQYL4QHhDu49`d(YC8y5=>)SXkx`qZGn6v*8 z{DZ#-aHFa70e?(EFzJ3DpV|FN#^WJbsj<`zcl%A!RFB9~A`uSN(KcvJKE=3VU&E;KD~4QyHQ|^%ZZUuLwdj)nvAh z?3ibeZYE&Zoyml7O>VZ+3t(hxP-@X z^e1ZhYPMWYC&c0Umhehg!WO2D(HUmkH}G08=bX}rw}rU}uZG!#mwmUmA|_QG_G@uH z{Ft8l+IkQpoU_$u&$ouhIp%RWUnp-ZbW{8so^pLjTdWHE5AD-?M19xc5zb0!9ZP=s zHg6-GPw9v8DZLpV(zke5O)@}JQilw{I0K9CEnK0~_Yl3ee!^XPXIZQnaM;FD>YIA% ze`h-%4_`Oz;W9rd-_@W!hSmLk)t(gY@(nlT!_V`(pfWt|p#m=VJbh$==j%W62aXo( zz4%q^aPE8kuVUkzF?V`744-Eh#bdL62)@Ja<=}X&Z80`ECLG5?pQZg=G!N@^f2#dpIuMAv~9j_^lk*;J0vGi@(Lug`eYRdkb-F z(lHm-;vdKEdH%ogL(a7L*4pA6YyLClZhX!q$|*(NwY~x0-%Uz&%QGwI7k!uaD*AmK zKH;s@_F&29*cR<)++SXdAJZM~UZ?R9Q+a@#A;T=EV!UBrZ6APl1}^Vm_mFoG-NOcc zxV*kp`5k;|oa^qY&R8*?@foPo*x~ZsV(%ICwNo3`1&2Ey{;b&ji1^|y-N4j0`BC+v zl~X>Dmjxbd|L8}>2jhwIF=*m0AYkEgbh4{Q^c*UHtV8|E);@`|s= zhuOZA%RBhRE#2$G;*Qu6f6YPM(mg&L#V>B@Rv(V!7q@ha4@dKhTYAffTkwlpy5_^J z_{A-~=EE-jd`2uk@;z{klcx(TCm(m~eot$j# zpYK!p{voB=Y-|6vx__4Y(Q52ZW7zr)(y7%ASnX4;Vjo49JD<-xytug7v8@oU7aZh* zH#aw3?rOE_5Sw^TfUmXX{s`eBKj)x^7`fNi*BvK_-`h}MTMGxXIEVIwpIk+HvB$0f zpK@s}Ha+_KlcT7;4&9#_B18}IygxCW6Tf0UKQ+u3A$j}y$AnZ(qSH_Mz!Hr zL>GQ1=Wj*s5k>O6_Tjv3*H>+Od)BtgOT)%+*|tp$TE0JL>~YgQZ~S@X>z6&FMy#DZ zvU=hxQVp z3*4uV*wER%_ubuH_Z(p#;J_{+`Doauj~VkE%k#x^ZwJYvu1ho_j>JH6B1C`w@56a~ z5u+AP?t5^tSQPbb8RPd8JxbW=viH-yy>B+nyj?F>_MV#Cd&=?L@XFp-5q{l?d%oBE zd&`c{>63kUZ+)|~^n|suAI5_{fpW{iUMprj2KQ1f?gd5ivR=h`xQCRhWY_c<%k90N zW(oHy;>NES&9iR~YPE*_Re#COdqfp(v(L2%H#kJU=i0~DUPJ@jefo)ME`CLNk`LnVM413bVv5SC zcAtLd^`$jaZRc!n+xF4UOAmH#y0>%Iruky$r%O9`HFmB7mv;VgyB@vXdHftUv(Kr0 zIEO9#i_7V2?|opj_@{Sx$pCkUrTss!mYtq@f2pn7rf7jnd(_(0kI|t2E^2#5c|$ZD zx;L6?G?aQ1kC0vw_Gy4Ksx8H-E9LFez`X*;RE#vx$22@Id{cXB{SXaNZsgZqksa0B z@I2E}G(Y}`BkEc5!|NA-zqJNGy+O?zYs2pvB5wSOLwi!Mb>12s8pBVmqUH~^;qRLt zPVJ3Nyo6DH&HQk~p-6lv4w)Zr?Tt-5!YFUZ{BXmiNW2!u%n!Hr#wM;9#mCGKH=K&Z zOE_hIxV1MnaWL{vnP0i-0TPd}W`1&}Vx*yO{;1|qer7Ta;q(7cy&|5P`MI7`Q8kR2 z-}U-_*&2jsR}IdC4vm%k#7l_Qh`$@g1UhPt+NEAmyl;N*>q~RsnySI6oj>C77>k~- zh2FQ_oZEj)upfY$X8veD{5;qXKKJ&+&!%b4*7ik&eV=e<-#<7ujs}j)sd#GyYvcP5 DJ}<5+ diff --git a/src/qt/icons/zip_empty_active.ico b/src/qt/icons/zip_empty_active.ico deleted file mode 100644 index d57860b1050ffb2520c1c04c337435f1fc4a50fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmchczi!+{5XSdxCq|IME*!v}Rl3X@_<{gwqr&V0Bvp{7kmxRD9zmtC0+KeBq?fpt zxFS%aMu5DT+2fB~j=1EKJbMHBU9qfO< zcJ6QSy?%YL|NO?e-@kS4U_pQ{(tuP$?0&XjHGgfGFQ`CE|A*z^retsVD z?CdPHgR7;M>%h};kPF`2+{D`J>+4t(WJz`RpYk*u)WjThYHotsGy1yfgN~*?&4nxW zmB7{2)ntGA4b~ctC`A5=`yl;oO|LJtpv=MkvBwf>=e1l>JGBYYLrZN9u^if2h2yCG z(UU`T5l{OQV{Ysmrt?$7d^sdWDcVOLu4Z2K8t|S=umSAs<}m z;A~r*qYoXUoQ3+}vU&#XhEr?O#WS|ET06%X>xCQSY_)qWH-oh!e$}V-?2+6)dJh-r zOM1XXo$}KMedJ6bb>w|1eQ2LTbb&+qh|Qf{d*9yPcAq67hl72YLh{itq>mZX9Ldua zds`%rx|k?J6p4Z4;Yn@1Pp{H8 zk%PUq7&&XZv5a9 z{nWAtAkP7NiT*(jc|bY;G4$uSnPaR+vlsDf>jAZU1Gn|V4bnsN(xraol@;Kk2GsnR z&>((`kxTi~OA6r~;viPq!}i1;(@#!m5Avu(W22;<}S6z^e^S4u0%ikT#9gmbM$Mj?xn0jL<8Jo`ia?G{1)j+K8Qbx z5&??DELu)$kLg!lUAAVet(;-^Jbdy`!^8Vcxc}(F-Kh(E!JVL26u=$i*QGr*#AS%T6){7(=(@kuctj< z#_oDP{^ixh4mu_^FsJF^25p%&p5>vw)~EY2p}~GG273w#e%~+WSoZS!XSI?os2)`B(MUPtnT$N|D>!oZmj1SsFyIw$#45a`WRa z(lBQalK%9t^Wdj9X!Ck@qao&U&Jt9=F5N5mb^hoR>~ST2;-Jmz**aUILu**-*Nc2@ zfew5ieyx?fRwFifIiyz)g@=6jQ*L4w>1omC +#include +#include "qt_iconindicators.hpp" + +QIcon +getIndicatorIcon(IconIndicator indicator) +{ + switch (indicator) { + case Active: + return QIcon(":/settings/qt/icons/active.ico"); + case Disabled: + return QIcon(":/settings/qt/icons/disabled.ico"); + default: + return QIcon(); + } +} + +QPixmap +getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator) +{ + auto iconPixmap = icon.pixmap(size, iconMode); + + if (indicator == None) + return iconPixmap; + + auto painter = QPainter(&iconPixmap); + auto indicatorPixmap = getIndicatorIcon(indicator).pixmap(size); + + painter.drawPixmap(0, 0, indicatorPixmap); + painter.end(); + + return iconPixmap; +} \ No newline at end of file diff --git a/src/qt/qt_iconindicators.hpp b/src/qt/qt_iconindicators.hpp new file mode 100644 index 000000000..553520063 --- /dev/null +++ b/src/qt/qt_iconindicators.hpp @@ -0,0 +1,15 @@ +#ifndef QT_ICONINDICATORS_HPP +# define QT_INDICATORS_HPP + +#include +#include + +enum IconIndicator { + None, + Active, + Disabled, +}; + +QPixmap getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator); + +#endif \ No newline at end of file diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index eff29a232..d555be360 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -54,6 +54,7 @@ extern "C" { #include "qt_mainwindow.hpp" #include "qt_soundgain.hpp" #include "qt_progsettings.hpp" +#include "qt_iconindicators.hpp" #include @@ -65,19 +66,24 @@ namespace { struct PixmapSetActive { QPixmap normal; QPixmap active; - void load(const QString &basePath); + void load(const QIcon &icon); +}; +struct PixmapSetDisabled { + QPixmap normal; + QPixmap disabled; + void load(const QIcon &icon); }; struct PixmapSetEmpty { QPixmap normal; QPixmap empty; - void load(const QString &basePath); + void load(const QIcon &icon); }; struct PixmapSetEmptyActive { QPixmap normal; QPixmap active; QPixmap empty; QPixmap empty_active; - void load(QString basePath); + void load(const QIcon &icon); }; struct Pixmaps { PixmapSetEmpty cartridge; @@ -90,7 +96,7 @@ struct Pixmaps { PixmapSetEmptyActive mo; PixmapSetActive hd; PixmapSetEmptyActive net; - QPixmap sound, soundMuted; + PixmapSetDisabled sound; }; struct StateActive { @@ -170,30 +176,35 @@ struct StateEmptyActive { }; static QSize pixmap_size(16, 16); -static const QString pixmap_empty = QStringLiteral("_empty"); -static const QString pixmap_active = QStringLiteral("_active"); -static const QString pixmap_empty_active = QStringLiteral("_empty_active"); + void -PixmapSetEmpty::load(const QString &basePath) +PixmapSetEmpty::load(const QIcon &icon) { - normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None); } void -PixmapSetActive::load(const QString &basePath) +PixmapSetActive::load(const QIcon &icon) { - normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); } void -PixmapSetEmptyActive::load(QString basePath) +PixmapSetDisabled::load(const QIcon &icon) { - normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); - empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); - empty_active = QIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + disabled = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Disabled); +} + +void +PixmapSetEmptyActive::load(const QIcon &icon) +{ + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); + empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None); + empty_active = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Active); } } @@ -202,21 +213,20 @@ struct MachineStatus::States { States(QObject *parent) { - pixmaps.cartridge.load(":/settings/qt/icons/cartridge%1.ico"); - pixmaps.cassette.load(":/settings/qt/icons/cassette%1.ico"); + pixmaps.cartridge.load(QIcon(":/settings/qt/icons/cartridge.ico")); + pixmaps.cassette.load(QIcon(":/settings/qt/icons/cassette.ico")); pixmaps.floppy_disabled.normal = QIcon(":/settings/qt/icons/floppy_disabled.ico").pixmap(pixmap_size); pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal; - pixmaps.floppy_525.load(":/settings/qt/icons/floppy_525%1.ico"); - pixmaps.floppy_35.load(":/settings/qt/icons/floppy_35%1.ico"); - pixmaps.cdrom.load(":/settings/qt/icons/cdrom%1.ico"); - pixmaps.zip.load(":/settings/qt/icons/zip%1.ico"); - pixmaps.mo.load(":/settings/qt/icons/mo%1.ico"); - pixmaps.hd.load(":/settings/qt/icons/hard_disk%1.ico"); - pixmaps.net.load(":/settings/qt/icons/network%1.ico"); - pixmaps.sound = QIcon(":/settings/qt/icons/sound.ico").pixmap(pixmap_size); - pixmaps.soundMuted = QIcon(":/settings/qt/icons/sound_mute.ico").pixmap(pixmap_size); + pixmaps.floppy_525.load(QIcon(":/settings/qt/icons/floppy_525.ico")); + pixmaps.floppy_35.load(QIcon(":/settings/qt/icons/floppy_35.ico")); + pixmaps.cdrom.load(QIcon(":/settings/qt/icons/cdrom.ico")); + pixmaps.zip.load(QIcon(":/settings/qt/icons/zip.ico")); + pixmaps.mo.load(QIcon(":/settings/qt/icons/mo.ico")); + pixmaps.hd.load(QIcon(":/settings/qt/icons/hard_disk.ico")); + pixmaps.net.load(QIcon(":/settings/qt/icons/network.ico")); + pixmaps.sound.load(QIcon(":/settings/qt/icons/sound.ico")); cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; @@ -510,7 +520,7 @@ MachineStatus::refresh(QStatusBar *sbar) sound_muted ^= 1; config_save(); if (d->sound) - d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); }); @@ -694,7 +704,7 @@ MachineStatus::refresh(QStatusBar *sbar) } d->sound = std::make_unique(); - d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); if (muteUnmuteAction) muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 6ca323b89..dc8db2c06 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -1,16 +1,9 @@ qt/icons/cartridge.ico - qt/icons/cartridge_empty.ico qt/icons/cassette.ico - qt/icons/cassette_active.ico - qt/icons/cassette_empty.ico - qt/icons/cassette_empty_active.ico qt/icons/cdrom.ico - qt/icons/cdrom_active.ico qt/icons/cdrom_disabled.ico - qt/icons/cdrom_empty.ico - qt/icons/cdrom_empty_active.ico qt/icons/cdrom_mute.ico qt/icons/cdrom_unmute.ico qt/icons/cdrom_image.ico @@ -18,38 +11,24 @@ qt/icons/cdrom_host.ico qt/icons/display.ico qt/icons/floppy_35.ico - qt/icons/floppy_35_active.ico - qt/icons/floppy_35_empty.ico - qt/icons/floppy_35_empty_active.ico qt/icons/floppy_525.ico - qt/icons/floppy_525_active.ico - qt/icons/floppy_525_empty.ico - qt/icons/floppy_525_empty_active.ico qt/icons/floppy_and_cdrom_drives.ico qt/icons/floppy_disabled.ico qt/icons/hard_disk.ico - qt/icons/hard_disk_active.ico qt/icons/input_devices.ico qt/icons/machine.ico qt/icons/mo.ico - qt/icons/mo_active.ico qt/icons/mo_disabled.ico - qt/icons/mo_empty.ico - qt/icons/mo_empty_active.ico qt/icons/network.ico - qt/icons/network_active.ico - qt/icons/network_empty.ico qt/icons/other_peripherals.ico qt/icons/other_removable_devices.ico qt/icons/ports.ico qt/icons/sound.ico - qt/icons/sound_mute.ico qt/icons/storage_controllers.ico qt/icons/zip.ico - qt/icons/zip_active.ico qt/icons/zip_disabled.ico - qt/icons/zip_empty.ico - qt/icons/zip_empty_active.ico + qt/icons/active.ico + qt/icons/disabled.ico qt/icons/86Box-gray.ico qt/icons/86Box-green.ico qt/icons/86Box-red.ico From fcd6bd9c664564eb2e0d03086cafb46e6163d585 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 01:22:35 +0100 Subject: [PATCH 27/32] Serial: Give the OKI IF386AX 16450 serial ports instead of 8250. --- src/device/serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/device/serial.c b/src/device/serial.c index deb97225a..8483f7fe3 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -999,7 +999,8 @@ void serial_standalone_init(void) { while (next_inst < SERIAL_MAX) - device_add_inst(&ns8250_device, next_inst + 1); + device_add_inst(!strcmp(machine_get_internal_name(), "if386sx") ? &ns16450_device : + &ns8250_device, next_inst + 1); }; const device_t ns8250_device = { From 2ed64c83996e762eb10c296666d759068c8ec69f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 08:11:04 +0100 Subject: [PATCH 28/32] Machine settings: Reduce the two loops to determine present machine types to a single loop, reduces the number of iterations from (number of machine types * number of machines) to just (number of machines), speeding things up. --- src/qt/qt_settingsmachine.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 9b1f9849e..34968b288 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -88,20 +88,31 @@ SettingsMachine::SettingsMachine(QWidget *parent) ui->comboBoxPitMode->setCurrentIndex(-1); ui->comboBoxPitMode->setCurrentIndex(pit_mode + 1); - int selectedMachineType = 0; - auto *machineTypesModel = ui->comboBoxMachineType->model(); - for (int i = 1; i < MACHINE_TYPE_MAX; ++i) { - int j = 0; - while (machine_get_internal_name_ex(j) != nullptr) { - if (machine_available(j) && (machine_get_type(j) == i)) { + int selectedMachineType = 0; + auto * machineTypesModel = ui->comboBoxMachineType->model(); + int i = -1; + int j = 0; + int cur_j = 0; + const void *miname; + do { + miname = machine_get_internal_name_ex(j); + + if ((miname == nullptr) || (machine_get_type(j) != i)) { + if ((i != -1) && (cur_j != 0)) { int row = Models::AddEntry(machineTypesModel, machine_types[i].name, machine_types[i].id); if (machine_types[i].id == machine_get_type(machine)) selectedMachineType = row; - break; } - j++; + + i = machine_get_type(j); + cur_j = 0; } - } + + if (machine_available(j)) + cur_j++; + + j++; + } while (miname != nullptr); ui->comboBoxMachineType->setCurrentIndex(-1); ui->comboBoxMachineType->setCurrentIndex(selectedMachineType); From bb22e1dccb39b0ce1af9bfbb3202c5a78da3bdb3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 08:14:30 +0100 Subject: [PATCH 29/32] Moved the Packard Bell PB450 to the correct place on the machines list. --- src/machine/machine_table.c | 80 ++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index aa9bae305..fa383139b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6981,46 +6981,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */ - { - .name = "[OPTi 895] Packard Bell PB450", - .internal_name = "pb450", - .type = MACHINE_TYPE_486_S3_PCI, - .chipset = MACHINE_CHIPSET_OPTI_895_802G, - .init = machine_at_pb450_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_PS2_PCI, - .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO, - .ram = { - .min = 1024, - .max = 65536, - .step = 1024 - }, - .nvrmask = 255, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = &pb450_device, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = &gd5428_vlb_onboard_device, - .snd_device = NULL, - .net_device = NULL - }, /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ { .name = "[SiS 461] Acer V10", @@ -7915,6 +7875,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */ + { + .name = "[OPTi 895] Packard Bell PB450", + .internal_name = "pb450", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_pb450_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_PS2_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &pb450_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5428_vlb_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[i420EX] ASUS PVI-486AP4", From 6d43f7e2df212fd7d9bf662a0fcf6caa18c75541 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:24:20 +0100 Subject: [PATCH 30/32] More fixes for 5380-based SCSI chips of the day (March 29th, 2025) 1. Avoid audio stops when they don't need to be. 2. And improved the MMIO-based NCR 53c400 timings to be similar to the port I/O-based one (T130B). 3. Minor timing fixes to the T128/PAS as well (especially for the hdd, when entering Windows 1.x using a SCSI HDD). --- src/scsi/scsi_ncr5380.c | 3 -- src/scsi/scsi_ncr53c400.c | 94 ++++++++++++++++++++++++++++----------- src/scsi/scsi_t128.c | 15 ++++--- 3 files changed, 77 insertions(+), 35 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 048194a96..132fade37 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -95,9 +95,6 @@ ncr5380_reset(ncr_t *ncr) ncr->timer(ncr->priv, 0.0); - for (int i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[ncr->bus][i]); - scsi_bus->state = STATE_IDLE; scsi_bus->clear_req = 0; scsi_bus->wait_complete = 0; diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index fc62a1cab..f91dc83a9 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -29,11 +29,11 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> -#include <86box/timer.h> #include <86box/dma.h> #include <86box/pic.h> #include <86box/mca.h> #include <86box/mem.h> +#include <86box/timer.h> #include <86box/rom.h> #include <86box/device.h> #include <86box/nvr.h> @@ -41,6 +41,7 @@ #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/scsi_ncr5380.h> +#include "cpu.h" #define LCS6821N_ROM "roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" #define COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.bin" @@ -80,6 +81,7 @@ typedef struct ncr53c400_t { int buffer_host_pos; int busy; + int reset; uint8_t pos_regs[8]; pc_timer_t timer; @@ -126,6 +128,9 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) addr &= 0x3fff; + if (addr >= 0x3880) + ncr53c400_log("%04X:%08X: memio_write(%04x)=%02x\n", CS, cpu_state.pc, addr, val); + if (addr >= 0x3a00) ncr400->ext_ram[addr - 0x3a00] = val; else { @@ -147,6 +152,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr400->busy = 1; + if (ncr400->type != ROM_T130B) + timer_on_auto(&ncr400->timer, 1.0); } } else ncr53c400_log("No Write.\n"); @@ -155,6 +162,19 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) case 0x3980: switch (addr) { case 0x3980: /* Control */ + /*Parity bits*/ + /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/ + /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/ + /*Required by RTASPI10.SYS otherwise it won't initialize.*/ + if (val & 0x80) { + if (ncr->mode & 0x30) { + if (!(ncr->mode & MODE_DMA)) { + ncr->mode = 0x00; + ncr400->reset = 1; + } + } + } + ncr53c400_log("NCR 53c400 control=%02x, mode=%02x.\n", val, ncr->mode); if ((val & CTRL_DATA_DIR) && !(ncr400->status_ctrl & CTRL_DATA_DIR)) { ncr400->buffer_host_pos = MIN(128, dev->buffer_length); @@ -180,10 +200,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) } if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { memset(ncr400->buffer, 0, MIN(128, dev->buffer_length)); - if (ncr400->type == ROM_T130B) - timer_on_auto(&ncr400->timer, 10.0); - else - timer_on_auto(&ncr400->timer, scsi_bus->period); + timer_on_auto(&ncr400->timer, 10.0); ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, p=%lf enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, scsi_bus->wait_data, scsi_bus->wait_complete, scsi_bus->clear_req, scsi_bus->period, timer_is_enabled(&ncr400->timer)); } else @@ -241,6 +258,20 @@ ncr53c400_read(uint32_t addr, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; + if (ncr400->type != ROM_T130B) { + if (!ncr400->block_count_loaded) { + scsi_bus->tx_mode = PIO_TX_BUS; + ncr53c400_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr53c400_log("NCR read irq\n"); + ncr5380_irq(ncr, 1); + } + } else if (!timer_is_enabled(&ncr400->timer)) { + ncr53c400_log("Timer re-enabled.\n"); + timer_on_auto(&ncr400->timer, 1.0); + } + } } } break; @@ -252,11 +283,10 @@ ncr53c400_read(uint32_t addr, void *priv) ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY); if (!ncr400->busy) ret |= STATUS_5380_ACCESSIBLE; - if (ncr->mode & 0x30) { /*Parity bits*/ - if (!(ncr->mode & MODE_DMA)) { /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/ - ret |= 0x01; /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/ - ncr->mode = 0x00; /*Required by RTASPI10.SYS otherwise it won't initialize.*/ - } + + if (ncr400->reset) { + ncr400->reset = 0; + ret |= 0x01; } ncr53c400_log("NCR 53c400 status=%02x.\n", ret); break; @@ -267,7 +297,10 @@ ncr53c400_read(uint32_t addr, void *priv) break; case 0x3982: /* switch register read */ - ret = 0xff; + if (ncr->irq != -1) { + ret = 0xf8; + ret += ncr->irq; + } ncr53c400_log("Switches read=%02x.\n", ret); break; @@ -282,7 +315,7 @@ ncr53c400_read(uint32_t addr, void *priv) } if (addr >= 0x3880) - ncr53c400_log("memio_read(%08x)=%02x\n", addr, ret); + ncr53c400_log("%04X:%08X: memio_read(%04x)=%02x\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -424,11 +457,8 @@ ncr53c400_callback(void *priv) uint8_t status; if (scsi_bus->tx_mode != PIO_TX_BUS) { - if (ncr400->type == ROM_T130B) { - ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0); - timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0); - } else - timer_on_auto(&ncr400->timer, 1.0); + ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0); + timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0); } if (scsi_bus->data_wait & 1) { @@ -538,14 +568,17 @@ ncr53c400_callback(void *priv) ncr400->block_count = (ncr400->block_count - 1) & 0xff; ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count); if (!ncr400->block_count) { - scsi_bus->tx_mode = PIO_TX_BUS; ncr400->block_count_loaded = 0; - ncr53c400_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr53c400_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); - } + if (ncr400->type == ROM_T130B) { + scsi_bus->tx_mode = PIO_TX_BUS; + ncr53c400_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr53c400_log("NCR read irq\n"); + ncr5380_irq(ncr, 1); + } + } else + timer_on_auto(&ncr400->timer, 1.0); } break; } @@ -732,8 +765,17 @@ ncr53c400_init(const device_t *info) scsi_bus_set_speed(ncr->bus, 5000000.0); scsi_bus->speed = 0.2; - scsi_bus->divider = 2.0; - scsi_bus->multi = 1.750; + if (ncr400->type == ROM_T130B) { + scsi_bus->divider = 2.0; + scsi_bus->multi = 1.750; + } else { + scsi_bus->divider = 1.0; + scsi_bus->multi = 1.0; + } + + for (int i = 0; i < 8; i++) + scsi_device_reset(&scsi_devices[ncr->bus][i]); + return ncr400; } diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index eada27246..3f273d1bb 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -95,9 +95,10 @@ t128_write(uint32_t addr, uint8_t val, void *priv) t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), t128->block_loaded); t128->status &= ~0x04; - timer_on_auto(&t128->timer, 10.0); + timer_on_auto(&t128->timer, 1.0); } - } + } else + t128_log("Write not allowed.\n"); } } @@ -136,20 +137,18 @@ t128_read(uint32_t addr, void *priv) t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n", t128->status, scsi_bus->period, timer_is_enabled(&t128->timer)); + t128->status &= ~0x04; if (!t128->block_loaded) { ncr->isr |= STATUS_END_OF_DMA; if (ncr->mode & MODE_ENA_EOP_INT) { t128_log("T128 read irq\n"); ncr5380_irq(ncr, 1); } - t128->status &= ~0x04; scsi_bus->bus_out |= BUS_CD; scsi_bus->tx_mode = PIO_TX_BUS; timer_stop(&t128->timer); } else if (!timer_is_enabled(&t128->timer)) - timer_on_auto(&t128->timer, 10.0); - else - t128->status &= ~0x04; + timer_on_auto(&t128->timer, 1.0); } } else { /*According to the WinNT DDK sources, just get the status timeout bit from here.*/ @@ -522,6 +521,10 @@ t128_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 1.0; scsi_bus->multi = 1.0; + + for (int i = 0; i < 8; i++) + scsi_device_reset(&scsi_devices[ncr->bus][i]); + return t128; } From c91f2255ad7795573ab2383e2a3205df69d308ad Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:42:25 +0100 Subject: [PATCH 31/32] Vast overhaul for the Mach8/32/8514/A (March 29th, 2025) 1. Implemented the FIFO test data to pass some tests of the Mach8 POST ROM and tests (not complete yet). 2. Overhauled the mode switches again, but this time with way less hacks and more on manual instructions. 3. Use a function pointer to determine if the Mach8 type used is a VGA combo or add-on. 4. Mach32 mode tests are no longer incorrectly green (was caused by improper pixtrans parts). 5. Implemented overscan color to the Mach32 as well as the CRT offset. 6. And fixed a PCI LFB GPF issue with the Mach32 2.3 drivers on Win3.1x. 7. Implemented memory boundary for both the Mach32 SVGA and its accelerator. 8. Added undocumented ports used by the FIFO (such as ports 0x8AEE and 0xEAEE). 9. Plus resetting the device right a la s3. 10. Temporarily switched the bus type of the Mach8 to 8-bit in both MCA and ISA variants. --- src/include/86box/vid_8514a.h | 21 +- src/include/86box/vid_ati_mach8.h | 14 +- src/video/vid_8514a.c | 696 +++++---- src/video/vid_ati_mach8.c | 2381 +++++++++++++++++++---------- 4 files changed, 1939 insertions(+), 1173 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index bfde22d5e..153bface4 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -18,6 +18,12 @@ #ifndef VIDEO_8514A_H #define VIDEO_8514A_H +#define INT_VSY (1 << 0) +#define INT_GE_BSY (1 << 1) +#define INT_FIFO_OVR (1 << 2) +#define INT_FIFO_EMP (1 << 3) +#define INT_MASK 0xf + typedef struct hwcursor8514_t { int ena; int x; @@ -61,6 +67,7 @@ typedef struct ibm8514_t { uint32_t vram_mask; uint32_t pallook[512]; uint32_t bios_addr; + uint32_t ma_latch; PALETTE vgapal; uint8_t hwcursor_oddeven; @@ -85,8 +92,8 @@ typedef struct ibm8514_t { uint16_t advfunc_cntl; uint16_t cur_y; uint16_t cur_x; - int16_t destx; - int16_t desty; + uint16_t destx; + uint16_t desty; int16_t desty_axstp; int16_t destx_distp; int16_t err_term; @@ -117,6 +124,8 @@ typedef struct ibm8514_t { int y1; int y2; int temp_cnt; + int16_t dx_ibm; + int16_t dy_ibm; int16_t cx; int16_t cx_back; int16_t cy; @@ -216,10 +225,9 @@ typedef struct ibm8514_t { uint16_t subsys_cntl; uint8_t subsys_stat; - atomic_int fifo_idx; - atomic_int ext_fifo_idx; atomic_int force_busy; atomic_int force_busy2; + atomic_int fifo_idx; int blitter_busy; uint64_t blitter_time; @@ -235,6 +243,11 @@ typedef struct ibm8514_t { PALETTE _8514pal; latch8514_t latch; + + void (*vblank_start)(void *priv); + void (*accel_out_fifo)(void *priv, uint16_t port, uint16_t val, int len); + void (*update_irqs)(void *priv); + } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index 849446def..4a5d3deb5 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -25,6 +25,7 @@ typedef struct mach_t { rom_t bios_rom; rom_t bios_rom2; mem_mapping_t mmio_linear_mapping; + mem_mapping_t banked_mapping; int mca_bus; int pci_bus; @@ -71,7 +72,12 @@ typedef struct mach_t { uint8_t bank_r; uint16_t shadow_set; uint16_t shadow_cntl; - int override_resolution; + uint8_t overscan_col_8; + uint8_t overscan_b_col_24; + uint8_t overscan_g_col_24; + uint8_t overscan_r_col_24; + uint16_t fifo_test_data[17]; + int resolution_crt; struct { uint8_t line_idx; @@ -79,9 +85,9 @@ typedef struct mach_t { uint8_t patt_idx; uint8_t patt_len; uint8_t pix_trans[2]; - uint8_t eeprom_control; uint8_t alu_bg_fn; uint8_t alu_fg_fn; + uint16_t eeprom_control; uint16_t clip_left; uint16_t clip_right; uint16_t clip_top; @@ -92,6 +98,7 @@ typedef struct mach_t { uint16_t src_x_end; uint16_t src_x_start; uint16_t src_x; + uint16_t r_src_x; uint16_t src_y; int16_t bres_count; uint16_t clock_sel; @@ -100,6 +107,8 @@ typedef struct mach_t { uint16_t dest_cmp_fn; uint16_t dp_config; uint16_t ext_ge_config; + uint16_t crt_offset_lo; + uint16_t crt_offset_hi; uint16_t ge_offset_lo; uint16_t ge_offset_hi; uint16_t linedraw_opt; @@ -159,6 +168,7 @@ typedef struct mach_t { } accel; atomic_int force_busy; + atomic_int fifo_test_idx; } mach_t; #endif /*VIDEO_ATI_MACH8_H*/ diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 765258237..efb05a307 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -15,6 +15,7 @@ * * Copyright 2022-2024 TheCollector1995. */ +#include #include #include #include @@ -32,7 +33,6 @@ #include <86box/mca.h> #include <86box/rom.h> #include <86box/plat.h> -#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_8514a.h> #include <86box/vid_8514a_device.h> @@ -153,12 +153,15 @@ CLAMP(int16_t in, int16_t min, int16_t max) dest_dat = ~(src_dat & dest_dat); \ break; \ case 0x09: \ + case 0x11: \ dest_dat = ~src_dat | dest_dat; \ break; \ case 0x0a: \ + case 0x12: \ dest_dat = src_dat | ~dest_dat; \ break; \ case 0x0b: \ + case 0x13: \ dest_dat = src_dat | dest_dat; \ break; \ case 0x0c: \ @@ -176,56 +179,43 @@ CLAMP(int16_t in, int16_t min, int16_t max) case 0x10: \ dest_dat = MIN(src_dat, dest_dat); \ break; \ - case 0x11: \ - dest_dat = dest_dat - src_dat; \ - break; \ - case 0x12: \ - dest_dat = src_dat - dest_dat; \ - break; \ - case 0x13: \ - dest_dat = src_dat + dest_dat; \ - break; \ case 0x14: \ dest_dat = MAX(src_dat, dest_dat); \ break; \ case 0x15: \ - dest_dat = (dest_dat - src_dat) >> 1; \ + dest_dat = (src_dat | ~dest_dat) >> 1; \ break; \ case 0x16: \ - dest_dat = (src_dat - dest_dat) >> 1; \ + dest_dat = (~src_dat | dest_dat) >> 1; \ break; \ case 0x17: \ - dest_dat = (dest_dat + src_dat) >> 1; \ + dest_dat = (src_dat | dest_dat) >> 1; \ break; \ case 0x18: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ case 0x19: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ + dest_dat = MAX(0, ~src_dat | dest_dat); \ break; \ case 0x1a: \ - dest_dat = MAX(0, (src_dat - dest_dat)); \ + dest_dat = MAX(0, src_dat | ~dest_dat); \ break; \ case 0x1b: \ if (dev->bpp) \ - dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xffff, src_dat | dest_dat); \ else \ - dest_dat = MIN(0xff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xff, src_dat | dest_dat); \ break; \ case 0x1c: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ - break; \ case 0x1d: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ + dest_dat = MAX(0, ~src_dat | dest_dat) >> 1; \ break; \ case 0x1e: \ - dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + dest_dat = MAX(0, src_dat | ~dest_dat) >> 1; \ break; \ case 0x1f: \ if (dev->bpp) \ - dest_dat = (0xffff < (src_dat + dest_dat)) ? 0xffff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xffff < (src_dat | dest_dat)) ? 0xffff : ((src_dat | dest_dat) >> 1); \ else \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xff < (src_dat | dest_dat)) ? 0xff : ((src_dat | dest_dat) >> 1); \ break; \ } \ } @@ -233,10 +223,10 @@ CLAMP(int16_t in, int16_t min, int16_t max) #define WRITE(addr, dat) \ if (dev->bpp) { \ vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ } else { \ dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; \ } int ibm8514_active = 0; @@ -246,7 +236,7 @@ ibm8514_cpu_src(svga_t *svga) { const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (!(dev->accel.cmd & 0x100)) + if (dev->accel.cmd_back) return 0; if (dev->accel.cmd & 1) @@ -260,7 +250,7 @@ ibm8514_cpu_dest(svga_t *svga) { const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (!(dev->accel.cmd & 0x100)) + if (dev->accel.cmd_back) return 0; if (dev->accel.cmd & 1) @@ -282,7 +272,7 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in int bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; int cmd = dev->accel.cmd >> 13; - if (dev->accel.cmd & 0x100) { + if (!dev->accel.cmd_back) { if (len == 2) { /*Bus size*/ if (dev->accel.cmd & 0x200) /*16-bit*/ @@ -344,27 +334,184 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port != 0x9ae8 && port != 0xe2e8) - ibm8514_log("Port OUT FIFO=%04x, val=%04x, len=%d.\n", port, val, len); - switch (port) { + case 0x2e8: + WRITE8(port, dev->htotal, val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + break; + + case 0x6e8: + /*In preparation to switch from VGA to 8514/A mode*/ + WRITE8(port, dev->hdisped, val); + dev->hdisp = (dev->hdisped + 1) << 3; + ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + svga_recalctimings(svga); + break; + + case 0x6e9: + WRITE8(port, dev->htotal, val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + break; + + case 0xae8: + WRITE8(port, dev->hsync_start, val); + pclog("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_start=%d.\n", port, val, (val + 1) << 3); + svga_recalctimings(svga); + break; + + case 0xee8: + WRITE8(port, dev->hsync_width, val); + pclog("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); + svga_recalctimings(svga); + break; + + case 0x12e8: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 2) { + dev->v_total_reg = val; + dev->v_total_reg &= 0x1fff; + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + } else { + WRITE8(port, dev->v_total_reg, val); + } + break; + case 0x12e9: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 1) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + } + break; + + case 0x16e8: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 2) { + dev->v_disp = val; + dev->v_disp &= 0x1fff; + dev->vdisp = (dev->v_disp + 1) >> 1; + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + svga_recalctimings(svga); + } else { + WRITE8(port, dev->v_disp, val); + } + break; + case 0x16e9: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 1) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = (dev->v_disp + 1) >> 1; + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + svga_recalctimings(svga); + } + break; + + case 0x1ae8: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 2) { + dev->v_sync_start = val; + dev->v_sync_start &= 0x1fff; + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); + svga_recalctimings(svga); + } else { + WRITE8(port, dev->v_sync_start, val); + } + break; + case 0x1ae9: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 1) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); + svga_recalctimings(svga); + } + break; + + case 0x22e8: + dev->disp_cntl = val; + dev->interlace = !!(dev->disp_cntl & 0x10); + ibm8514_log("IBM 8514/A compatible: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); + svga_recalctimings(svga); + break; + + case 0x1ee8: + case 0x1ee9: + ibm8514_log("IBM 8514/A compatible: V_SYNC_WID write 1EE8 = %02x\n", val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncwidth=0x%02x.\n", port, val); + svga_recalctimings(svga); + break; + + case 0x42e8: + ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + if (len == 2) { + dev->subsys_cntl = val; + dev->subsys_stat &= ~val; + if ((val & 0xc000) == 0x8000) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } + } else { + WRITE8(port, dev->subsys_cntl, val); + dev->subsys_stat &= ~val; + } + break; + case 0x42e9: + if (len == 1) { + WRITE8(port, dev->subsys_cntl, val); + if ((val & 0xc0) == 0x80) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } + } + break; + + case 0x4ae8: + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on = dev->accel.advfunc_cntl & 0x01; + ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", CS, cpu_state.pc, port, dev->on, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + ibm8514_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); + svga_recalctimings(svga); + break; + case 0x82e8: case 0xc2e8: - dev->fifo_idx++; if (len == 2) dev->accel.cur_y = val & 0x7ff; break; case 0x86e8: case 0xc6e8: - dev->fifo_idx++; if (len == 2) dev->accel.cur_x = val & 0x7ff; break; case 0x8ae8: case 0xcae8: - dev->fifo_idx++; if (len == 2) { dev->accel.desty = val & 0x7ff; dev->accel.desty_axstp = val & 0x3fff; @@ -375,7 +522,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x8ee8: case 0xcee8: - dev->fifo_idx++; if (len == 2) { dev->accel.destx = val & 0x7ff; dev->accel.destx_distp = val & 0x3fff; @@ -385,7 +531,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x92e8: - dev->fifo_idx++; if (len == 2) dev->test = val; fallthrough; @@ -400,7 +545,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x96e8: case 0xd6e8: - dev->fifo_idx++; if (len == 2) { dev->accel.maj_axis_pcnt = val & 0x7ff; dev->accel.maj_axis_pcnt_no_limit = val; @@ -409,7 +553,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x9ae8: case 0xdae8: - dev->fifo_idx++; dev->accel.ssv_state = 0; if (len == 2) { dev->data_available = 0; @@ -419,14 +562,13 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; - ibm8514_log("8514/A CMD=%04x, back=%d.\n", dev->accel.cmd, dev->accel.cmd_back); + ibm8514_log("8514/A CMD=%04x, back=%d, frgd color=%04x, frgdmix=%02x, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.cmd_back, dev->accel.frgd_color, dev->accel.frgd_mix, dev->accel.multifunc[0x0a]); ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; case 0x9ee8: case 0xdee8: - dev->fifo_idx++; dev->accel.ssv_state = 1; if (len == 2) { dev->accel.short_stroke = val; @@ -451,7 +593,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0xa2e8: case 0xe2e8: - dev->fifo_idx++; if (port == 0xe2e8) { if (len == 2) { if (dev->accel.cmd_back) @@ -470,7 +611,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0xa6e8: case 0xe6e8: - dev->fifo_idx++; if (port == 0xe6e8) { if (len == 2) { if (dev->accel.cmd_back) @@ -489,40 +629,34 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0xaae8: case 0xeae8: - dev->fifo_idx++; if (len == 2) dev->accel.wrt_mask = val; break; case 0xaee8: case 0xeee8: - dev->fifo_idx++; if (len == 2) dev->accel.rd_mask = val; break; case 0xb2e8: case 0xf2e8: - dev->fifo_idx++; if (len == 2) dev->accel.color_cmp = val; break; case 0xb6e8: case 0xf6e8: - dev->fifo_idx++; dev->accel.bkgd_mix = val & 0xff; break; case 0xbae8: case 0xfae8: - dev->fifo_idx++; dev->accel.frgd_mix = val & 0xff; break; case 0xbee8: case 0xfee8: - dev->fifo_idx++; if (len == 2) { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; @@ -631,115 +765,13 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - ibm8514_accel_out_fifo(svga, port, val, len); - else { - switch (port) { - case 0x2e8: - case 0x6e9: - WRITE8(port, dev->htotal, val); - ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x6e8: - /*In preparation to switch from VGA to 8514/A mode*/ - dev->hdisped = val; - dev->hdisp = (dev->hdisped + 1) << 3; - ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); - svga_recalctimings(svga); - break; - - case 0xae8: - dev->hsync_start = val; - ibm8514_log("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_start=%d.\n", port, val, (val + 1) << 3); - svga_recalctimings(svga); - break; - - case 0xee8: - dev->hsync_width = val; - ibm8514_log("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); - svga_recalctimings(svga); - break; - - case 0x12e8: - case 0x12e9: - /*In preparation to switch from VGA to 8514/A mode*/ - WRITE8(port, dev->v_total_reg, val); - dev->v_total_reg &= 0x1fff; - dev->v_total = dev->v_total_reg + 1; - if (dev->interlace) - dev->v_total >>= 1; - - ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x16e8: - case 0x16e9: - /*In preparation to switch from VGA to 8514/A mode*/ - WRITE8(port, dev->v_disp, val); - dev->v_disp &= 0x1fff; - dev->vdisp = (dev->v_disp + 1) >> 1; - ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); - ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x1ae8: - case 0x1ae9: - /*In preparation to switch from VGA to 8514/A mode*/ - WRITE8(port, dev->v_sync_start, val); - dev->v_sync_start &= 0x1fff; - dev->v_syncstart = dev->v_sync_start + 1; - if (dev->interlace) - dev->v_syncstart >>= 1; - - ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); - ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x1ee8: - case 0x1ee9: - ibm8514_log("IBM 8514/A compatible: V_SYNC_WID write 1EE8 = %02x\n", val); - ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncwidth=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x22e8: - dev->disp_cntl = val; - dev->interlace = !!(dev->disp_cntl & 0x10); - ibm8514_log("IBM 8514/A compatible: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); - svga_recalctimings(svga); - break; - - case 0x42e8: - ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); - dev->subsys_cntl = (dev->subsys_cntl & 0xff00) | val; - dev->subsys_stat &= ~val; - break; - case 0x42e9: - dev->subsys_cntl = (dev->subsys_cntl & 0xff) | (val << 8); - if ((val & 0xc0) == 0x80) { - dev->fifo_idx = 0; - dev->force_busy = 0; - dev->force_busy2 = 0; - } - break; - - case 0x4ae8: - WRITE8(port, dev->accel.advfunc_cntl, val); - dev->on = dev->accel.advfunc_cntl & 0x01; - ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", CS, cpu_state.pc, port, dev->on, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); - ibm8514_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); - svga_recalctimings(svga); - break; - - default: - break; - } + if (dev->accel.cmd_back) { + dev->fifo_idx++; + if (dev->fifo_idx > 8) + dev->fifo_idx = 8; } + + ibm8514_accel_out_fifo(svga, port, val, len); } static void @@ -790,28 +822,21 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) case 0x9ae8: case 0xdae8: - if ((dev->fifo_idx >= 1) && (dev->fifo_idx <= 8)) { - temp |= (1 << (dev->fifo_idx - 1)); - switch (dev->accel.cmd >> 13) { - case 2: - case 3: - case 4: - case 6: - if (dev->accel.sy < 0) - dev->fifo_idx = 0; - break; - default: - if (!dev->accel.sy) - dev->fifo_idx = 0; - break; - } - } if (len == 2) { + if (dev->fifo_idx <= 8) { + for (int i = 1; i <= dev->fifo_idx; i++) + temp |= (1 << (7 - (i - 1))); + } else + temp = 0x00ff; + + if (dev->fifo_idx > 0) + dev->fifo_idx--; + if (dev->force_busy) - temp |= 0x200; /*Hardware busy*/ + temp |= 0x0200; /*Hardware busy*/ dev->force_busy = 0; if (dev->data_available) { - temp |= 0x100; /*Read Data available*/ + temp |= 0x0100; /*Read Data available*/ dev->data_available = 0; } } @@ -819,8 +844,11 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) case 0x9ae9: case 0xdae9: if (len == 1) { + dev->fifo_idx = 0; + if (dev->force_busy2) temp |= 0x02; /*Hardware busy*/ + dev->force_busy2 = 0; if (dev->data_available2) { temp |= 0x01; /*Read Data available*/ @@ -868,7 +896,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) switch (port) { case 0x2e8: - if (dev->vc == dev->dispend) + if (dev->vc == dev->v_syncstart) temp |= 0x02; ibm8514_log("Read: Display Status1=%02x.\n", temp); @@ -896,36 +924,35 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) case 0x42e8: case 0x42e9: - if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) - temp |= 0x01; + if (!(port & 1)) { + if ((dev->subsys_cntl & INT_VSY) && !(dev->subsys_stat & INT_VSY) && (dev->vc == dev->dispend)) + temp |= INT_VSY; - if (cmd == 6) { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r_ibm) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b_ibm)) - temp |= 0x02; - } else { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r_ibm) && - (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b_ibm)) - temp |= 0x02; - } + if (cmd == 6) { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r_ibm) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b_ibm)) + temp |= INT_GE_BSY; + } else { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r_ibm) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b_ibm)) + temp |= INT_GE_BSY; + } - if (!dev->fifo_idx) { - if (!dev->force_busy && !dev->force_busy2) - temp |= 0x08; - } - - if (port & 1) { - temp = dev->vram_512k_8514 ? 0x00 : 0x80; - temp |= (dev->subsys_cntl >> 8); - } else { + if (dev->accel.cmd_back) { + dev->force_busy = 0; + dev->force_busy2 = 0; + dev->data_available = 0; + dev->data_available2 = 0; + temp |= INT_FIFO_EMP; + } temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); temp |= 0x20; } @@ -1024,7 +1051,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat rd_mask_polygon &= 0xff; } - if (dev->accel.cmd & 0x100) { + if (!dev->accel.cmd_back) { dev->force_busy = 1; dev->force_busy2 = 1; } @@ -1129,8 +1156,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_mix_dat = mix_dat; - if (cmd == 5 || cmd == 1 || (cmd == 2 && (dev->accel.multifunc[0x0a] & 0x06))) - ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06); + if (cmd != 0) + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on @@ -1146,7 +1173,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1197,6 +1224,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.ssv_len) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1242,7 +1270,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1293,6 +1321,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.ssv_len) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1378,7 +1407,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { @@ -1468,6 +1497,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; if (!cpu_input) { dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1537,7 +1567,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga)) { READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); } else @@ -1588,6 +1618,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1629,7 +1660,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { @@ -1691,6 +1722,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; if (!cpu_input) { dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1828,7 +1860,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1970,8 +2002,10 @@ skip_vector_rect_write: dev->accel.sy--; dev->accel.x_count = 0; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -1986,7 +2020,7 @@ skip_vector_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { @@ -2129,8 +2163,10 @@ skip_nibble_rect_write: dev->accel.sy--; dev->accel.x_count = 0; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -2148,7 +2184,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2215,8 +2251,10 @@ skip_nibble_rect_write: dev->accel.sy--; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -2231,7 +2269,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2301,6 +2339,7 @@ skip_nibble_rect_write: dev->accel.cur_y = dev->accel.cy; } dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -2313,7 +2352,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2412,6 +2451,7 @@ skip_nibble_rect_write: if (dev->accel.sy < 0) { ibm8514_log(".\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; return; @@ -2419,13 +2459,13 @@ skip_nibble_rect_write: } } } else { - ibm8514_log("Polygon Draw Type=%02x, CX=%d, CY=%d, SY=%d, CL=%d, CR=%d.\n", dev->accel.multifunc[0x0a] & 0x06, dev->accel.cx, dev->accel.cy, dev->accel.sy, clip_l, clip_r); + ibm8514_log("Polygon Draw Type=%02x, CX=%d, CY=%d, SY=%d, CL=%d, CR=%d, frgdmix=%d, bkgdmix=%d, cmpmode=%02x, pitch=%d.\n", dev->accel.multifunc[0x0a] & 0x06, dev->accel.cx, dev->accel.cy, dev->accel.sy, clip_l, clip_r, frgd_mix, bkgd_mix, compare_mode, dev->pitch); while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2501,6 +2541,7 @@ skip_nibble_rect_write: dev->accel.cur_y = dev->accel.cy; } dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -2548,7 +2589,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2603,6 +2644,7 @@ skip_nibble_rect_write: if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -2656,7 +2698,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2707,6 +2749,7 @@ skip_nibble_rect_write: if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -2753,13 +2796,8 @@ skip_nibble_rect_write: { dev->accel.x_count = 0; - dev->accel.dx = dev->accel.destx; - if (dev->accel.destx >= 0x600) - dev->accel.dx |= ~0x5ff; - - dev->accel.dy = dev->accel.desty; - if (dev->accel.desty >= 0x600) - dev->accel.dy |= ~0x5ff; + dev->accel.dx_ibm = dev->accel.destx; + dev->accel.dy_ibm = dev->accel.desty; dev->accel.cx = dev->accel.cur_x; if (dev->accel.cur_x >= 0x600) @@ -2774,13 +2812,13 @@ skip_nibble_rect_write: if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.fill_state = 0; @@ -2805,17 +2843,16 @@ skip_nibble_rect_write: dev->data_available = 1; dev->data_available2 = 1; return; /*Wait for data from CPU*/ - } + } else + ibm8514_log("BitBLT normal: Parameters: DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, dstheight=%d, clipl=%d, clipr=%d, clipt=%d, clipb=%d.\n", dev->accel.dx_ibm, dev->accel.dy_ibm, dev->accel.cx, dev->accel.cy, dev->accel.sx, dev->accel.sy, clip_l, clip_r, clip_t, clip_b); } - ibm8514_log("BitBLT: full=%04x, odd=%d, c(%d,%d), d(%d,%d), xcount=%d, and3=%d, len(%d,%d), CURX=%d, Width=%d, pixcntl=%d, mix_dat=%08x, count=%d, cpu_data=%08x, cpu_input=%d.\n", dev->accel.cmd, dev->accel.input, dev->accel.cx, dev->accel.cy, dev->accel.dx, dev->accel.dy, dev->accel.x_count, and3, dev->accel.sx, dev->accel.sy, dev->accel.cur_x, dev->accel.maj_axis_pcnt, pixcntl, mix_dat, count, cpu_dat, cpu_input); if (cpu_input) { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2879,7 +2916,7 @@ skip_nibble_rect_write: } } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -2895,20 +2932,20 @@ skip_nibble_rect_write: goto skip_nibble_bitblt_write; dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } else { MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } } if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -2935,37 +2972,39 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; dev->accel.x_count = 0; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -2979,11 +3018,10 @@ skip_nibble_bitblt_write: mix_dat >>= 8; dev->accel.temp_cnt = 8; } - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3002,7 +3040,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3014,7 +3052,7 @@ skip_nibble_bitblt_write: old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } @@ -3025,10 +3063,10 @@ skip_nibble_bitblt_write: } if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -3037,36 +3075,38 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -3077,11 +3117,10 @@ skip_nibble_bitblt_write: dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3100,7 +3139,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3112,7 +3151,7 @@ skip_nibble_bitblt_write: old_dest_dat = dest_dat; MIX(mix_dat & 0x01, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } @@ -3120,10 +3159,10 @@ skip_nibble_bitblt_write: mix_dat >>= 1; if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -3132,37 +3171,38 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.destx = dev->accel.dx; - dev->accel.desty = dev->accel.dy; + dev->accel.destx = dev->accel.dx_ibm; + dev->accel.desty = dev->accel.dy_ibm; dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -3174,15 +3214,13 @@ skip_nibble_bitblt_write: int64_t dx; cx = (int64_t) dev->accel.cx; - dx = (int64_t) dev->accel.dx; + dx = (int64_t) dev->accel.dx_ibm; while (1) { if ((dx >= (((int64_t)clip_l) * 3)) && (dx <= (((uint64_t)clip_r) * 3)) && - (dev->accel.dy >= (clip_t << 1)) && - (dev->accel.dy <= (clip_b << 1))) { - dev->subsys_stat |= 0x02; - + (dev->accel.dy_ibm >= (clip_t << 1)) && + (dev->accel.dy_ibm <= (clip_b << 1))) { READ(dev->accel.src + cx, src_dat); READ(dev->accel.dest + dx, dest_dat); dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); @@ -3195,16 +3233,16 @@ skip_nibble_bitblt_write: dev->accel.sx--; if (dev->accel.sx < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } } else { while (count-- && dev->accel.sy >= 0) { - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -3238,7 +3276,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3250,12 +3288,14 @@ skip_nibble_bitblt_write: old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (dev->accel.cmd & 0x04) { if (dev->accel.sx) { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } else { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + ibm8514_log("BitBLT DX=%d, DY=%d, data=%02x, old=%02x, src=%02x, frmix=%02x, bkmix=%02x, pixcntl=%d.\n", dev->accel.dx_ibm, dev->accel.dy_ibm, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); } } } @@ -3264,10 +3304,10 @@ skip_nibble_bitblt_write: mix_dat |= 1; if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -3277,37 +3317,38 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.destx = dev->accel.dx; - dev->accel.desty = dev->accel.dy; + dev->accel.destx = dev->accel.dx_ibm; + dev->accel.desty = dev->accel.dy_ibm; dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -3334,7 +3375,7 @@ ibm8514_render_blank(svga_t *svga) dev->firstline_draw = dev->displine; dev->lastline_draw = dev->displine; - uint32_t *line_ptr = &svga->monitor->target_buffer->line[dev->displine + svga->y_add][svga->x_add]; + uint32_t *line_ptr = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; uint32_t line_width = (uint32_t)(dev->h_disp) * sizeof(uint32_t); if (dev->h_disp > 0) @@ -3628,7 +3669,7 @@ ibm8514_poll(void *priv) int wx; int wy; - ibm8514_log("IBM 8514/A poll=%x.\n", dev->on); + ibm8514_log("IBM 8514/A poll=%x offtime=%" PRIu64 ", ontime=%" PRIu64 ".\n", dev->on, dev->dispofftime, dev->dispontime); if (dev->on) { ibm8514_log("ON!\n"); if (!dev->linepos) { @@ -3713,7 +3754,7 @@ ibm8514_poll(void *priv) dev->vc &= 0xfff; if (dev->vc == dev->dispend) { - dev->subsys_stat |= 0x01; + dev->vblank_start(svga); ibm8514_log("VBLANK irq.\n"); dev->dispon = 0; @@ -3751,16 +3792,16 @@ ibm8514_poll(void *priv) svga->vslines = 0; if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = (dev->rowoffset << 1); + dev->ma = dev->maback = dev->ma_latch + (dev->rowoffset << 1); else - dev->ma = dev->maback = 0; + dev->ma = dev->maback = dev->ma_latch; dev->ma = (dev->ma << 2); dev->maback = (dev->maback << 2); } if (dev->vc == dev->v_total) { dev->vc = 0; - dev->sc = 0; + dev->sc = (svga->crtc[0x8] & 0x1f); dev->dispon = 1; dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; @@ -3876,6 +3917,15 @@ ibm8514_mca_reset(void *priv) svga_set_poll(svga); } +static void +ibm8514_vblank_start(void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + dev->subsys_stat |= INT_VSY; +} + static void * ibm8514_init(const device_t *info) { @@ -3938,6 +3988,7 @@ ibm8514_init(const device_t *info) fallthrough; default: + dev->extensions = 0; ibm8514_io_set(svga); if (dev->type & DEVICE_MCA) { @@ -3945,8 +3996,11 @@ ibm8514_init(const device_t *info) dev->pos_regs[1] = 0xef; mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); } + + dev->vblank_start = ibm8514_vblank_start; break; } + return svga; } @@ -3981,7 +4035,7 @@ ibm8514_force_redraw(void *priv) { svga_t *svga = (svga_t *) priv; - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; } // clang-format off diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index d35257ea7..9f1bb99d6 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -70,6 +70,10 @@ static uint16_t ati8514_accel_inw(uint16_t port, void *priv); static uint32_t ati8514_accel_inl(uint16_t port, void *priv); static void mach32_updatemapping(mach_t *mach, svga_t *svga); +static __inline void mach32_writew_linear(uint32_t addr, uint16_t val, mach_t *mach); +static __inline void mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach, svga_t *svga); + +static mach_t *reset_state = NULL; #ifdef ENABLE_MACH_LOG int mach_do_log = ENABLE_MACH_LOG; @@ -121,14 +125,14 @@ mach_log(const char *fmt, ...) } #define READ_PIXTRANS_WORD(cx, n) \ - if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ + if ((cmd == 0) || (cmd == 1) || (cmd == 5) || ((mach->accel.cmd_type == -1) && (cmd != 2))) { \ if (dev->bpp) \ temp = vram_w[((dev->accel.cy * dev->pitch) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ else { \ temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } \ - } else if ((mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ + } else if (((cmd == 2) && (mach->accel.cmd_type == -1)) || (mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ if (dev->bpp) \ temp = vram_w[((dev->accel.dest) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ else { \ @@ -184,12 +188,15 @@ mach_log(const char *fmt, ...) dest_dat = ~(src_dat & dest_dat); \ break; \ case 0x09: \ + case 0x11: \ dest_dat = ~src_dat | dest_dat; \ break; \ case 0x0a: \ + case 0x12: \ dest_dat = src_dat | ~dest_dat; \ break; \ case 0x0b: \ + case 0x13: \ dest_dat = src_dat | dest_dat; \ break; \ case 0x0c: \ @@ -207,56 +214,43 @@ mach_log(const char *fmt, ...) case 0x10: \ dest_dat = MIN(src_dat, dest_dat); \ break; \ - case 0x11: \ - dest_dat = dest_dat - src_dat; \ - break; \ - case 0x12: \ - dest_dat = src_dat - dest_dat; \ - break; \ - case 0x13: \ - dest_dat = src_dat + dest_dat; \ - break; \ case 0x14: \ dest_dat = MAX(src_dat, dest_dat); \ break; \ case 0x15: \ - dest_dat = (dest_dat - src_dat) / 2; \ + dest_dat = (src_dat | ~dest_dat) >> 1; \ break; \ case 0x16: \ - dest_dat = (src_dat - dest_dat) / 2; \ + dest_dat = (~src_dat | dest_dat) >> 1; \ break; \ case 0x17: \ - dest_dat = (dest_dat + src_dat) / 2; \ + dest_dat = (src_dat | dest_dat) >> 1; \ break; \ case 0x18: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ case 0x19: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ + dest_dat = MAX(0, ~src_dat | dest_dat); \ break; \ case 0x1a: \ - dest_dat = MAX(0, (src_dat - dest_dat)); \ + dest_dat = MAX(0, src_dat | ~dest_dat); \ break; \ case 0x1b: \ if (dev->bpp) \ - dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xffff, src_dat | dest_dat); \ else \ - dest_dat = MIN(0xff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xff, src_dat | dest_dat); \ break; \ case 0x1c: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ - break; \ case 0x1d: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ + dest_dat = MAX(0, ~src_dat | dest_dat) >> 1; \ break; \ case 0x1e: \ - dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + dest_dat = MAX(0, src_dat | ~dest_dat) >> 1; \ break; \ case 0x1f: \ if (dev->bpp) \ - dest_dat = (0xffff < (src_dat + dest_dat)) ? 0xffff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xffff < (src_dat | dest_dat)) ? 0xffff : ((src_dat | dest_dat) >> 1); \ else \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xff < (src_dat | dest_dat)) ? 0xff : ((src_dat | dest_dat) >> 1); \ break; \ } \ } @@ -265,10 +259,10 @@ mach_log(const char *fmt, ...) #define WRITE(addr, dat) \ if (dev->bpp) { \ vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ } else { \ dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; \ } static int @@ -297,6 +291,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 uint16_t rd_mask = dev->accel.rd_mask; uint16_t wrt_mask = dev->accel.wrt_mask; uint16_t dest_cmp_clr = dev->accel.color_cmp; + uint16_t frgd_color = dev->accel.frgd_color; + uint16_t bkgd_color = dev->accel.bkgd_color; int frgd_sel; int bkgd_sel; int mono_src; @@ -313,9 +309,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 int16_t clip_b = dev->accel.clip_bottom; int16_t clip_r = dev->accel.clip_right; + if (clip_l < 0) + clip_l = 0; + if (clip_t < 0) + clip_t = 0; + if (!dev->bpp) { rd_mask &= 0xff; dest_cmp_clr &= 0xff; + frgd_color &= 0xff; + bkgd_color &= 0xff; } compare_mode = (mach->accel.dest_cmp_fn >> 3) & 7; @@ -341,6 +344,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.rd_mask, mach->accel.dp_config, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); + mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i.\n", cmd_type, frgd_sel, bkgd_sel, mono_src); + switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ if (!cpu_input) { @@ -438,13 +443,12 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -547,9 +551,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mono_src == 1) && !count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -662,13 +668,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -772,9 +778,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mono_src == 1) && !count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -997,6 +1005,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dy_end == mach->accel.dy_start) { mach_log("No DEST.\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } @@ -1004,6 +1013,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.sx_end == mach->accel.sx_start) { mach_log("No SRC.\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -1015,6 +1025,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sy == mach->accel.height) { mach_log("No Blit on DPCONFIG=3251.\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -1069,7 +1080,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (mach->accel.dp_config & 0x02) { READ(dev->accel.src + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); @@ -1080,10 +1091,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1232,6 +1243,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sy >= mach->accel.height) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; if ((mono_src == 2) || (mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) return; if ((mono_src == 1) && (frgd_sel == 5) && (dev->accel_bpp == 24)) @@ -1311,14 +1323,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1391,6 +1403,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1445,7 +1458,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; if (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { @@ -1459,10 +1472,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1561,6 +1574,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sx >= mach->accel.width) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1604,14 +1618,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1685,6 +1699,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1739,14 +1754,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1843,6 +1858,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sx >= mach->accel.width) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1873,8 +1889,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.poly_fill = 0; mach->accel.line_array[(cmd_type == 4) ? 4 : 0] = dev->accel.cx; mach->accel.line_array[(cmd_type == 4) ? 5 : 1] = dev->accel.cy; - dev->accel.cur_x = mach->accel.line_array[(cmd_type == 4) ? 4 : 0]; - dev->accel.cur_y = mach->accel.line_array[(cmd_type == 4) ? 5 : 1]; + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + mach_log("Done: %i, %i\n", dev->accel.cur_x, dev->accel.cur_y); break; case 5: /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ @@ -1920,12 +1937,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dest_y_end >= 0x600) mach->accel.dy_end |= ~0x5ff; - if (mach->accel.dy_end > mach->accel.dy_start) + if (mach->accel.dy_end > mach->accel.dy_start) { + dev->accel.sy = (mach->accel.dy_end - mach->accel.dy_start); mach->accel.stepy = 1; - else if (mach->accel.dy_end < mach->accel.dy_start) + } else if (mach->accel.dy_end < mach->accel.dy_start) { + dev->accel.sy = (mach->accel.dy_start - mach->accel.dy_end); mach->accel.stepy = -1; - else + } else { mach->accel.stepy = 0; + dev->accel.sy = 0; + } if (dev->bpp) dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); @@ -1969,9 +1990,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); - mach_log("ScanToX=%04x, MonoSRC=%d, FrgdSel=%d, BkgdSel=%d, Pitch=%d, C(%d,%d), SRCWidth=%d, WH(%d,%d), colorpattidx=%d, pattlen=%d.\n", - mach->accel.dp_config, mono_src, frgd_sel, bkgd_sel, dev->ext_pitch, dev->accel.cx, dev->accel.cy, mach->accel.src_width, - mach->accel.width, mach->accel.height, mach->accel.color_pattern_idx, mach->accel.patt_len); + mach_log("ScanToX: Parameters=%04x: DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, srcwidth=%d, height=%d, clipl=%d, clipr=%d, clipt=%d, clipb=%d, frmix=%02x.\n", mach->accel.dp_config, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.src_width, dev->accel.sy, clip_l, clip_r, clip_t, clip_b, dev->accel.frgd_mix & 0x1f); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -2035,13 +2054,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -2104,6 +2123,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config & 0x10) { WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + mach_log("ScanToX: DXS=%d, DYS=%d, dest data=%02x, lineidx=%d.\n", dev->accel.dx, dev->accel.dy, dest_dat, mach->accel.line_idx); } } @@ -2148,7 +2168,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.line_array[0] = dev->accel.dx; mach->accel.line_array[4] = dev->accel.dx; } + if (dev->accel.sy >= 0) + dev->accel.sy--; + dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; return; } } @@ -2278,16 +2305,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2); mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } - if (dev->on) - mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); + mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } else { /* Single bank mode */ mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); if ((dev->local & 0xff) >= 0x02) mach->bank_w |= ((mach->regs[0xae] & 3) << 4); mach->bank_r = mach->bank_w; - if (dev->on) - mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); + mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } svga->read_bank = mach->bank_r << 16; svga->write_bank = mach->bank_w << 16; @@ -2420,7 +2445,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga->fullchange = 3; svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); } } @@ -2490,6 +2515,7 @@ mach_in(uint16_t addr, void *priv) temp = mach->regs[mach->index]; break; } + mach_log("ATI VGA read reg=%02x, val=%02x.\n", mach->index, temp); break; case 0x2ea: @@ -2637,6 +2663,40 @@ ati_render_32bpp(svga_t *svga) } } +static void +mach_set_resolution(mach_t *mach, svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + dev->hdisp = (dev->hdisped + 1) << 3; + dev->h_total = dev->htotal + 1; + + dev->vdisp = (dev->v_disp + 1) >> 1; + if ((dev->vdisp == 478) || (dev->vdisp == 598) || (dev->vdisp == 766) || (dev->vdisp == 1022)) + dev->vdisp += 2; + + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + mach_log("Shadow set ATI=%x, shadow set 8514/A=%x, resolution h=%d, v=%d.\n", mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + if ((mach->accel.clock_sel & 0x01) || dev->bpp || ((mach->accel.ext_ge_config & 0x30) == 0x30)) /*ATI and 15bpp+ mode*/ + svga_recalctimings(svga); + else { /*8514/A mode*/ + if (mach->resolution_crt == 0x02) { + if (!(dev->accel.advfunc_cntl & 0x04)) { + dev->hdisp = 640; + dev->vdisp = 480; + svga_recalctimings(svga); + } + } + } +} + void ati8514_recalctimings(svga_t *svga) { @@ -2648,7 +2708,6 @@ ati8514_recalctimings(svga_t *svga) mach_log("8514/A ON.\n"); dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - dev->h_total = dev->htotal + 1; dev->rowcount = !!(dev->disp_cntl & 0x08); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; @@ -2656,23 +2715,8 @@ ati8514_recalctimings(svga_t *svga) mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x05, mach->accel.clock_sel & 0x01); - if (mach->accel.clock_sel & 0x01) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - if (dev->accel.advfunc_cntl & 0x04) { - if (dev->hdisp == 640) { - dev->h_disp = 1024; - dev->dispend = 768; - } else { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } - } else { - dev->h_disp = 640; - dev->dispend = 480; - } - } + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; if (dev->accel.advfunc_cntl & 0x04) svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; @@ -2695,6 +2739,7 @@ ati8514_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; + mach->resolution_crt = 0; svga->render8514 = ibm8514_render_8bpp; } } @@ -2753,9 +2798,9 @@ mach_recalctimings(svga_t *svga) mach_log("ON?=%d, override=%d.\n", dev->on, svga->override); if (dev->on) { mach_log("8514/A ON, extpitch=%d, devma=%x, vgamalatch=%x.\n", dev->ext_pitch, dev->ma, svga->ma_latch); + dev->ma_latch = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2; dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - dev->h_total = dev->htotal + 1; dev->rowcount = !!(dev->disp_cntl & 0x08); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; @@ -2763,42 +2808,12 @@ mach_recalctimings(svga_t *svga) mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x, interlace=%x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0xfe, dev->interlace); - if ((dev->local & 0xff) >= 0x02) { - if (dev->bpp || ((mach->accel.ext_ge_config & 0x30) == 0x30) || (mach->accel.clock_sel & 0x01)) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - if (dev->interlace) { /*Interlaced displays are only for 800x600 and up.*/ - if (dev->accel.advfunc_cntl & 0x04) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - dev->h_disp = 640; - dev->dispend = 480; - } - } else { - if (((mach->shadow_set & 0x03) == 0x00) && ((dev->hdisp2 == 640) || (dev->hdisp2 == 1280)) && (dev->hdisp != 800)) { - dev->h_disp = dev->hdisp2; - dev->dispend = dev->vdisp2; - } else { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } - } - } - } else { - if (mach->accel.clock_sel & 0x01) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - if (dev->accel.advfunc_cntl & 0x04) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - dev->h_disp = 640; - dev->dispend = 480; - } - } + + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + if (dev->dispend == 959) { /*FIXME: vertical resolution mess on EEPROM tests on Mach8*/ + dev->dispend >>= 1; + dev->dispend++; } svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); @@ -2809,21 +2824,29 @@ mach_recalctimings(svga_t *svga) dev->dispend >>= 1; if ((dev->local & 0xff) >= 0x02) { - mach_log("HDISP=%d, mask=%02x.\n", dev->h_disp, dev->dac_mask); + mach_log("cntl=%d, clksel=%x, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d, vgahdisp=%d.\n", + dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0x01, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, + mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace, svga->hdisp); if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) { if ((mach->accel.ext_ge_config & 0x30) == 0x20) { - if ((mach->accel.ext_ge_config & 0xc0) == 0x40) + if ((mach->accel.ext_ge_config & 0xc0) == 0x40) { dev->accel_bpp = 16; - else + svga->overscan_color = video_16to32[((mach->overscan_r_col_24 << 16) | (mach->overscan_g_col_24 << 8) | mach->overscan_b_col_24) & 0xffff]; + } else { dev->accel_bpp = 15; + svga->overscan_color = video_15to32[((mach->overscan_r_col_24 << 16) | (mach->overscan_g_col_24 << 8) | mach->overscan_b_col_24) & 0xffff]; + } } else if ((mach->accel.ext_ge_config & 0x30) == 0x30) { if (mach->accel.ext_ge_config & 0x200) dev->accel_bpp = 32; else dev->accel_bpp = 24; - } else if ((mach->accel.ext_ge_config & 0x30) == 0x10) + + svga->overscan_color = ((mach->overscan_r_col_24 << 16) | (mach->overscan_g_col_24 << 8) | mach->overscan_b_col_24); + } else if ((mach->accel.ext_ge_config & 0x30) == 0x10) { dev->accel_bpp = 8; - else { + svga->overscan_color = dev->pallook[mach->overscan_col_8]; + } else { if (dev->vram_512k_8514) { if (dev->h_disp == 640) { dev->ext_pitch = 640; @@ -2834,12 +2857,14 @@ mach_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; + svga->overscan_color = dev->pallook[mach->overscan_col_8]; } - svga->render8514 = ibm8514_render_blank; mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp, mach->shadow_set & 3, svga->hdisp); + + mach->resolution_crt = 0; switch (dev->accel_bpp) { case 8: svga->render8514 = ibm8514_render_8bpp; @@ -2864,10 +2889,9 @@ mach_recalctimings(svga_t *svga) } } } else { - svga->render8514 = ibm8514_render_blank; - mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", - dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, - mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); + mach_log("cntl=%d, clksel=%x, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d, vgahdisp=%d.\n", + dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0x01, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, + mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace, svga->hdisp); if (dev->vram_512k_8514) { if (dev->h_disp == 640) { dev->ext_pitch = 640; @@ -2878,6 +2902,7 @@ mach_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; + mach->resolution_crt = 0; svga->render8514 = ibm8514_render_8bpp; } } else { @@ -2934,22 +2959,248 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("[%04X:%08X]: Port FIFO OUT=%04x, val=%04x, len=%d.\n", CS, cpu_state.pc, port, val, len); switch (port) { + case 0x2e8: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) + dev->htotal = val; + + mach_set_resolution(mach, svga); + } + break; + + case 0xae8: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) { + WRITE8(port, dev->hsync_start, val); + } + svga_recalctimings(svga); + } + break; + + case 0xee8: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) { + WRITE8(port, dev->hsync_width, val); + } + svga_recalctimings(svga); + } + break; + + case 0x1ee8: + case 0x1ee9: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) /*For 8514/A mode, take the shadow sets into account.*/ + svga_recalctimings(svga); + break; + + case 0x6e8: + if (len == 2) { + mach_log("HDISP and HTOTAL=%04x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } + + if (!(mach->shadow_cntl & 0x04)) + dev->htotal = (val >> 8) & 0xff; + + mach_set_resolution(mach, svga); + } + } else { + mach_log("HDISP and HTOTAL=%02x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } + mach_set_resolution(mach, svga); + } else if (!(mach->accel.clock_sel & 0x01) && ((mach->shadow_set & 0x03) == 0x00) && dev->on) { /*Still write the parameter even after going to 8514/A mode if needed*/ + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } + if (mach->resolution_crt == 0x00) + mach->resolution_crt = 0x02; + + mach_set_resolution(mach, svga); + } + } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x, shadowcntl=%02x, shadowset=%02x.\n", + CS, cpu_state.pc, port, val, mach->shadow_cntl & 0x08, mach->shadow_set & 0x03); + break; + + case 0x6e9: + if (len == 1) { + mach_log("HDISP and HTOTAL+1=%02x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) { + dev->htotal = val; + } + mach_set_resolution(mach, svga); + } + } + break; + + case 0x12e8: + if (len == 2) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x10)) { + dev->v_total_reg = val; + dev->v_total_reg &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } else { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x10)) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + break; + + case 0x12e9: + if (len == 1) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + } + break; + + case 0x16e8: + if (len == 2) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x20)) { /*For 8514/A mode, take the shadow sets into account.*/ + dev->v_disp = val; + dev->v_disp &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_DISP write 16E8=%d, vdisp2=%d.\n", dev->v_disp, dev->v_disp2); + mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + } else { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x20)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } + break; + case 0x16e9: + if (len == 1) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x20)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_DISP write 16E8=%d, vdisp2=%d.\n", dev->v_disp, dev->v_disp2); + mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + } + break; + + case 0x1ae8: + if (len == 2) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + dev->v_sync_start = val; + dev->v_sync_start &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + mach_log("ATI 8514/A: (0x%04x): vsyncstart=0x%02x.\n", port, val); + } else { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } + break; + case 0x1ae9: + if (len == 1) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + mach_log("ATI 8514/A: (0x%04x): vsyncstart=0x%02x.\n", port, val); + } + break; + + case 0x22e8: + if ((mach->shadow_cntl & 0x03) == 0x00) { + dev->disp_cntl = val; + dev->interlace = !!(dev->disp_cntl & 0x10); + } + mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, written=%02x, interlace=%d.\n", + port, val & 0x70, dev->disp_cntl & 0x70, dev->interlace); + svga_recalctimings(svga); + break; + + + case 0x42e8: + case 0x42e9: + mach_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + if (len == 2) + dev->subsys_cntl = val; + else { + WRITE8(port, dev->subsys_cntl, val); + } + dev->subsys_stat &= ~val; + if ((dev->subsys_cntl & 0xc000) == 0x8000) { + mach->force_busy = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + } + break; + + case 0x46e8: + case 0x46e9: + mach_log("0x%04x write: VGA subsystem enable add-on=%02x.\n", port, val); + break; + + case 0x4ae8: + dev->accel.advfunc_cntl = val; + dev->on = dev->accel.advfunc_cntl & 0x01; + dev->vendor_mode = 0; + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", + CS, cpu_state.pc, port, val & 0x01, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + + if ((dev->local & 0xff) < 0x02) { + dev->ext_crt_pitch = 128; + mach_set_resolution(mach, svga); + } else { + mach_set_resolution(mach, svga); + mach32_updatemapping(mach, svga); + } + mach_log("Vendor IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); + break; + case 0x82e8: case 0x86e8: case 0xc2e8: case 0xc6e8: - dev->ext_fifo_idx++; - ibm8514_accel_out_fifo(svga, port, val, len); - break; case 0xf6ee: - dev->ext_fifo_idx++; - if (len == 2) - dev->accel.cur_y = val & 0x7ff; + ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x8ae8: case 0xcae8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { mach_log("SRCY=%d.\n", val & 0x07ff); @@ -2959,7 +3210,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x8ee8: case 0xcee8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { mach_log("SRCX=%d.\n", val & 0x07ff); @@ -2969,13 +3219,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x92e8: case 0xd2e8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x96e8: case 0xd6e8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) mach->accel.test = val & 0x1fff; @@ -2983,34 +3231,42 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x9ae8: case 0xdae8: - dev->ext_fifo_idx++; mach->accel.cmd_type = -1; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x9ee8: case 0xdee8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xa2e8: case 0xe2e8: - dev->ext_fifo_idx++; - dev->fifo_idx++; if (port == 0xe2e8) { if (len == 2) { if (dev->accel.cmd_back) { - dev->accel.bkgd_color = val; - mach_log("CMDBack BKGDCOLOR, sy=%d, height=%d, val=%04x.\n", dev->accel.sy, mach->accel.height, val); + if (mach->accel.cmd_type == 5) { + if (dev->accel.sy >= 0) { + if (mach_pixel_read(mach)) + break; + + mach_accel_out_pixtrans(svga, mach, dev, val); + } else + dev->accel.bkgd_color = val; + } else + dev->accel.bkgd_color = val; + + mach_log("%04X: CMDBack BKGDCOLOR, sy=%d, height=%d, val=%04x.\n", port, dev->accel.sy, mach->accel.height, val); } else { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach_accel_out_pixtrans(svga, mach, dev, val); } else { if (ibm8514_cpu_dest(svga)) break; + ibm8514_accel_out_pixtrans(svga, port, val, len); } } @@ -3018,31 +3274,43 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach->accel.pix_trans[1] = val; } } } else { if (len == 2) dev->accel.bkgd_color = val; + + mach_log("%04X: Background Color=%04x.\n", port, val); } break; case 0xa6e8: case 0xe6e8: - dev->ext_fifo_idx++; - dev->fifo_idx++; if (port == 0xe6e8) { if (len == 2) { - if (dev->accel.cmd_back) - dev->accel.frgd_color = val; - else { + if (dev->accel.cmd_back) { + if (mach->accel.cmd_type == 5) { + if (dev->accel.sy >= 0) { + if (mach_pixel_read(mach)) + break; + + mach_accel_out_pixtrans(svga, mach, dev, val); + } else + dev->accel.frgd_color = val; + } else + dev->accel.frgd_color = val; + } else { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach_accel_out_pixtrans(svga, mach, dev, val); } else { if (ibm8514_cpu_dest(svga)) break; + ibm8514_accel_out_pixtrans(svga, port, val, len); } } @@ -3050,6 +3318,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach->accel.pix_trans[1] = val; } } @@ -3061,13 +3330,12 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xe2e9: case 0xe6e9: - dev->ext_fifo_idx++; - dev->fifo_idx++; mach_log("Write PORT=%04x, 8514/A=%x, val=%04x, len=%d.\n", port, dev->accel.cmd_back, val, len); if (len == 1) { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach->accel.pix_trans[0] = val; frgd_sel = (mach->accel.dp_config >> 13) & 7; bkgd_sel = (mach->accel.dp_config >> 7) & 3; @@ -3114,13 +3382,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xf2e8: case 0xf6e8: case 0xfae8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xbee8: case 0xfee8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { if ((dev->accel.multifunc_cntl >> 12) == 5) { @@ -3131,485 +3397,95 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; /*ATI Mach8/32 specific registers*/ - case 0x82ee: - dev->ext_fifo_idx++; - mach->accel.patt_data_idx_reg = val & 0x1f; - mach->accel.patt_data_idx = mach->accel.patt_data_idx_reg; - - if (mach->accel.patt_data_idx_reg < 0x10) - mach->accel.color_pattern_idx = mach->accel.patt_idx; - else - mach->accel.color_pattern_idx = 0; - - mach_log("Write Port 82ee: Pattern Data Index=%d.\n", val & 0x1f); - break; - - case 0x8eee: - dev->ext_fifo_idx++; - if (len == 2) { - if (mach->accel.patt_data_idx_reg < 0x10) { - mach->accel.color_pattern[mach->accel.patt_data_idx] = val & 0xff; - mach->accel.color_pattern[mach->accel.patt_data_idx + 1] = (val >> 8) & 0xff; - mach_log("Write Port 8eee: Color Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx, val); - } else { - mach->accel.mono_pattern_normal[mach->accel.patt_data_idx - 0x10] = val & 0xff; - mach->accel.mono_pattern_normal[(mach->accel.patt_data_idx + 1) - 0x10] = (val >> 8) & 0xff; - mach_log("Write Port 8eee: Mono Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx - 0x10, val); - } - mach->accel.patt_data_idx += 2; - } - break; - - case 0x96ee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.bres_count = val & 0x7ff; - mach_log("BresenhamDraw=%04x.\n", mach->accel.dp_config); - dev->data_available = 0; - dev->data_available2 = 0; - mach->accel.cmd_type = 1; - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - } - break; - - case 0x9aee: - dev->ext_fifo_idx++; - mach->accel.line_idx = val & 0x07; - break; - - case 0xa2ee: - dev->ext_fifo_idx++; - mach_log("Line OPT=%04x.\n", val); - if (len == 2) { - mach->accel.linedraw_opt = val; - mach->accel.bbottom = dev->accel.clip_bottom; - mach->accel.btop = dev->accel.clip_top; - mach->accel.bleft = dev->accel.clip_left; - mach->accel.bright = dev->accel.clip_right; - if (mach->accel.linedraw_opt & 0x100) { - mach->accel.bbottom = 2047; - mach->accel.btop = 0; - mach->accel.bleft = 0; - mach->accel.bright = 2047; - } - } - break; - - case 0xa6ee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.dest_x_start = val & 0x7ff; - break; - - case 0xaaee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.dest_x_end = val & 0x7ff; - break; - - case 0xaeee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.dest_y_end = val & 0x7ff; - if ((val + 1) == 0x10000) { - mach_log("Dest_Y_end overflow val=%04x, DPCONFIG=%04x\n", val, mach->accel.dp_config); - mach->accel.dest_y_end = 0; - } - dev->data_available = 0; - dev->data_available2 = 0; - mach_log("BitBLT=%04x.\n", mach->accel.dp_config); - mach_log(".\n"); - mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ - - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - } - break; - - case 0xb2ee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.src_x_start = val & 0x7ff; - break; - - case 0xb6ee: - dev->ext_fifo_idx++; - dev->accel.bkgd_mix = val & 0xff; - break; - - case 0xbaee: - dev->ext_fifo_idx++; - dev->accel.frgd_mix = val & 0xff; - break; - - case 0xbeee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.src_x_end = val & 0x7ff; - break; - - case 0xc2ee: - dev->ext_fifo_idx++; - mach->accel.src_y_dir = val & 1; - break; - - case 0xc6ee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.cmd_type = 0; - mach_log("TODO: Short Stroke.\n"); - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - } - break; - - case 0xcaee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.scan_to_x = (val & 0x7ff); - if ((val + 1) == 0x10000) { - mach_log("Scan_to_X overflow val = %04x\n", val); - mach->accel.scan_to_x = 0; - } - dev->data_available = 0; - dev->data_available2 = 0; - mach->accel.cmd_type = 5; /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ - mach_log("ScanToX=%04x.\n", mach->accel.dp_config); - mach_log(".\n"); - - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - } - break; - - case 0xceee: - dev->ext_fifo_idx++; - mach_log("CEEE write val = %04x.\n", val); - if (len == 2) { - dev->data_available = 0; - dev->data_available2 = 0; - mach->accel.dp_config = val; - } - break; - - case 0xd2ee: - dev->ext_fifo_idx++; - mach->accel.patt_len = val & 0x1f; - mach_log("Write Port d2ee: Pattern Length=%d, val=%04x.\n", val & 0x1f, val); - mach->accel.mono_pattern_enable = !!(val & 0x80); - if (len == 2) { - mach->accel.block_write_mono_pattern_enable = !!(val & 0x8000); - mach->accel.patt_len_reg = val; - } - break; - - case 0xd6ee: - dev->ext_fifo_idx++; - mach->accel.patt_idx = val & 0x1f; - mach_log("Write Port d6ee: Pattern Index=%d.\n", val & 0x1f); - break; - - case 0xdaee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[2] = val & 0x7ff; - dev->accel.clip_left = dev->accel.multifunc[2]; - if (val & 0x800) - dev->accel.clip_left |= ~0x7ff; - } - mach_log("DAEE (extclipl) write val=%d, left=%d.\n", val, dev->accel.clip_left); - break; - - case 0xdeee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[1] = val & 0x7ff; - dev->accel.clip_top = dev->accel.multifunc[1]; - if (val & 0x800) { - dev->accel.clip_top |= ~0x7ff; - } - } - mach_log("DEEE (extclipt) write val = %d\n", val); - break; - - case 0xe2ee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[4] = val & 0x7ff; - dev->accel.clip_right = dev->accel.multifunc[4]; - if (val & 0x800) - dev->accel.clip_right |= ~0x7ff; - } - mach_log("E2EE (extclipr) write val = %d\n", val); - break; - - case 0xe6ee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[3] = val & 0x7ff; - dev->accel.clip_bottom = dev->accel.multifunc[3]; - if (val & 0x800) - dev->accel.clip_bottom |= ~0x7ff; - } - mach_log("E6EE (extclipb) write val = %d\n", val); - break; - - case 0xeeee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.dest_cmp_fn = val; - break; - - case 0xf2ee: - dev->ext_fifo_idx++; - mach_log("F2EE.\n"); - if (len == 2) - mach->accel.dst_clr_cmp_mask = val; - break; - - case 0xfeee: - dev->ext_fifo_idx++; - mach_log("LineDraw=%04x.\n", mach->accel.dp_config); - if (len == 2) { - mach->accel.line_array[mach->accel.line_idx] = val; - dev->accel.cur_x = mach->accel.line_array[(mach->accel.line_idx == 4) ? 4 : 0]; - dev->accel.cur_y = mach->accel.line_array[(mach->accel.line_idx == 5) ? 5 : 1]; - mach->accel.cx_end_line = mach->accel.line_array[2]; - mach->accel.cy_end_line = mach->accel.line_array[3]; - if ((mach->accel.line_idx == 3) || (mach->accel.line_idx == 5)) { - mach->accel.cmd_type = (mach->accel.line_idx == 5) ? 4 : 3; - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - mach->accel.line_idx = (mach->accel.line_idx == 5) ? 4 : 2; - break; - } - mach->accel.line_idx++; - } - break; - - default: - break; - } -} - -static void -mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) -{ - if (port == 0x42e8 || port == 0x42e9) - mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); - - switch (port) { - case 0x2e8: - case 0x6e9: - case 0xae8: - case 0xee8: - case 0x1ee8: - case 0x1ee9: - case 0x42e8: - ibm8514_accel_out(port, val, svga, 2); - break; - case 0x42e9: - ibm8514_accel_out(port, val, svga, 2); - if ((val & 0xc0) == 0x80) { - dev->ext_fifo_idx = 0; - mach->force_busy = 0; - } - break; - - case 0x6e8: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x08)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01)) { - dev->hdisped = val; - dev->hdisp = (val + 1) << 3; - } else if (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01)) - dev->hdisp2 = (val + 1) << 3; - } - mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x, shadowcntl=%02x, shadowset=%02x.\n", - CS, cpu_state.pc, port, val, mach->shadow_cntl & 0x08, mach->shadow_set & 0x03); - svga_recalctimings(svga); - break; - - case 0x12e8: - case 0x12e9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x10)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01) || - (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01))) { - WRITE8(port, dev->v_total_reg, val); - dev->v_total_reg &= 0x1fff; - dev->v_total = dev->v_total_reg + 1; - if (dev->interlace) - dev->v_total >>= 1; - } - } - mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); - svga_recalctimings(svga); - break; - - case 0x16e8: - case 0x16e9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x20)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01)) { - WRITE8(port, dev->v_disp, val); - dev->v_disp &= 0x1fff; - dev->vdisp = (dev->v_disp + 1) >> 1; - if ((dev->vdisp == 478) || (dev->vdisp == 598) || (dev->vdisp == 766) || (dev->vdisp == 1022)) - dev->vdisp += 2; - } else if (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01)) { - WRITE8(port, dev->v_disp2, val); - dev->v_disp2 &= 0x1fff; - dev->vdisp2 = (dev->v_disp2 + 1) >> 1; - if ((dev->vdisp2 == 478) || (dev->vdisp2 == 598) || (dev->vdisp2 == 766) || (dev->vdisp2 == 1022)) - dev->vdisp2 += 2; - } - } - mach_log("ATI 8514/A: V_DISP write 16E8=%d, vdisp2=%d.\n", dev->v_disp, dev->v_disp2); - mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x1ae8: - case 0x1ae9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x10)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01) || - (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01))) { - WRITE8(port, dev->v_sync_start, val); - dev->v_sync_start &= 0x1fff; - dev->v_syncstart = dev->v_sync_start + 1; - if (dev->interlace) - dev->v_syncstart >>= 1; - } - } - mach_log("ATI 8514/A: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); - mach_log("ATI 8514/A: (0x%04x): vsyncstart=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x22e8: - if (!(mach->shadow_cntl & 0x03)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01) || - (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01))) { - dev->disp_cntl = val; - dev->interlace = !!(dev->disp_cntl & 0x10); - } - } - mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, written=%02x, interlace=%d.\n", - port, val & 0x70, dev->disp_cntl & 0x70, dev->interlace); - svga_recalctimings(svga); - break; - - case 0x46e8: - case 0x46e9: - mach_log("0x%04x write: VGA subsystem enable add-on=%02x.\n", port, val); - break; - - case 0x4ae8: - dev->accel.advfunc_cntl = val; - dev->on = dev->accel.advfunc_cntl & 0x01; - dev->vendor_mode = 0; - mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", - CS, cpu_state.pc, port, val & 0x01, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); - - if ((dev->local & 0xff) < 0x02) { - dev->ext_crt_pitch = 128; - svga_recalctimings(svga); - } else { - svga_recalctimings(svga); - mach32_updatemapping(mach, svga); - } - mach_log("Vendor IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); - break; - - /*ATI Mach8/32 specific registers*/ case 0x2ee: - mach_log("2EE write val = %02x.\n", val); - break; case 0x2ef: - mach_log("2EF write val = %02x.\n", val); + if (len == 2) { + mach->overscan_col_8 = val & 0xff; + mach->overscan_b_col_24 = (val >> 8) & 0xff; + } else { + if (port & 1) + mach->overscan_b_col_24 = val; + else + mach->overscan_col_8 = val; + } + svga_recalctimings(svga); break; - case 0x6ee: - mach_log("6EE write val = %02x.\n", val); - break; case 0x6ef: - mach_log("6EF write val = %02x.\n", val); + if (len == 2) { + mach->overscan_g_col_24 = val & 0xff; + mach->overscan_r_col_24 = (val >> 8) & 0xff; + } else { + if (port & 1) + mach->overscan_r_col_24 = val; + else + mach->overscan_g_col_24 = val; + } + svga_recalctimings(svga); break; case 0xaee: case 0xaef: - WRITE8(port, mach->cursor_offset_lo_reg, val); + if (len == 2) + mach->cursor_offset_lo_reg = val; + else { + WRITE8(port, mach->cursor_offset_lo_reg, val); + } mach->cursor_offset_lo = mach->cursor_offset_lo_reg; dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); break; case 0xeee: case 0xeef: - WRITE8(port, mach->cursor_offset_hi_reg, val); + if (len == 2) + mach->cursor_offset_hi_reg = val; + else { + WRITE8(port, mach->cursor_offset_hi_reg, val); + } + dev->hwcursor.ena = !!(mach->cursor_offset_hi_reg & 0x8000); mach->cursor_offset_hi = mach->cursor_offset_hi_reg & 0x0f; dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); - dev->hwcursor.ena = !!(mach->cursor_offset_hi_reg & 0x8000); mach_log("HWCursorEnabled=%x.\n", dev->hwcursor.ena); break; case 0x12ee: case 0x12ef: - WRITE8(port, mach->cursor_x, val); + if (len == 2) + mach->cursor_x = val; + else { + WRITE8(port, mach->cursor_x, val); + } dev->hwcursor.x = mach->cursor_x & 0x7ff; break; case 0x16ee: case 0x16ef: - WRITE8(port, mach->cursor_y, val); + if (len == 2) + mach->cursor_y = val; + else { + WRITE8(port, mach->cursor_y, val); + } dev->hwcursor.y = mach->cursor_y & 0xfff; break; case 0x1aee: case 0x1aef: - WRITE8(port, mach->cursor_col_b, val); + if (len == 2) + mach->cursor_col_b = val; + else { + WRITE8(port, mach->cursor_col_b, val); + } mach->cursor_col_0 = mach->cursor_col_b & 0xff; mach->cursor_col_1 = (mach->cursor_col_b >> 8) & 0xff; break; case 0x1eee: case 0x1eef: - WRITE8(port, mach->cursor_vh_offset, val); + if (len == 2) + mach->cursor_vh_offset = val; + else { + WRITE8(port, mach->cursor_vh_offset, val); + } dev->hwcursor.xoff = mach->cursor_vh_offset & 0x3f; dev->hwcursor.yoff = (mach->cursor_vh_offset >> 8) & 0x3f; break; @@ -3624,7 +3500,11 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x26ee: case 0x26ef: - WRITE8(port, mach->accel.crt_pitch, val); + if (len == 2) + mach->accel.crt_pitch = val; + else { + WRITE8(port, mach->accel.crt_pitch, val); + } dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; if (dev->accel_bpp > 8) { if (dev->accel_bpp == 24) @@ -3642,54 +3522,98 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 if ((dev->local & 0xff) >= 0x01) mach32_updatemapping(mach, svga); - mach_log("ATI 8514/A: (0x%04x) val=0x%02x, extended 8514/A mode=%02x.\n", port, val, mach->regs[0xb0] & 0x20); + mach_log("ATI 8514/A: (0x%04x) CRT Pitch, val=0x%02x, crtpitch=%x, len=%d, extended 8514/A mode=%02x.\n", port, val, dev->ext_crt_pitch, len, mach->regs[0xb0] & 0x20); + break; + + case 0x2aee: + case 0x2aef: + if (len == 2) { + mach->accel.crt_offset_lo = val; + } else { + WRITE8(port, mach->accel.crt_offset_lo, val); + } + svga_recalctimings(svga); + break; + + case 0x2eee: + case 0x2eef: + mach->accel.crt_offset_hi = val & 0x0f; + svga_recalctimings(svga); break; case 0x32ee: case 0x32ef: - WRITE8(port, mach->local_cntl, val); + if (len == 2) + mach->local_cntl = val; + else { + WRITE8(port, mach->local_cntl, val); + } if ((dev->local & 0xff) >= 0x01) mach32_updatemapping(mach, svga); break; case 0x36ee: case 0x36ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - if ((dev->local & 0xff) >= 0x02) { - WRITE8(port, mach->misc, val); - mach->misc &= 0xfff0; + if (len == 2) { + if ((dev->local & 0xff) >= 0x02) + mach->misc = val; + } else { + if ((dev->local & 0xff) >= 0x02) + WRITE8(port, mach->misc, val); } + mach->misc &= 0xfff0; break; case 0x3aee: case 0x3aef: - WRITE8(port, mach->cursor_col_0_rg, val); + if (len == 2) + mach->cursor_col_0_rg = val; + else { + WRITE8(port, mach->cursor_col_0_rg, val); + } mach->ext_cur_col_0_g = mach->cursor_col_0_rg & 0xff; mach->ext_cur_col_0_r = (mach->cursor_col_0_rg >> 8) & 0xff; break; case 0x3eee: case 0x3eef: - WRITE8(port, mach->cursor_col_1_rg, val); + if (len == 2) + mach->cursor_col_1_rg = val; + else { + WRITE8(port, mach->cursor_col_1_rg, val); + } mach->ext_cur_col_1_g = mach->cursor_col_1_rg & 0xff; mach->ext_cur_col_1_r = (mach->cursor_col_1_rg >> 8) & 0xff; break; case 0x42ee: case 0x42ef: - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); - WRITE8(port, mach->accel.test2, val); + if (len == 2) + mach->accel.test2 = val; + else { + WRITE8(port, mach->accel.test2, val); + } + mach_log("ATI 8514/A: (0x%04x) MEM_BNDRY val=%04x, memory part=%06x, gdcreg6=%02x.\n", port, val, (mach->accel.test2 & 0x0f) << 18, svga->gdcreg[6] & 0x0c); + mach32_updatemapping(mach, svga); break; case 0x46ee: case 0x46ef: - WRITE8(port, mach->shadow_cntl, val); + if (len == 2) + mach->shadow_cntl = val; + else { + WRITE8(port, mach->shadow_cntl, val); + } mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); break; case 0x4aee: case 0x4aef: - WRITE8(port, mach->accel.clock_sel, val); + if (len == 2) + mach->accel.clock_sel = val; + else { + WRITE8(port, mach->accel.clock_sel, val); + } dev->on = mach->accel.clock_sel & 0x01; dev->vendor_mode = 1; mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", @@ -3703,31 +3627,50 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x52ee: case 0x52ef: - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); - WRITE8(port, mach->accel.scratch0, val); + mach_log("ATI 8514/A: (0x%04x) ScratchPad0 val=%04x.\n", port, val); + if (len == 2) + mach->accel.scratch0 = val; + else { + WRITE8(port, mach->accel.scratch0, val); + } break; case 0x56ee: case 0x56ef: - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); - WRITE8(port, mach->accel.scratch1, val); + mach_log("ATI 8514/A: (0x%04x) ScratchPad1 val=%04x.\n", port, val); + if (len == 2) + mach->accel.scratch1 = val; + else { + WRITE8(port, mach->accel.scratch1, val); + } break; case 0x5aee: case 0x5aef: - WRITE8(port, mach->shadow_set, val); + if (len == 2) + mach->shadow_set = val; + else { + WRITE8(port, mach->shadow_set, val); + } mach_log("ATI 8514/A: (0x%04x) val=0x%02x.\n", port, val); if ((mach->shadow_set & 0x03) == 0x00) mach_log("Primary CRT register set.\n"); - else if ((mach->shadow_set & 0x03) == 0x01) + else if ((mach->shadow_set & 0x03) == 0x01) { mach_log("CRT Shadow Set 1: 640x480.\n"); - else if ((mach->shadow_set & 0x03) == 0x02) + mach->resolution_crt = 0x01; + } else if ((mach->shadow_set & 0x03) == 0x02) { mach_log("CRT Shadow Set 2: 1024x768.\n"); + mach->resolution_crt = 0x02; + } break; case 0x5eee: case 0x5eef: - WRITE8(port, mach->memory_aperture, val); + if (len == 2) + mach->memory_aperture = val; + else { + WRITE8(port, mach->memory_aperture, val); + } mach_log("Memory Aperture = %04x.\n", mach->memory_aperture); if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; @@ -3736,36 +3679,44 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach32_updatemapping(mach, svga); break; - case 0x62ee: - mach_log("62EE write val = %04x, len = %d.\n", val, len); - break; - - case 0x66ee: - mach_log("66EE write val = %04x, len = %d.\n", val, len); - break; - case 0x6aee: case 0x6aef: - WRITE8(port, mach->accel.max_waitstates, val); + if (len == 2) + mach->accel.max_waitstates = val; + else { + WRITE8(port, mach->accel.max_waitstates, val); + } break; case 0x6eee: case 0x6eef: - WRITE8(port, mach->accel.ge_offset_lo, val); + if (len == 2) + mach->accel.ge_offset_lo = val; + else { + WRITE8(port, mach->accel.ge_offset_lo, val); + } svga_recalctimings(svga); mach_log("ATI 8514/A: (0x%04x) val=0x%02x, geoffset=%04x.\n", port, val, dev->accel.ge_offset); break; case 0x72ee: case 0x72ef: - WRITE8(port, mach->accel.ge_offset_hi, val); + if (len == 2) + mach->accel.ge_offset_hi = val; + else { + WRITE8(port, mach->accel.ge_offset_hi, val); + } svga_recalctimings(svga); mach_log("ATI 8514/A: (0x%04x) val=0x%02x, geoffset=%04x.\n", port, val, dev->accel.ge_offset); break; case 0x76ee: case 0x76ef: - WRITE8(port, mach->accel.ge_pitch, val); + if (len == 2) + mach->accel.ge_pitch = val; + else { + WRITE8(port, mach->accel.ge_pitch, val); + } dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); mach_log("ATI 8514/A: (0x%04x) val=0x%02x, extpitch=%d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); @@ -3773,7 +3724,11 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x7aee: case 0x7aef: - WRITE8(port, mach->accel.ext_ge_config, val); + if (len == 2) + mach->accel.ext_ge_config = val; + else { + WRITE8(port, mach->accel.ext_ge_config, val); + } if ((dev->local & 0xff) >= 0x02) { if (mach->accel.crt_pitch & 0xff) dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; @@ -3802,24 +3757,295 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); svga_recalctimings(svga); } else - ati_eeprom_write(&mach->eeprom, !!(mach->accel.ext_ge_config & 0x4000), !!(mach->accel.ext_ge_config & 0x2000), !!(mach->accel.ext_ge_config & 0x1000)); + ati_eeprom_write(&mach->eeprom, !!(mach->accel.ext_ge_config & 0x04), !!(mach->accel.ext_ge_config & 0x02), !!(mach->accel.ext_ge_config & 0x01)); + break; + + case 0x7eee: + case 0x7eef: + if (len == 2) + mach->accel.eeprom_control = val; + else { + WRITE8(port, mach->accel.eeprom_control, val); + } + mach_log("%04X write val=%04x, actual=%04x, len=%d.\n", port, mach->accel.eeprom_control, val, len); + break; + + case 0x82ee: + mach->accel.patt_data_idx_reg = val & 0x1f; + mach->accel.patt_data_idx = mach->accel.patt_data_idx_reg; + + if (mach->accel.patt_data_idx_reg < 0x10) + mach->accel.color_pattern_idx = mach->accel.patt_idx; + else + mach->accel.color_pattern_idx = 0; + + mach_log("Write Port 82ee: Pattern Data Index=%d.\n", val & 0x1f); + break; + + case 0x8eee: + if (len == 2) { + if (mach->accel.patt_data_idx_reg < 0x10) { + mach->accel.color_pattern[mach->accel.patt_data_idx] = val & 0xff; + mach->accel.color_pattern[mach->accel.patt_data_idx + 1] = (val >> 8) & 0xff; + mach_log("Write Port 8eee: Color Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx, val); + } else { + mach->accel.mono_pattern_normal[mach->accel.patt_data_idx - 0x10] = val & 0xff; + mach->accel.mono_pattern_normal[(mach->accel.patt_data_idx + 1) - 0x10] = (val >> 8) & 0xff; + mach_log("Write Port 8eee: Mono Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx - 0x10, val); + } + mach->accel.patt_data_idx += 2; + } + break; + + case 0x92ee: + mach_log("Write port 92ee, malatch=%08x.\n", svga->ma_latch); + break; + + case 0x96ee: + if (len == 2) { + mach->accel.bres_count = val & 0x7ff; + mach_log("BresenhamDraw=%04x.\n", mach->accel.dp_config); + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 1; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + } + break; + + case 0x9aee: + mach->accel.line_idx = val & 0x07; + break; + + case 0xa2ee: + mach_log("Line OPT=%04x.\n", val); + if (len == 2) { + mach->accel.linedraw_opt = val; + mach->accel.bbottom = dev->accel.clip_bottom; + mach->accel.btop = dev->accel.clip_top; + mach->accel.bleft = dev->accel.clip_left; + mach->accel.bright = dev->accel.clip_right; + if (mach->accel.linedraw_opt & 0x100) { + mach->accel.bbottom = 2047; + mach->accel.btop = 0; + mach->accel.bleft = 0; + mach->accel.bright = 2047; + } + } + break; + + case 0xa6ee: + if (len == 2) + mach->accel.dest_x_start = val & 0x7ff; + break; + + case 0xaaee: + if (len == 2) + mach->accel.dest_x_end = val & 0x7ff; + break; + + case 0xaeee: + if (len == 2) { + mach->accel.dest_y_end = val & 0x7ff; + if ((val + 1) == 0x10000) { + mach_log("Dest_Y_end overflow val=%04x, DPCONFIG=%04x\n", val, mach->accel.dp_config); + mach->accel.dest_y_end = 0; + } + dev->data_available = 0; + dev->data_available2 = 0; + mach_log("BitBLT=%04x.\n", mach->accel.dp_config); + mach_log(".\n"); + mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ + + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + } + break; + + case 0xb2ee: + if (len == 2) + mach->accel.src_x_start = val & 0x7ff; + break; + + case 0xb6ee: + dev->accel.bkgd_mix = val & 0xff; + break; + + case 0xbaee: + dev->accel.frgd_mix = val & 0xff; + break; + + case 0xbeee: + if (len == 2) + mach->accel.src_x_end = val & 0x7ff; + break; + + case 0xc2ee: + mach->accel.src_y_dir = val & 1; + break; + + case 0xc6ee: + if (len == 2) { + mach->accel.cmd_type = 0; + mach_log("TODO: Short Stroke.\n"); + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + } + break; + + case 0xcaee: + if (len == 2) { + mach->accel.scan_to_x = (val & 0x7ff); + if ((val + 1) == 0x10000) { + mach_log("Scan_to_X overflow val = %04x\n", val); + mach->accel.scan_to_x = 0; + } + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 5; /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ + mach_log(".\n"); + + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_log("ScanToX=%04x, mono_src=%d, bkgd_sel=%d, frgd_sel=%d, pixread=%x.\n", mach->accel.dp_config, mono_src, bkgd_sel, frgd_sel, mach_pixel_read(mach)); + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + } + break; + + case 0xceee: + mach_log("Data Path Configuration (%04x) write val=%04x.\n", port, val); + if (len == 2) { + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.dp_config = val; + } + break; + + case 0xd2ee: + mach->accel.patt_len = val & 0x1f; + mach_log("Write Port d2ee: Pattern Length=%d, val=%04x.\n", val & 0x1f, val); + mach->accel.mono_pattern_enable = !!(val & 0x80); + if (len == 2) { + mach->accel.block_write_mono_pattern_enable = !!(val & 0x8000); + mach->accel.patt_len_reg = val; + } + break; + + case 0xd6ee: + mach->accel.patt_idx = val & 0x1f; + mach_log("Write Port d6ee: Pattern Index=%d.\n", val & 0x1f); + break; + + case 0xdaee: + if (len == 2) { + dev->accel.multifunc[2] = val & 0x7ff; + dev->accel.clip_left = dev->accel.multifunc[2]; + if (val & 0x800) + dev->accel.clip_left |= ~0x7ff; + } + mach_log("DAEE (extclipl) write val=%d, left=%d.\n", val, dev->accel.clip_left); + break; + + case 0xdeee: + if (len == 2) { + dev->accel.multifunc[1] = val & 0x7ff; + dev->accel.clip_top = dev->accel.multifunc[1]; + if (val & 0x800) { + dev->accel.clip_top |= ~0x7ff; + } + } + mach_log("DEEE (extclipt) write val = %d\n", val); + break; + + case 0xe2ee: + if (len == 2) { + dev->accel.multifunc[4] = val & 0x7ff; + dev->accel.clip_right = dev->accel.multifunc[4]; + if (val & 0x800) + dev->accel.clip_right |= ~0x7ff; + } + mach_log("E2EE (extclipr) write val = %d\n", val); + break; + + case 0xe6ee: + if (len == 2) { + dev->accel.multifunc[3] = val & 0x7ff; + dev->accel.clip_bottom = dev->accel.multifunc[3]; + if (val & 0x800) + dev->accel.clip_bottom |= ~0x7ff; + } + mach_log("E6EE (extclipb) write val = %d\n", val); + break; + + case 0xeeee: + if (len == 2) + mach->accel.dest_cmp_fn = val; + break; + + case 0xf2ee: + mach_log("F2EE.\n"); + if (len == 2) + mach->accel.dst_clr_cmp_mask = val; + break; + + case 0xfeee: + if (len == 2) { + mach->accel.line_array[mach->accel.line_idx] = val; + mach_log("mach->accel.line_array[%02X] = %04X\n", mach->accel.line_idx, val); + dev->accel.cur_x = mach->accel.line_array[(mach->accel.line_idx == 4) ? 4 : 0]; + dev->accel.cur_y = mach->accel.line_array[(mach->accel.line_idx == 5) ? 5 : 1]; + mach->accel.cx_end_line = mach->accel.line_array[2]; + mach->accel.cy_end_line = mach->accel.line_array[3]; + if ((mach->accel.line_idx == 3) || (mach->accel.line_idx == 5)) { + mach->accel.cmd_type = (mach->accel.line_idx == 5) ? 4 : 3; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_log("LineDraw type=%x, dpconfig=%04x.\n", mach->accel.cmd_type, mach->accel.dp_config); + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + mach->accel.line_idx = (mach->accel.line_idx == 5) ? 4 : 2; + break; + } + mach->accel.line_idx++; + } break; default: + mach_log("Unknown or reserved write to %04x, val=%04x, len=%d, latch=%08x.\n", port, val, len, svga->ma_latch); break; } } -static void -mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) -{ - svga_t *svga = &mach->svga; - - mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); - - mach_accel_out_call(port, val, mach, svga, (ibm8514_t *) svga->dev8514); -} - static uint16_t mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, int len) { @@ -3832,7 +4058,19 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in switch (port) { case 0x82e8: + if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) + temp = mach->accel.cy_end_line; + else + temp = ibm8514_accel_in_fifo(svga, port, len); + break; + case 0x86e8: + if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) + temp = mach->accel.cx_end_line; + else + temp = ibm8514_accel_in_fifo(svga, port, len); + break; + case 0x92e8: case 0x96e8: case 0xc2e8: @@ -3842,18 +4080,24 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x9ae8: case 0xdae8: - if ((dev->fifo_idx >= 1) && (dev->fifo_idx <= 8)) { - temp |= (1 << (dev->fifo_idx - 1)); - dev->fifo_idx = 0; - } - if (len == 2) { - if (dev->force_busy) - temp |= 0x200; /*Hardware busy*/ + if (dev->fifo_idx <= 8) { + for (int i = 1; i <= dev->fifo_idx; i++) + temp |= (1 << (7 - (i - 1))); + } else + temp = 0x00ff; + + if (dev->fifo_idx > 0) + dev->fifo_idx--; + + if (dev->force_busy) + temp |= 0x0200; /*Hardware busy*/ + + if (dev->accel.cmd_back) + dev->force_busy = 0; - dev->force_busy = 0; if (dev->data_available) { - temp |= 0x100; /*Read Data available*/ + temp |= 0x0100; /*Read Data available*/ if (mach->accel.cmd_type >= 0) { switch (mach->accel.cmd_type) { case 2: @@ -3891,10 +4135,13 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x9ae9: case 0xdae9: if (len == 1) { + dev->fifo_idx = 0; + if (dev->force_busy2) temp |= 0x02; /*Hardware busy*/ dev->force_busy2 = 0; + if (dev->data_available2) { temp |= 0x01; /*Read Data available*/ if (mach->accel.cmd_type >= 0) { @@ -3913,8 +4160,19 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; } } else { - if (dev->accel.sy < 0) - dev->data_available2 = 0; + switch (dev->accel.cmd >> 13) { + case 2: + case 3: + case 4: + case 6: + if (dev->accel.sy < 0) + dev->data_available = 0; + break; + default: + if (!dev->accel.sy) + dev->data_available = 0; + break; + } } } } @@ -3930,7 +4188,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in READ_PIXTRANS_BYTE_IO(dev->accel.dx, 1) temp = mach->accel.pix_trans[1]; } else { - if (mach->accel.cmd_type == 3) { + if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { READ_PIXTRANS_WORD(dev->accel.cx, 0) } else { READ_PIXTRANS_WORD(dev->accel.dx, 0) @@ -3943,7 +4201,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in cmd = (dev->accel.cmd >> 13); if (len == 2) { READ_PIXTRANS_WORD(dev->accel.cx, 0) - if (dev->subsys_stat & 0x01) { + if (dev->subsys_stat & INT_VSY) { dev->force_busy = 1; dev->data_available = 1; } @@ -4017,10 +4275,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x8eee: - if (len == 1) - temp = mach->accel.ext_ge_config & 0xff; - else + if (len == 2) temp = mach->accel.ext_ge_config; + else + temp = mach->accel.ext_ge_config & 0xff; mach_log("ExtGE Read = %04x, len=%d.\n", temp, len); break; @@ -4030,10 +4288,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x92ee: - if (len == 1) - temp = mach->accel.eeprom_control & 0xff; - else + if (len == 2) temp = mach->accel.eeprom_control; + else + temp = mach->accel.eeprom_control & 0xff; mach_log("EEPROM cntl read=%04x, len=%d.\n", temp, len); break; @@ -4045,10 +4303,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x96ee: - if (len == 1) - temp = mach->accel.test & 0xff; - else + if (len == 2) temp = mach->accel.test; + else + temp = mach->accel.test & 0xff; break; case 0x96ef: if (len == 1) @@ -4057,18 +4315,22 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x9aee: if (len == 2) { - if ((dev->ext_fifo_idx >= 1) && (dev->ext_fifo_idx <= 16)) { - temp |= (1 << (dev->ext_fifo_idx - 1)); - dev->ext_fifo_idx = 0; - } + if (dev->fifo_idx <= 16) { + for (int i = 1; i <= dev->fifo_idx; i++) + temp |= (1 << (15 - (i - 1))); + } else + temp = 0xffff; + + if (dev->fifo_idx > 0) + dev->fifo_idx--; } break; case 0xa2ee: - if (len == 1) - temp = mach->accel.linedraw_opt & 0xff; - else + if (len == 2) temp = mach->accel.linedraw_opt; + else + temp = mach->accel.linedraw_opt & 0xff; break; case 0xa2ef: if (len == 1) @@ -4076,11 +4338,11 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xb2ee: - if (len == 1) - temp = dev->hdisped; - else { + if (len == 2) { temp = dev->hdisped & 0xff; temp |= (dev->htotal << 8); + } else { + temp = dev->hdisped; } mach_log("B2EE read=%02x.\n", temp & 0xff); break; @@ -4098,12 +4360,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xc2ee: - if (len == 1) - temp = dev->v_total_reg & 0xff; - else { + if (len == 2) temp = dev->v_total_reg; - mach_log("VTOTAL read=%d.\n", temp); - } + else + temp = dev->v_total_reg & 0xff; break; case 0xc2ef: if (len == 1) @@ -4111,12 +4371,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xc6ee: - if (len == 1) - temp = dev->v_disp & 0xff; - else { + if (len == 2) temp = dev->v_disp; - mach_log("VDISP read=%d.\n", temp); - } + else + temp = dev->v_disp & 0xff; break; case 0xc6ef: if (len == 1) @@ -4124,10 +4382,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xcaee: - if (len == 1) - temp = dev->v_sync_start & 0xff; - else + if (len == 2) temp = dev->v_sync_start; + else + temp = dev->v_sync_start & 0xff; break; case 0xcaef: if (len == 1) @@ -4136,10 +4394,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xceee: mach_log("CEEE read=%d.\n", len); - if (len == 1) - temp = dev->vc & 0xff; - else + if (len == 2) temp = dev->vc & 0x7ff; + else + temp = dev->vc & 0xff; break; case 0xceef: mach_log("CEEF read=%d.\n", len); @@ -4167,8 +4425,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in if (len == 2) { if ((dev->local & 0xff) >= 0x02) temp = mach->accel.src_y; - } else - temp = mach->accel.src_y & 0xff; + } else { + if ((dev->local & 0xff) >= 0x02) + temp = mach->accel.src_y & 0xff; + } break; case 0xdeef: if (len == 1) { @@ -4218,6 +4478,7 @@ static uint8_t mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) { uint8_t temp = 0; + uint8_t fifo_test_tag[16] = { 0x7c, 0x64, 0x60, 0x5c, 0x58, 0x54, 0x50, 0x68, 0x38, 0x24, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x4c}; int16_t clip_t = dev->accel.clip_top; int16_t clip_l = dev->accel.clip_left; int16_t clip_b = dev->accel.clip_bottom; @@ -4240,63 +4501,64 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x42e8: case 0x42e9: - if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) - temp |= 0x01; + if (!(port & 1)) { + if ((dev->subsys_cntl & INT_VSY) && !(dev->subsys_stat & INT_VSY) && (dev->vc == dev->dispend)) + temp |= INT_VSY; - if (mach->accel.cmd_type == -1) { - if (cmd == 6) { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r_ibm) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b_ibm)) - temp |= 0x02; - } else { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r_ibm) && - (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b_ibm)) - temp |= 0x02; - } - } else { - switch (mach->accel.cmd_type) { - case 1: - case 2: - case 5: - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) - temp |= 0x02; - break; - case 3: - case 4: - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && + if (mach->accel.cmd_type == -1) { + if (cmd == 6) { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r_ibm) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b_ibm)) + temp |= INT_GE_BSY; + } else { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && (dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r) && + (dev->accel.cx <= clip_r_ibm) && (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b)) - temp |= 0x02; - break; - default: - break; + (dev->accel.cy <= clip_b_ibm)) + temp |= INT_GE_BSY; + } + } else { + switch (mach->accel.cmd_type) { + case 1: + case 2: + case 5: + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b)) + temp |= INT_GE_BSY; + break; + case 3: + case 4: + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b)) + temp |= INT_GE_BSY; + break; + default: + break; + } } - } - if ((!dev->fifo_idx || !dev->ext_fifo_idx)) { - if ((!dev->force_busy && !dev->force_busy2) || !mach->force_busy) - temp |= 0x08; - } - if (port & 1) { - temp = dev->vram_512k_8514 ? 0x00 : 0x80; - temp |= (dev->subsys_cntl >> 8); - } else { + if (dev->accel.cmd_back) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + dev->data_available = 0; + dev->data_available2 = 0; + temp |= INT_FIFO_EMP; + } temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); @@ -4318,8 +4580,16 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) break; case 0x1aee: + if (dev->fifo_idx > 0) + dev->fifo_idx--; + if (mach->fifo_test_idx > 0) + mach->fifo_test_idx--; + fallthrough; case 0x1aef: - temp = 0x00; + mach_log("FIFO Test IDX=%d, Data=%04x.\n", mach->fifo_test_idx, mach->fifo_test_data[mach->fifo_test_idx]); + READ8(port, mach->fifo_test_data[mach->fifo_test_idx]); + if (!mach->fifo_test_idx && ((mach->accel.dp_config == 0xaaaa) || (mach->accel.dp_config == 0x5555))) + mach->accel.dp_config = 0x2211; break; case 0x22ee: @@ -4336,7 +4606,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x36ef: if ((dev->local & 0xff) >= 0x02) { READ8(port, mach->misc); - if (!(port & 1)) { temp &= ~0x0c; switch (dev->vram_amount) { @@ -4357,6 +4626,14 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) } break; + case 0x3aee: + case 0x3aef: + if (port & 1) + temp = 0x01; + else + temp = fifo_test_tag[dev->fifo_idx]; + break; + case 0x42ee: case 0x42ef: READ8(port, mach->accel.test2); @@ -4380,7 +4657,13 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) temp = (((dev->bios_rom.mapping.base >> 7) - 0x1000) >> 4); if (port & 1) temp |= 0x01; + } else { + if (mach->accel.scratch0 == 0x1234) + temp = 0x0000; } + } else { + if (mach->accel.scratch0 == 0x1234) + temp = 0x0000; } break; @@ -4440,30 +4723,30 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) default: break; } - if (port == 0x2ee8 || port == 0x2ee9 || port == 0x42e8 || port == 0x42e9) - mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } -static void -ati8514_accel_out(uint16_t port, uint8_t val, svga_t *svga) -{ - mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); - - mach_accel_out_call(port, val, (mach_t *)svga->ext8514, svga, (ibm8514_t *) svga->dev8514); -} - static void ati8514_accel_outb(uint16_t port, uint8_t val, void *priv) { svga_t *svga = (svga_t *)priv; mach_t *mach = (mach_t *)svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); - else - ati8514_accel_out(port, val, svga); + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } + } + dev->accel_out_fifo(svga, port, val, 1); + mach_log("%04X:%08X: OUTB port=%04x, val=%02x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4471,13 +4754,23 @@ ati8514_accel_outw(uint16_t port, uint16_t val, void *priv) { svga_t *svga = (svga_t *)priv; mach_t *mach = (mach_t *)svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); - else { - ati8514_accel_out(port, val, svga); - ati8514_accel_out(port + 1, (val >> 8), svga); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(svga, port, val, 2); + mach_log("%04X:%08X: OUTW port=%04x, val=%04x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4485,16 +4778,23 @@ ati8514_accel_outl(uint16_t port, uint32_t val, void *priv) { svga_t *svga = (svga_t *)priv; mach_t *mach = (mach_t *)svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) { - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); - } else { - ati8514_accel_out(port, val, svga); - ati8514_accel_out(port + 1, (val >> 8), svga); - ati8514_accel_out(port + 2, (val >> 16), svga); - ati8514_accel_out(port + 3, (val >> 24), svga); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(svga, port, val, 2); + mach_log("OUTL port=%04x, val=%08x, fifo idx=%d.\n", port, val, dev->fifo_idx); } static void @@ -4502,11 +4802,20 @@ mach_accel_outb(uint16_t port, uint8_t val, void *priv) { mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); - else - mach_accel_out(port, val, mach); + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } + } + dev->accel_out_fifo(mach, port, val, 1); + mach_log("%04X:%08X: OUTB port=%04x, val=%02x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4514,13 +4823,23 @@ mach_accel_outw(uint16_t port, uint16_t val, void *priv) { mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); - else { - mach_accel_out(port, val, mach); - mach_accel_out(port + 1, (val >> 8), mach); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(mach, port, val, 2); + mach_log("%04X:%08X: OUTW port=%04x, val=%04x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4528,16 +4847,23 @@ mach_accel_outl(uint16_t port, uint32_t val, void *priv) { mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) { - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); - } else { - mach_accel_out(port, val, mach); - mach_accel_out(port + 1, (val >> 8), mach); - mach_accel_out(port + 2, (val >> 16), mach); - mach_accel_out(port + 3, (val >> 24), mach); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(mach, port, val, 2); + mach_log("OUTL port=%04x, val=%08x, fifo idx=%d.\n", port, val, dev->fifo_idx); } static uint8_t @@ -4558,6 +4884,7 @@ ati8514_accel_inb(uint16_t port, void *priv) else temp = ati8514_accel_in(port, svga); + mach_log("%04X:%08X: INB port=%04x, temp=%02x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4574,6 +4901,8 @@ ati8514_accel_inw(uint16_t port, void *priv) temp = ati8514_accel_in(port, svga); temp |= (ati8514_accel_in(port + 1, svga) << 8); } + + mach_log("%04X:%08X: INW port=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4584,14 +4913,11 @@ ati8514_accel_inl(uint16_t port, void *priv) mach_t *mach = (mach_t *)svga->ext8514; uint32_t temp; - if (port & 0x8000) { + if (port & 0x8000) temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); - temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); - } else { + else { temp = ati8514_accel_in(port, svga); temp |= (ati8514_accel_in(port + 1, svga) << 8); - temp |= (ati8514_accel_in(port + 2, svga) << 16); - temp |= (ati8514_accel_in(port + 3, svga) << 24); } return temp; } @@ -4615,6 +4941,7 @@ mach_accel_inb(uint16_t port, void *priv) else temp = mach_accel_in(port, mach); + mach_log("%04X:%08X: INB port=%04x, temp=%02x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4631,6 +4958,8 @@ mach_accel_inw(uint16_t port, void *priv) temp = mach_accel_in(port, mach); temp |= (mach_accel_in(port + 1, mach) << 8); } + + mach_log("%04X:%08X: INW port=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4641,14 +4970,11 @@ mach_accel_inl(uint16_t port, void *priv) svga_t *svga = &mach->svga; uint32_t temp; - if (port & 0x8000) { + if (port & 0x8000) temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); - temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); - } else { + else { temp = mach_accel_in(port, mach); temp |= (mach_accel_in(port + 1, mach) << 8); - temp |= (mach_accel_in(port + 2, mach) << 16); - temp |= (mach_accel_in(port + 3, mach) << 24); } return temp; } @@ -4817,6 +5143,11 @@ mach32_write(uint32_t addr, uint8_t val, void *priv) xga_write_test(addr, val, svga); addr = (addr & svga->banked_mask) + svga->write_bank; + if (mach->accel.test2 & 0x10) { + if (addr < ((mach->accel.test2 & 0x0f) << 18)) + return; + } + if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; switch (addr & 0x06) { @@ -4838,6 +5169,8 @@ mach32_write(uint32_t addr, uint8_t val, void *priv) } } else mach32_write_common(addr, val, 0, mach, svga); + + mach_log("Writeb banked=%08x.\n", addr); } static void @@ -4850,6 +5183,11 @@ mach32_writew(uint32_t addr, uint16_t val, void *priv) xga_write_test(addr, val, svga); addr = (addr & svga->banked_mask) + svga->write_bank; + if (mach->accel.test2 & 0x10) { + if (addr < ((mach->accel.test2 & 0x0f) << 18)) + return; + } + if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; if (addr & 0x04) { @@ -4867,6 +5205,7 @@ mach32_writew(uint32_t addr, uint16_t val, void *priv) mach32_write_common(addr, val & 0xff, 0, mach, svga); mach32_write_common(addr + 1, val >> 8, 0, mach, svga); } + mach_log("Writew banked=%08x.\n", addr); } static void @@ -4879,6 +5218,11 @@ mach32_writel(uint32_t addr, uint32_t val, void *priv) xga_write_test(addr, val, svga); addr = (addr & svga->banked_mask) + svga->write_bank; + if (mach->accel.test2 & 0x10) { + if (addr < ((mach->accel.test2 & 0x0f) << 18)) + return; + } + if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; mach32_write_common(addr, val & 0x0f, 0, mach, svga); @@ -4895,6 +5239,223 @@ mach32_writel(uint32_t addr, uint32_t val, void *priv) mach32_write_common(addr + 2, val >> 16, 0, mach, svga); mach32_write_common(addr + 3, val >> 24, 0, mach, svga); } + + mach_log("Writel banked=%08x.\n", addr); +} + +static __inline void +mach32_svga_write(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + int writemask2 = svga->writemask; + int reset_wm = 0; + latch_t vall; + uint8_t wm = svga->writemask; + uint8_t count; + uint8_t i; + + cycles -= svga->monitor->mon_video_timing_write_b; + + xga_write_test(addr, val, svga); + addr = svga_decode_addr(svga, addr, 1); + if (addr == 0xffffffff) { + mach_log("WriteCommon Over.\n"); + return; + } + + if (mach->accel.test2 & 0x10) { + if (addr >= ((mach->accel.test2 & 0x0f) << 18)) + return; + } + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if (((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain4 && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) { + mach_log("WriteBankedOver=%08x, val=%02x.\n", addr & svga->vram_mask, val); + return; + } + + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + + count = 4; + + switch (svga->writemode) { + case 0: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = val; + } + return; + } else { + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = val; + } + } + break; + case 1: + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = svga->latch.b[i]; + } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(val & (1 << i)) * 0xff; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + return; + } + break; + case 3: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= val; + + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + + reset_wm = 1; + break; + default: + return; + } + + switch (svga->gdcreg[3] & 0x18) { + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } + break; + + default: + break; + } + + if (reset_wm) + svga->gdcreg[8] = wm; +} + +static __inline void +mach32_svga_writew(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + + if (!svga->fast) { + mach32_svga_write(addr, val, priv); + mach32_svga_write(addr + 1, val >> 8, priv); + return; + } + + cycles -= svga->monitor->mon_video_timing_write_w; + + xga_write_test(addr, val & 0xff, svga); + xga_write_test(addr + 1, val >> 8, svga); + addr = svga_decode_addr(svga, addr, 1); + + if (addr == 0xffffffff) + return; + + if (mach->accel.test2 & 0x10) { + if (addr >= ((mach->accel.test2 & 0x0f) << 18)) + return; + } + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + *(uint16_t *) &svga->vram[addr] = val; +} + +static __inline void +mach32_svga_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + + if (!svga->fast) { + mach32_svga_write(addr, val, priv); + mach32_svga_write(addr + 1, val >> 8, priv); + mach32_svga_write(addr + 2, val >> 16, priv); + mach32_svga_write(addr + 3, val >> 24, priv); + return; + } + + cycles -= svga->monitor->mon_video_timing_write_l; + + xga_write_test(addr, val & 0xff, svga); + xga_write_test(addr + 1, (val >> 8) & 0xff, svga); + xga_write_test(addr + 2, (val >> 16) & 0xff, svga); + xga_write_test(addr + 3, (val >> 24) & 0xff, svga); + addr = svga_decode_addr(svga, addr, 1); + + if (addr == 0xffffffff) + return; + + if (mach->accel.test2 & 0x10) { + if (addr >= ((mach->accel.test2 & 0x0f) << 18)) + return; + } + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + *(uint32_t *) &svga->vram[addr] = val; } static __inline void @@ -5100,6 +5661,7 @@ mach32_read(uint32_t addr, void *priv) } else ret = mach32_read_common(addr, 0, mach, svga); + mach_log("Readb banked=%08x.\n", addr); return ret; } @@ -5131,6 +5693,7 @@ mach32_readw(uint32_t addr, void *priv) ret = mach32_read_common(addr, 0, mach, svga); ret |= (mach32_read_common(addr + 1, 0, mach, svga) << 8); } + mach_log("Readw banked=%08x.\n", addr); return ret; } @@ -5161,6 +5724,7 @@ mach32_readl(uint32_t addr, void *priv) ret |= (mach32_read_common(addr + 2, 0, mach, svga) << 16); ret |= (mach32_read_common(addr + 3, 0, mach, svga) << 24); } + mach_log("Readl banked=%08x.\n", addr); return ret; } @@ -5224,19 +5788,22 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (addr & 1) + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (addr & 1) + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - mach_log("Port WORDB Write=%04x.\n", 0x02ee + (port_dword << 8)); - mach_accel_outb(0x02ee + (addr & 1) + (port_dword << 8), val, mach); + mach_log("Port WORDB Write=%04x.\n", actual_port_ext); + mach_accel_outb(actual_port_ext, val, mach); } else { - mach_log("Port WORDB Write=%04x.\n", 0x02e8 + (port_dword << 8)); - mach_accel_outb(0x02e8 + (addr & 1) + (port_dword << 8), val, mach); + mach_log("Port WORDB Write=%04x.\n", actual_port); + mach_accel_outb(actual_port, val, mach); } } else { mach_log("Linear WORDB Write=%08x, val=%02x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + if (dev->on) mach32_write_common(addr, val, 1, mach, svga); else @@ -5251,19 +5818,21 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); - mach_accel_outw(0x02ee + (port_dword << 8), val, mach); + mach_log("Port WORDW Write=%04x, localcntl=%02x, pcicntl=%02x, actual addr=%08x, val=%04x.\n", actual_port_ext, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80, addr, val); + mach_accel_outw(actual_port_ext, val, mach); } else { - mach_log("Port WORDW Write=%04x.\n", 0x02e8 + (port_dword << 8)); - mach_accel_outw(0x02e8 + (port_dword << 8), val, mach); + mach_log("Port WORDW Write=%04x, localcntl=%02x, pcicntl=%02x, actual addr=%08x.\n", actual_port, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80, addr); + mach_accel_outw(actual_port, val, mach); } } else { - mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x.\n", - addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x, base=%08x, 8514/A port=%04x, ATI port=%04x, switch=%03x.\n", + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20, mach->linear_base, actual_port, actual_port_ext, addr & 0x100); if (dev->on) mach32_writew_linear(addr, val, mach); else @@ -5278,6 +5847,8 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); @@ -5285,13 +5856,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - mach_log("Port WORDL Write=%04x.\n", 0x02ee + (port_dword << 8)); - mach_accel_outw(0x02ee + (port_dword << 8), val & 0xffff, mach); - mach_accel_outw(0x02ee + (port_dword << 8) + 4, val >> 16, mach); + mach_log("Port WORDL Write=%04x, localcntl=%02x, pcicntl=%02x.\n", actual_port_ext, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80); + mach_accel_outl(actual_port_ext, val, mach); } else { - mach_log("Port WORDL Write=%04x.\n", 0x02e8 + (port_dword << 8)); - mach_accel_outw(0x02e8 + (port_dword << 8), val & 0xffff, mach); - mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); + mach_log("Port WORDL Write=%04x, localcntl=%02x, pcicntl=%02x.\n", actual_port, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80); + mach_accel_outl(actual_port, val, mach); } } else { if (dev->on) @@ -5309,13 +5878,15 @@ mach32_ap_readb(uint32_t addr, void *priv) const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (addr & 1) + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (addr & 1) + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) - temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); + temp = mach_accel_inb(actual_port_ext, mach); else - temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); + temp = mach_accel_inb(actual_port, mach); } else { if (dev->on) temp = mach32_read_common(addr, 1, mach, svga); @@ -5335,14 +5906,19 @@ mach32_ap_readw(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint16_t temp; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if (addr & 0x100) - temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); - else - temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); + if (addr & 0x100) { + temp = mach_accel_inw(actual_port_ext, mach); + mach_log("Port WORDW Read=%04x.\n", actual_port_ext); + } else { + temp = mach_accel_inw(actual_port, mach); + mach_log("Port WORDW Read=%04x.\n", actual_port); + } } else { if (dev->on) temp = mach32_readw_linear(addr, mach); @@ -5363,15 +5939,17 @@ mach32_ap_readl(uint32_t addr, void *priv) const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); - temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); + temp = mach_accel_inl(actual_port_ext, mach); + mach_log("Port WORDL Read=%04x.\n", actual_port_ext); } else { - temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); - temp |= (mach_accel_inw(0x02e8 + (port_dword << 8) + 4, mach) << 8); + temp = mach_accel_inl(actual_port, mach); + mach_log("Port WORDL Read=%04x.\n", actual_port); } } else { if (dev->on) @@ -5405,14 +5983,17 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; + mem_mapping_set_addr(&mach->banked_mapping, 0xa0000, 0x20000); break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; + mem_mapping_set_addr(&mach->banked_mapping, 0xa0000, 0x10000); break; case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; + mem_mapping_set_addr(&mach->banked_mapping, 0xb0000, 0x08000); break; case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); @@ -5426,6 +6007,7 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) } } } + mem_mapping_set_addr(&mach->banked_mapping, 0xb8000, 0x08000); break; default: @@ -5433,7 +6015,7 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) } } - mach_log("Linear base = %08x, aperture = %04x, localcntl = %02x svgagdc = %x.\n", + mach_log("Linear base=%08x, aperture=%04x, localcntl=%02x, svgagdc=%x.\n", mach->linear_base, mach->memory_aperture, mach->local_cntl, svga->gdcreg[6] & 0x0c); if (mach->linear_base) { if (((mach->memory_aperture & 3) == 1) && !mach->pci_bus) { @@ -5452,24 +6034,20 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) mach_log("Linear Disabled APSIZE=4.\n"); mem_mapping_disable(&mach->mmio_linear_mapping); } + if ((dev->local & 0xff) >= 0x02) { if (dev->on && dev->vendor_mode) { mach_log("Mach32 banked mapping.\n"); - mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); - mem_mapping_set_p(&svga->mapping, mach); + mem_mapping_disable(&svga->mapping); + mem_mapping_enable(&mach->banked_mapping); } else { - if (!dev->on) { - memset(dev->vram, 0, dev->vram_size); - memset(dev->changedvram, 0, (dev->vram_size >> 12) + 1); - } mach_log("IBM compatible banked mapping.\n"); - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&svga->mapping, svga); + mem_mapping_enable(&svga->mapping); + mem_mapping_disable(&mach->banked_mapping); } } else { - mach_log("IBM compatible banked mapping.\n"); - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&svga->mapping, svga); + mem_mapping_enable(&svga->mapping); + mem_mapping_disable(&mach->banked_mapping); } } @@ -5869,6 +6447,7 @@ mach_io_set(mach_t *mach) io_sethandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x86ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x8aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -5891,6 +6470,7 @@ mach_io_set(mach_t *mach) io_sethandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xeaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -6122,6 +6702,95 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) } } +static void +mach_vblank_start(mach_t *mach, svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + dev->subsys_stat |= INT_VSY; +} + +static void +mach_combo_vblank_start(void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + + mach_vblank_start(mach, svga); +} + +static void +ati8514_vblank_start(void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + + mach_vblank_start(mach, svga); +} + +static void +mach_combo_accel_out_fifo(void *priv, uint16_t port, uint16_t val, int len) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("Accel OUT Combo=%04x, val=%04x, len=%d.\n", port, val, len); + mach_accel_out_fifo(mach, svga, dev, port, val, len); +} + +static void +ati8514_accel_out_fifo(void *priv, uint16_t port, uint16_t val, int len) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_accel_out_fifo(mach, svga, dev, port, val, len); +} + +static void +mach_disable_handlers(mach_t *mach) +{ + io_removehandler(0x01ce, 2, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + mach_io_remove(mach); + + mem_mapping_disable(&mach->mmio_linear_mapping); + mem_mapping_disable(&mach->banked_mapping); + mem_mapping_disable(&mach->svga.mapping); + if (mach->pci_bus && mach->has_bios) + mem_mapping_disable(&mach->bios_rom.mapping); + + /* Save all the mappings and the timers because they are part of linked lists. */ + reset_state->mmio_linear_mapping = mach->mmio_linear_mapping; + reset_state->banked_mapping = mach->banked_mapping; + reset_state->svga.mapping = mach->svga.mapping; + reset_state->bios_rom.mapping = mach->bios_rom.mapping; + + reset_state->svga.timer = mach->svga.timer; +} + +static void +mach_reset(void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (reset_state != NULL) { + mach_disable_handlers(mach); + mach->force_busy = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + if (mach->pci_bus) + reset_state->pci_slot = mach->pci_slot; + + *mach = *reset_state; + } +} + static void * mach8_init(const device_t *info) { @@ -6130,6 +6799,7 @@ mach8_init(const device_t *info) ibm8514_t *dev; mach = calloc(1, sizeof(mach_t)); + reset_state = calloc(1, sizeof(mach_t)); svga = &mach->svga; dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); @@ -6145,6 +6815,7 @@ mach8_init(const device_t *info) mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : 1; dev->vram_amount = device_get_config_int("memory"); dev->vram_512k_8514 = dev->vram_amount == 512; + dev->accel.cmd_back = 1; if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus) { @@ -6227,8 +6898,12 @@ mach8_init(const device_t *info) mach->config1 |= 0x0400; svga->clock_gen = device_add(&ati18811_1_device); } + mem_mapping_add(&mach->banked_mapping, 0, 0, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel, NULL, MEM_MAPPING_EXTERNAL, mach); mem_mapping_add(&mach->mmio_linear_mapping, 0, 0, mach32_ap_readb, mach32_ap_readw, mach32_ap_readl, mach32_ap_writeb, mach32_ap_writew, mach32_ap_writel, NULL, MEM_MAPPING_EXTERNAL, mach); + mem_mapping_disable(&mach->banked_mapping); mem_mapping_disable(&mach->mmio_linear_mapping); + + mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, mach32_svga_write, mach32_svga_writew, mach32_svga_writel); } else { svga_init(info, svga, mach, (512 << 10), /*default: 512kB VGA for 28800-6 + 1MB for Mach8*/ mach_recalctimings, @@ -6240,7 +6915,7 @@ mach8_init(const device_t *info) dev->changedvram = calloc((dev->vram_size >> 12) + 1, 1); dev->vram_mask = dev->vram_size - 1; video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); - mach->config1 = 0x01 | 0x02 | 0x08 | 0x80; + mach->config1 = 0x01 | 0x08 | 0x80; if (dev->vram_amount >= 1024) mach->config1 |= 0x20; @@ -6296,6 +6971,11 @@ mach8_init(const device_t *info) } else ati_eeprom_load_mach8_vga(&mach->eeprom, "mach8.nvr"); + dev->accel_out_fifo = mach_combo_accel_out_fifo; + dev->vblank_start = mach_combo_vblank_start; + + *reset_state = *mach; + return mach; } @@ -6315,9 +6995,11 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); ati8514_io_set(svga); + mach->accel.cmd_type = -2; mach->mca_bus = !!(dev->type & DEVICE_MCA); + dev->accel.cmd_back = 1; - mach->config1 = 0x02 | 0x08 | 0x80; + mach->config1 = 0x08 | 0x80; if (mach->mca_bus) mach->config1 |= 0x04; @@ -6326,6 +7008,9 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) mach->config1 |= 0x20; mach->config2 = 0x01 | 0x02; + + dev->accel_out_fifo = ati8514_accel_out_fifo; + dev->vblank_start = ati8514_vblank_start; } static int @@ -6373,6 +7058,10 @@ mach_close(void *priv) } svga_close(svga); + + free(reset_state); + reset_state = NULL; + free(mach); } @@ -6479,7 +7168,7 @@ const device_t mach8_vga_isa_device = { .local = 1, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach8_vga_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6493,7 +7182,7 @@ const device_t mach32_isa_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_isa_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6507,7 +7196,7 @@ const device_t mach32_vlb_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_vlb_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6521,7 +7210,7 @@ const device_t mach32_mca_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_mca_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6535,7 +7224,7 @@ const device_t mach32_pci_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_pci_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6549,7 +7238,7 @@ const device_t mach32_onboard_pci_device = { .local = 2 | 0x100, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = NULL, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, From 1c98437e664918c05e66e4d664ae061fc0374bb0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:49:13 +0100 Subject: [PATCH 32/32] More display changes. SVGA related: If CRTC1/HDISP is odd (if bit 0 is set), then make it even accordingly, else leave it as is. Should fix some display skews. S3 related: Remove old code references (can still be accessed through history if one needs it). 8514/A compatible related: Proper use of the htotal and hdisp timings. --- src/video/vid_s3.c | 177 +------------------------------------------ src/video/vid_svga.c | 10 ++- 2 files changed, 8 insertions(+), 179 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 769cd0001..ef21b18df 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3519,34 +3519,6 @@ s3_recalctimings(svga_t *svga) } } -#ifdef OLD_CODE_REFERENCE - if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (!(svga->crtc[0x5e] & 0x04)) - svga->vblankstart = svga->dispend; - if (svga->bpp != 32) { - if (svga->crtc[0x31] & 2) - s3->width = 2048; - else { - if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - if (svga->hdisp == 1280 && s3->width == 1024) { - s3->width = 1280; - } - } - } - } else { - if (s3->card_type == S3_NUMBER9_9FX_531) { - if ((svga->hdisp == 1600) && (s3->width == 1600)) - s3->width = 800; - } - } - } else if (s3->chip == S3_86C928) { - if (svga->bpp == 15) { - if (s3->width == 800) - s3->width = 1024; - } - } -#endif - if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " "attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], @@ -3665,29 +3637,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if (s3->chip != S3_VISION868) { - if (s3->chip == S3_86C928) { - if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) { - if ((s3->width != 1600) && (svga->dispend == 1024) && (svga->hdisp != 1280)) - svga->hdisp <<= 2; - else - svga->hdisp <<= 1; - } - } else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } - } else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } -#endif break; case 15: svga->render = svga_render_15bpp_highres; @@ -3856,29 +3805,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { - if (s3->chip == S3_86C928) - svga->hdisp <<= 1; - else if (s3->chip != S3_VISION968) - svga->hdisp >>= 1; - } - if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp == (1408 * 2)) - svga->hdisp >>= 1; - else - svga->hdisp = s3->width; - } - - if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) - svga->hdisp = s3->width; -#endif break; case 16: svga->render = svga_render_16bpp_highres; @@ -4044,35 +3970,6 @@ s3_recalctimings(svga_t *svga) default: break; } - -#ifdef OLD_CODE_REFERENCE - if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } - if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { - if (s3->chip == S3_86C928) - svga->hdisp <<= 1; - else if (s3->chip != S3_VISION968) - svga->hdisp >>= 1; - } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) - svga->hdisp >>= 1; - if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp == (1408 << 1)) - svga->hdisp >>= 1; - else - svga->hdisp = s3->width; - } - - if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) - svga->hdisp = s3->width; -#endif break; case 24: svga->render = svga_render_24bpp_highres; @@ -4150,34 +4047,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if (s3->chip != S3_VISION968) { - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) - svga->hdisp /= 3; - else - svga->hdisp = (svga->hdisp * 2) / 3; - - if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (s3->width == 2048) { - switch (svga->dispend) { - case 480: - svga->hdisp = 640; - break; - - default: - break; - } - } - } else if (s3->chip == S3_86C924) { - if (svga->dispend == 480) - svga->hdisp = 640; - } - } else { - if ((s3->card_type == S3_MIROVIDEO40SV_ERGO_968) || - (s3->card_type == S3_PHOENIX_VISION968) || (s3->card_type == S3_SPEA_MERCURY_P64V)) - svga->hdisp = s3->width; - } -#endif break; case 32: svga->render = svga_render_32bpp_highres; @@ -4262,48 +4131,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { - if (s3->chip == S3_VISION868) - svga->hdisp >>= 1; - else - svga->hdisp >>= 2; - } - if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_NUMBER9_9FX_771)) - svga->hdisp <<= 1; - if (s3->card_type == S3_NUMBER9_9FX_771) { - if (svga->hdisp == 832) - svga->hdisp -= 32; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - svga->hdisp = s3->width; - if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { - if (s3->width == 800 || s3->width == 1024 || s3->width == 1600) { - switch (svga->dispend) { - case 400: - case 480: - svga->hdisp = 640; - break; - - case 576: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 768; - break; - - case 600: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 800; - break; - - default: - break; - } - } - } - } -#endif break; default: @@ -4362,7 +4189,7 @@ s3_trio64v_recalctimings(svga_t *svga) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * svga->dots_per_clock; + svga->hdisp |= (0x100 * svga->dots_per_clock); } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -4681,6 +4508,7 @@ s3_trio64_getclock(int clock, void *priv) return 25175000.0; if (clock == 1) return 28322000.0; + m = svga->seqregs[0x13] + 2; n1 = (svga->seqregs[0x12] & 0x1f) + 2; n2 = ((svga->seqregs[0x12] >> 5) & 0x07); @@ -9523,7 +9351,6 @@ s3_disable_handlers(s3_t *s3) reset_state->bios_rom.mapping = s3->bios_rom.mapping; reset_state->svga.timer = s3->svga.timer; - reset_state->svga.timer8514 = s3->svga.timer8514; memset(s3->svga.vram, 0x00, s3->svga.vram_max + 8); memset(s3->svga.changedvram, 0x00, (s3->svga.vram_max >> 12) + 1); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index c7a65120f..a44838d68 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -739,7 +739,8 @@ svga_recalctimings(svga_t *svga) svga->vblankstart++; svga->hdisp = svga->crtc[1]; - svga->hdisp++; + if (svga->crtc[1] & 1) + svga->hdisp++; svga->htotal = svga->crtc[0]; /* +5 has been verified by Sergi to be correct - +6 must have been an off by one error. */ @@ -944,7 +945,7 @@ svga_recalctimings(svga_t *svga) if (dev->on) { uint32_t dot8514 = dev->h_blankstart; uint32_t adj_dot8514 = dev->h_blankstart; - uint32_t eff_mask8514 = 0x0000003f; + uint32_t eff_mask8514 = 0x0000001f; dev->hblank_sub = 0; while (adj_dot8514 < (dev->h_total << 1)) { @@ -1029,8 +1030,9 @@ svga_recalctimings(svga_t *svga) if (ibm8514_active && (svga->dev8514 != NULL)) { if (dev->on) { - disptime8514 = dev->h_total ? dev->h_total : TIMER_USEC; - _dispontime8514 = dev->hdisped; + disptime8514 = dev->h_total; + _dispontime8514 = (dev->hdisped + 1) * 8; + svga_log("HDISPED 8514=%d, htotal=%02x.\n", (dev->hdisped + 1) << 3, dev->h_total); } }