From 6802c0593b10e090b21f7e70d72d5a63f3ac9251 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 30 Sep 2023 22:08:08 +0200 Subject: [PATCH] Video, Storage and MCA changes/fixes. 1. Cirrus Logic GD54xx, Paradise/WD VGA now reset the interlace once a text mode is issued if not done automatically. 2. Paradise/WD's 15/16bpp modes using the 800x600 resolution now have the correct ma_latch, should fix most operating systems drivers using this combo. 3. More fixes (hopefully) to the accelerated pitch and rowoffset of the Trident TGUI cards (9440AGi and 96x0XGi), should fix issues with delayed displays mode changes under various operating systems (e.g.: Win3.1x). 4. Preliminary implementation of the Area Fill command of XGA, which is issued while using various painting and/or calc utilities on Win3.1x (IBM XGA updated drivers, e.g.: 2.12). 5. Preliminary (and incomplete) 4bpp XGA mode. 6. The XGA memory test for the 0xa5 using writes (used by various operating systems) no longer conflicts with DOS' XGAKIT's memory detection. 7. Small ROP fixes to both XGA and 8514/A. 8. Re-organized the mapping of the Mach32 chipset, especially when to enable the ATI mode or switching back to IBM mode, should fix LFB conflicts with various operating systems. 9. According to The OS/2 Museum, the Adaptec AHA-154xB series of SCSI cards fail the ASPI4DOS.SYS 3.36 signature check, so now make the changes accordingly. 10. Remove useless and crashy bios-less option of the Trantor T128. 11. The Image Manager 1024 card can also be used on a XT (although only if it has a V20/V30). 12. Re-organized the IBM PS/2 model 60 initialization as well as its right POS machine ID (though an update to sc.exe is still required for the POST memory amount to work normally). --- src/include/86box/scsi_x54x.h | 3 +- src/include/86box/vid_xga.h | 3 + src/machine/m_ps2_mca.c | 64 +++---- src/scsi/scsi_ncr5380.c | 29 ++- src/scsi/scsi_x54x.c | 42 ++-- src/video/vid_8514a.c | 122 +++++++----- src/video/vid_ati_mach8.c | 148 +++++++------- src/video/vid_cl54xx.c | 11 ++ src/video/vid_im1024.c | 2 +- src/video/vid_paradise.c | 25 ++- src/video/vid_svga.c | 12 +- src/video/vid_tgui9440.c | 52 ++++- src/video/vid_xga.c | 349 +++++++++++++++++++++++++++------- 13 files changed, 587 insertions(+), 275 deletions(-) diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index 22d4b35e4..0f1874302 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -366,6 +366,7 @@ typedef struct SGE_t { #define X54X_INT_GEOM_WRITABLE 8 #define X54X_MBX_24BIT 16 #define X54X_ISAPNP 32 +#define X54X_HAS_SIGNATURE 64 typedef struct x54x_t { /* 32 bytes */ @@ -404,7 +405,7 @@ typedef struct x54x_t { /* for multi-threading, keep these volatile */ volatile uint8_t Status; - volatile uint8_t Interrupt; + volatile uint8_t Interrupt; volatile uint8_t MailboxIsBIOS; volatile uint8_t ToRaise; volatile uint8_t flags; diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index 97eb1456f..739e30c5c 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -201,6 +201,8 @@ typedef struct xga_t { int dst_map; int bkgd_src; int fore_src; + int oldx; + int oldy; int x; int y; int sx; @@ -211,6 +213,7 @@ typedef struct xga_t { int py; int pattern; int command_len; + int filling; uint32_t short_stroke; uint32_t color_cmp; diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index b93f332db..a6fc30e1c 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -362,11 +362,6 @@ static void model_50_write(uint16_t port, uint8_t val) { switch (port) { - case 0x100: - ps2.io_id = val; - break; - case 0x101: - break; case 0x102: lpt1_remove(); serial_remove(ps2.uart); @@ -499,11 +494,6 @@ static void model_55sx_write(uint16_t port, uint8_t val) { switch (port) { - case 0x100: - ps2.io_id = val; - break; - case 0x101: - break; case 0x102: lpt1_remove(); serial_remove(ps2.uart); @@ -563,10 +553,6 @@ static void model_70_type3_write(uint16_t port, uint8_t val) { switch (port) { - case 0x100: - break; - case 0x101: - break; case 0x102: lpt1_remove(); serial_remove(ps2.uart); @@ -621,10 +607,6 @@ static void model_80_write(uint16_t port, uint8_t val) { switch (port) { - case 0x100: - break; - case 0x101: - break; case 0x102: lpt1_remove(); serial_remove(ps2.uart); @@ -985,12 +967,12 @@ ps2_mca_mem_d071_init(int start_mb) } static void -ps2_mca_board_model_50_init(int slots) +ps2_mca_board_model_50_init(void) { ps2_mca_board_common_init(); mem_remap_top(384); - mca_init(slots); + mca_init(4); device_add(&keyboard_ps2_mca_2_device); ps2.planar_read = model_50_read; @@ -1005,6 +987,29 @@ ps2_mca_board_model_50_init(int slots) device_add(&ps1vga_mca_device); } +static void +ps2_mca_board_model_60_init(void) +{ + ps2_mca_board_common_init(); + + mem_remap_top(384); + mca_init(8); + device_add(&keyboard_ps2_mca_2_device); + + ps2.planar_read = model_50_read; + ps2.planar_write = model_50_write; + + if (mem_size > 2048) { + /* Only 2 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(2); + } + + device_add(&ps2_nvr_55ls_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&ps1vga_mca_device); +} + static void ps2_mca_board_model_55sx_init(int has_sec_nvram, int slots) { @@ -1051,10 +1056,8 @@ ps2_mca_board_model_55sx_init(int has_sec_nvram, int slots) mca_init(slots); device_add(&keyboard_ps2_device); - if (has_sec_nvram == 1) + if (has_sec_nvram) device_add(&ps2_nvr_55ls_device); - else if (has_sec_nvram == 2) - device_add(&ps2_nvr_device); ps2.planar_read = model_55sx_read; ps2.planar_write = model_55sx_write; @@ -1312,7 +1315,7 @@ ps2_mca_board_model_70_type34_init(int is_type4, int slots) } static void -ps2_mca_board_model_80_type2_init(int is486ps2) +ps2_mca_board_model_80_type2_init(void) { ps2_mca_board_common_init(); @@ -1372,7 +1375,7 @@ ps2_mca_board_model_80_type2_init(int is486ps2) NULL); mem_mapping_disable(&ps2.split_mapping); - if ((mem_size > 4096) && !is486ps2) { + if (mem_size > 4096) { /* Only 4 MB supported on planar, create a memory expansion card for the rest */ if (mem_size > 12288) ps2_mca_mem_d071_init(4); @@ -1426,7 +1429,7 @@ machine_ps2_model_50_init(const machine_t *model) machine_ps2_common_init(model); ps2.planar_id = 0xfbff; - ps2_mca_board_model_50_init(4); + ps2_mca_board_model_50_init(); return ret; } @@ -1448,8 +1451,8 @@ machine_ps2_model_60_init(const machine_t *model) machine_ps2_common_init(model); - ps2.planar_id = 0xfbff; - ps2_mca_board_model_50_init(8); + ps2.planar_id = 0xf7ff; + ps2_mca_board_model_60_init(); return ret; } @@ -1509,7 +1512,6 @@ machine_ps2_model_70_type3_init(const machine_t *model) machine_ps2_common_init(model); ps2.planar_id = 0xf9ff; - ps2_mca_board_model_70_type34_init(0, 4); return ret; @@ -1530,7 +1532,7 @@ machine_ps2_model_80_init(const machine_t *model) machine_ps2_common_init(model); ps2.planar_id = 0xfdff; - ps2_mca_board_model_80_type2_init(0); + ps2_mca_board_model_80_type2_init(); return ret; } @@ -1550,7 +1552,6 @@ machine_ps2_model_80_axx_init(const machine_t *model) machine_ps2_common_init(model); ps2.planar_id = 0xfff9; - ps2_mca_board_model_70_type34_init(0, 8); return ret; @@ -1571,7 +1572,6 @@ machine_ps2_model_70_type4_init(const machine_t *model) machine_ps2_common_init(model); ps2.planar_id = 0xf9ff; - ps2_mca_board_model_70_type34_init(1, 4); return ret; diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index c4bec884d..656257849 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -1553,10 +1553,14 @@ ncr_init(const device_t *info) ncr_dev->bios_ver = 1; } - if (ncr_dev->bios_ver == 1) - fn = RT1000B_820R_ROM; - else - fn = RT1000B_810R_ROM; + switch (ncr_dev->bios_ver) { + case 0: + fn = RT1000B_810R_ROM; + break; + case 1: + fn = RT1000B_820R_ROM; + break; + } rom_init(&ncr_dev->bios_rom, fn, ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -1601,9 +1605,8 @@ ncr_init(const device_t *info) ncr_dev->irq = device_get_config_int("irq"); ncr_dev->t128.bios_enabled = device_get_config_int("boot"); - if (ncr_dev->t128.bios_enabled) - rom_init(&ncr_dev->bios_rom, T128_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&ncr_dev->bios_rom, T128_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, t128_read, NULL, NULL, @@ -1635,15 +1638,12 @@ ncr_init(const device_t *info) ncr_log("%s\n", temp); ncr_reset(ncr_dev, &ncr_dev->ncr); - if (ncr_dev->type < 3 || ncr_dev->type == 4) { + if ((ncr_dev->type < 3) || (ncr_dev->type == 4)) { ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; ncr_dev->buffer_host_pos = 128; } else { ncr_dev->t128.status = 0x04; ncr_dev->t128.host_pos = 512; - - if (!ncr_dev->t128.bios_enabled) - ncr_dev->t128.status |= 0x80; } timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0); @@ -1894,13 +1894,6 @@ static const device_config_t t128_config[] = { { .description = "" } }, }, - { - .name = "boot", - .description = "Enable Boot ROM", - .type = CONFIG_BINARY, - .default_string = "", - .default_int = 1 - }, { .name = "", .description = "", .type = CONFIG_END } }; // clang-format on diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 2c714e18a..6876e4385 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -103,7 +103,7 @@ x54x_irq(x54x_t *dev, int set) else picintc(1 << irq); } - } + } } static void @@ -466,6 +466,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) } return 0; + break; case 0x02: /* Read Desired Sectors to Memory */ case 0x03: /* Write Desired Sectors from Memory */ @@ -1341,24 +1342,27 @@ x54x_in(uint16_t port, void *priv) if (dev->flags & X54X_INT_GEOM_WRITABLE) ret = dev->Geometry; else { - switch (dev->Geometry) { - default: - case 0: - ret = 'A'; - break; - case 1: - ret = 'D'; - break; - case 2: - ret = 'A'; - break; - case 3: - ret = 'P'; - break; - } - ret ^= 1; - dev->Geometry++; - dev->Geometry &= 0x03; + if (dev->flags & X54X_HAS_SIGNATURE) { + switch (dev->Geometry) { + default: + case 0: + ret = 'A'; + break; + case 1: + ret = 'D'; + break; + case 2: + ret = 'A'; + break; + case 3: + ret = 'P'; + break; + } + ret ^= 1; + dev->Geometry++; + dev->Geometry &= 0x03; + } else + ret = 0xff; break; } break; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 8ee0daadd..ef735852c 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -144,13 +144,13 @@ ibm8514_log(const char *fmt, ...) dest_dat = MAX(src_dat, dest_dat); \ break; \ case 0x15: \ - dest_dat = (dest_dat - src_dat) / 2; \ + dest_dat = (dest_dat - src_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 = (dest_dat + src_dat) >> 1; \ break; \ case 0x18: \ dest_dat = MAX(0, (dest_dat - src_dat)); \ @@ -162,7 +162,7 @@ ibm8514_log(const char *fmt, ...) dest_dat = MAX(0, (src_dat - dest_dat)); \ break; \ case 0x1b: \ - dest_dat = MIN(0xff, (dest_dat + src_dat)); \ + dest_dat = MIN(~0, (dest_dat + src_dat)); \ break; \ case 0x1c: \ dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ @@ -174,7 +174,7 @@ ibm8514_log(const char *fmt, ...) dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ break; \ case 0x1f: \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + dest_dat = (~0 < (src_dat + dest_dat)) ? ~0 : ((src_dat + dest_dat) >> 1); \ break; \ } \ } @@ -1297,7 +1297,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat /*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 the NOP command)*/ - ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d.\n", cmd, dev->accel.cmd, pixcntl, count); + ibm8514_log("CMD8514: CMD=%d, full=%04x, pixcntl=%x, count=%d, frgdmix = %02x, bkgdmix = %02x, polygon=%x.\n", cmd, dev->accel.cmd, pixcntl, count, frgd_mix, bkgd_mix, dev->accel.multifunc[0x0a] & 6); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -3057,13 +3057,39 @@ rect_fill: 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 & 4) && (dev->accel.sy < dev->accel.maj_axis_pcnt)) { - if (!dev->accel.sy) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } else if ((dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.cy == (dev->accel.oldcy + 1))) { - WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); - } else if (!(dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.err_term >= 0) && (dev->accel.cy == (dev->accel.oldcy + 1))) { + if (dev->accel.cmd & 4) { + if (dev->accel.sy < dev->accel.maj_axis_pcnt) { + if (dev->accel.cmd & 0x40) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } else { + if (dev->accel.cy == (dev->accel.oldcy + 1)) { + if (dev->accel.cmd & 0x20) { + if (dev->accel.err_term < (dev->accel.destx_distp + dev->accel.desty_axstp)) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } else { + if (dev->accel.err_term >= 0) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } + } + } + } + } else { + if (dev->accel.cmd & 0x40) { WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } else { + if (dev->accel.cy == (dev->accel.oldcy + 1)) { + if (dev->accel.cmd & 0x20) { + if (dev->accel.err_term < (dev->accel.destx_distp + dev->accel.desty_axstp)) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } else { + if (dev->accel.err_term >= 0) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } + } + } } } } @@ -3080,7 +3106,42 @@ rect_fill: break; } - if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx--; + break; + case 0x20: + dev->accel.cx++; + break; + case 0x40: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x60: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx++; + break; + case 0xc0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xe0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + + default: + break; + } + + if (dev->accel.err_term >= 0) { dev->accel.err_term += dev->accel.destx_distp; /*Step minor axis*/ switch (dev->accel.cmd & 0xe0) { @@ -3119,41 +3180,6 @@ rect_fill: } else dev->accel.err_term += dev->accel.desty_axstp; - /*Step major axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cx--; - break; - case 0x20: - dev->accel.cx++; - break; - case 0x40: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy--; - break; - case 0x60: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy--; - break; - case 0x80: - dev->accel.cx--; - break; - case 0xa0: - dev->accel.cx++; - break; - case 0xc0: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy++; - break; - case 0xe0: - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy++; - break; - - default: - break; - } - dev->accel.sy++; } break; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 8df054060..1d3f6bbc8 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -99,6 +99,7 @@ typedef struct mach_t { uint8_t bank_w; uint8_t bank_r; uint16_t shadow_set; + int ext_on; struct { uint8_t line_idx; @@ -2599,7 +2600,6 @@ mach_recalctimings(svga_t *svga) if (dev->on) { mach_log("8514/A ON.\n"); - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); if (dev->local >= 2) { dev->h_disp = (dev->hdisp + 1) << 3; dev->h_total = (dev->htotal + 1); @@ -2614,6 +2614,9 @@ mach_recalctimings(svga_t *svga) if (dev->dispend == 598) dev->dispend += 2; + if (dev->h_disp == 1024) + dev->accel.advfunc_cntl |= 4; /*Bit 2 means high resolution e.g.: 1024x768*/ + if (dev->accel.advfunc_cntl & 4) { if (mach->shadow_set & 2) { if (dev->h_disp == 8) { @@ -2622,14 +2625,20 @@ mach_recalctimings(svga_t *svga) dev->v_total = 1536; dev->v_syncstart = 1536; } - } + mach_log("Shadow set 2.\n"); + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } else { - if (mach->shadow_set & 1) { - if (dev->h_disp == 1024) { - dev->h_disp = 640; - dev->dispend = 480; - } + if (dev->h_disp == 1024) { + dev->h_disp = 640; + dev->dispend = 480; } + if (mach->shadow_set & 1) { + mach_log("Shadow set 1.\n"); + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } if (dev->interlace) { @@ -2721,14 +2730,18 @@ mach_recalctimings(svga_t *svga) dev->v_total = 1536; dev->v_syncstart = 1536; } - } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } else { - if (mach->shadow_set & 1) { - if (dev->h_disp == 1024) { - dev->h_disp = 640; - dev->dispend = 480; - } + if (dev->h_disp == 1024) { + dev->h_disp = 640; + dev->dispend = 480; } + if (mach->shadow_set & 1) { + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } if (dev->interlace) { dev->dispend >>= 1; @@ -2740,7 +2753,7 @@ mach_recalctimings(svga_t *svga) } dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x.\n", dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0); + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0); svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; if (mach->regs[0xb8] & 0x40) @@ -2750,6 +2763,7 @@ mach_recalctimings(svga_t *svga) if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { if (((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { + mach_log("VGA clock=%02x.\n", mach->regs[0xa7] & 0x80); svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); if (mach->regs[0xa7] & 0x80) svga->clock *= 3; @@ -3688,7 +3702,9 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } else { dev->on = (dev->accel.advfunc_cntl & 0x01); vga_on = !dev->on; - mach_log("ATI 8514/A: (0x4ae8) val = %04x\n", val & 0x01); + mach->ext_on = dev->on; + mach_log("ATI 8514/A: (0x4ae9) val = %04x, ext = %d.\n", dev->accel.advfunc_cntl & 0x01, mach->ext_on); + mach32_updatemapping(mach); } svga_recalctimings(svga); break; @@ -3777,6 +3793,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x36ee: case 0x36ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->misc, val); mach->misc &= 0xfff0; break; @@ -3813,21 +3830,27 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x4aef: WRITE8(port, mach->accel.clock_sel, val); if (port & 1) { - mach_log("ATI 8514/A: (0x4aee) val = %04x\n", mach->accel.clock_sel & 0x01); dev->on = mach->accel.clock_sel & 0x01; vga_on = !dev->on; + pclog("ATI 8514/A: (0x4aef) val = %04x, ext = %d.\n", mach->accel.clock_sel & 0x01, mach->ext_on); } svga_recalctimings(svga); break; case 0x52ee: case 0x52ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.scratch0, val); + if (port & 1) + mach->ext_on = 1; break; case 0x56ee: case 0x56ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.scratch1, val); + if (port & 1) + mach->ext_on = 1; break; case 0x5aee: @@ -4744,13 +4767,8 @@ mach32_write_linear(uint32_t addr, uint8_t val, void *priv) static void mach32_write(uint32_t addr, uint8_t val, void *priv) { - svga_t *svga = (svga_t *) priv; - const ibm8514_t *dev = &svga->dev8514; - - if (!dev->on) { - svga_write(addr, val, svga); - return; - } + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; addr = (addr & svga->banked_mask) + svga->write_bank; mach32_write_linear(addr, val, svga); @@ -4759,33 +4777,25 @@ mach32_write(uint32_t addr, uint8_t val, void *priv) static void mach32_writew(uint32_t addr, uint16_t val, void *priv) { - svga_t *svga = (svga_t *) priv; - const ibm8514_t *dev = &svga->dev8514; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; - if (!dev->on) { - svga_writew(addr, val, svga); - return; - } - - mach32_write(addr, val & 0xff, svga); - mach32_write(addr + 1, val >> 8, svga); + addr = (addr & svga->banked_mask) + svga->write_bank; + mach32_write_linear(addr, val & 0xff, svga); + mach32_write_linear(addr + 1, val >> 8, svga); } static void mach32_writel(uint32_t addr, uint32_t val, void *priv) { - svga_t *svga = (svga_t *) priv; - const ibm8514_t *dev = &svga->dev8514; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; - if (!dev->on) { - svga_writel(addr, val, svga); - return; - } - - mach32_write(addr, val & 0xff, svga); - mach32_write(addr + 1, val >> 8, svga); - mach32_write(addr + 2, val >> 16, svga); - mach32_write(addr + 3, val >> 24, svga); + addr = (addr & svga->banked_mask) + svga->write_bank; + mach32_write_linear(addr, val & 0xff, svga); + mach32_write_linear(addr + 1, val >> 8, svga); + mach32_write_linear(addr + 2, val >> 16, svga); + mach32_write_linear(addr + 3, val >> 24, svga); } static uint8_t @@ -4872,15 +4882,10 @@ mach32_read_linear(uint32_t addr, void *priv) static uint8_t mach32_read(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *) priv; - const ibm8514_t *dev = &svga->dev8514; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; uint8_t ret; - if (!dev->on) { - ret = svga_read(addr, svga); - return ret; - } - addr = (addr & svga->banked_mask) + svga->read_bank; ret = mach32_read_linear(addr, svga); return ret; @@ -4889,36 +4894,28 @@ mach32_read(uint32_t addr, void *priv) static uint16_t mach32_readw(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *) priv; - const ibm8514_t *dev = &svga->dev8514; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; uint16_t ret; - if (!dev->on) { - ret = svga_readw(addr, svga); - return ret; - } - - ret = mach32_read(addr, svga); - ret |= (mach32_read(addr + 1, svga) << 8); + addr = (addr & svga->banked_mask) + svga->read_bank; + ret = mach32_read_linear(addr, svga); + ret |= (mach32_read_linear(addr + 1, svga) << 8); return ret; } static uint32_t mach32_readl(uint32_t addr, void *priv) { - svga_t *svga = (svga_t *) priv; - const ibm8514_t *dev = &svga->dev8514; + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; uint32_t ret; - if (!dev->on) { - ret = svga_readl(addr, svga); - return ret; - } - - ret = mach32_read(addr, svga); - ret |= (mach32_read(addr + 1, svga) << 8); - ret |= (mach32_read(addr + 2, svga) << 16); - ret |= (mach32_read(addr + 3, svga) << 24); + addr = (addr & svga->banked_mask) + svga->read_bank; + ret = mach32_read_linear(addr, svga); + ret |= (mach32_read_linear(addr + 1, svga) << 8); + ret |= (mach32_read_linear(addr + 2, svga) << 16); + ret |= (mach32_read_linear(addr + 3, svga) << 24); return ret; } @@ -4986,7 +4983,7 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); } } else { - mach_log("Linear WORDL Write=%08x, val=%08x, mode=%d, rop=%02x.\n", addr, val, mach->svga.writemode, mach->svga.gdcreg[3] & 0x18); + mach_log("Linear WORDL Write=%08x.\n", addr); mach32_write_linear(addr, val & 0xff, svga); mach32_write_linear(addr + 1, val >> 8, svga); mach32_write_linear(addr + 2, val >> 16, svga); @@ -5069,6 +5066,7 @@ static void mach32_updatemapping(mach_t *mach) { svga_t *svga = &mach->svga; + ibm8514_t *dev = &svga->dev8514; if (mach->pci_bus && (!(mach->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))) { mem_mapping_disable(&svga->mapping); @@ -5118,6 +5116,13 @@ mach32_updatemapping(mach_t *mach) mach->ap_size = 4; mem_mapping_disable(&mach->mmio_linear_mapping); } + if (mach->ext_on && (dev->local >= 2)) { + 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); + } else { + 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); + } } static void @@ -5692,7 +5697,6 @@ mach8_init(const device_t *info) mach->config1 |= 0x0400; svga->clock_gen = device_add(&ati18811_0_device); } - mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); 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->mmio_linear_mapping); } else { diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index f5742e6d0..41aadf6ba 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1739,6 +1739,10 @@ gd54xx_recalctimings(svga_t *svga) svga->interlace = (svga->crtc[0x1a] & 0x01); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->interlace = 0; + } + svga->map8 = svga->pallook; if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) { if (linedbl) @@ -1921,6 +1925,13 @@ gd54xx_recalctimings(svga_t *svga) } svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; + + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) { + svga->render = svga_render_text_40; + } else + svga->render = svga_render_text_80; + } } static void diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index 1e60a3258..c7602ffd0 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -1085,7 +1085,7 @@ im1024_speed_changed(void *priv) const device_t im1024_device = { .name = "ImageManager 1024", .internal_name = "im1024", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA, .local = 0, .init = im1024_init, .close = im1024_close, diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index a98753337..ad197f302 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -341,23 +341,44 @@ paradise_recalctimings(svga_t *svga) } } + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->interlace = 0; + } + if (paradise->type < WD90C30) { - if (svga->bpp >= 8 && !svga->lowres) { + if ((svga->bpp >= 8) && !svga->lowres) { svga->render = svga_render_8bpp_highres; } } else { - if (svga->bpp >= 8 && !svga->lowres) { + if ((svga->bpp >= 8) && !svga->lowres) { if (svga->bpp == 16) { svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; } else if (svga->bpp == 15) { svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; } else { svga->render = svga_render_8bpp_highres; } } } + + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->hdisp == 360) + svga->hdisp <<= 1; + if (svga->seqregs[1] & 8) { + svga->render = svga_render_text_40; + } else + svga->render = svga_render_text_80; + } } static void diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 6a9f2099b..e32575db7 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -830,7 +830,7 @@ svga_poll(void *priv) return; } if (xga_active && xga->on) { - if ((xga->disp_cntl_2 & 7) >= 3) { + if ((xga->disp_cntl_2 & 7) >= 2) { xga_poll(xga, svga); return; } @@ -1247,11 +1247,12 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { if (val == 0xa5) { /*Memory size test of XGA*/ xga->test = val; - xga->a5_test = 1; + if (addr == 0xa0001) + xga->a5_test = 1; + xga->on = 0; vga_on = 1; xga->disp_cntl_2 = 0; - xga->clk_sel_1 = 0; svga_log("XGA test1 addr = %05x.\n", addr); return; } else if (val == 0x5a) { @@ -1259,7 +1260,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) xga->on = 0; vga_on = 1; xga->disp_cntl_2 = 0; - xga->clk_sel_1 = 0; + svga_log("XGA test2 addr = %05x.\n", addr); return; } else if ((addr == 0xa0000) || (addr == 0xa0010)) { addr += xga->write_bank; @@ -1469,6 +1470,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *priv) xga->on = 1; vga_on = 0; } else if ((addr == 0xa0000) && xga->a5_test) { /*This is required by XGAKIT to pass the memory test*/ + svga_log("A5 test bank = %x.\n", addr); addr += xga->read_bank; ret = xga->vram[addr & xga->vram_mask]; } else { @@ -1476,7 +1478,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *priv) xga->on = 1; vga_on = 0; } - svga_log("A5 read: XGA ON = %d, addr = %05x.\n", xga->on, addr); + svga_log("A5 read: XGA ON = %d, addr = %05x, ret = %02x, test1 = %x.\n", xga->on, addr, ret, xga->a5_test); return ret; } else if (xga->test == 0x5a) { ret = xga->test; diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 9204e8644..0f9473d1a 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -1399,6 +1399,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) uint32_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col; uint16_t *vram_w = (uint16_t *) svga->vram; uint32_t *vram_l = (uint32_t *) svga->vram; + uint8_t ger22upper = (tgui->accel.ger22 >> 8); if (tgui->accel.bpp == 0) { trans_col &= 0xff; @@ -1454,6 +1455,16 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } + /*For delayed mode switches.*/ + if (tgui->type == TGUI_9440) { + if (tgui->accel.pitch == 800) + tgui->accel.pitch += 32; + + if (tgui->accel.bpp == 1) { + if (!ger22upper) + tgui->accel.pitch = svga->rowoffset << 2; + } + } #if 0 pclog("TGUI accel command = %x, ger22 = %04x, hdisp = %d, dispend = %d, vtotal = %d, rowoffset = %d, svgabpp = %d, interlace = %d, accelbpp = %d, pitch = %d.\n", tgui->accel.command, tgui->accel.ger22, svga->hdisp, svga->dispend, svga->vtotal, svga->rowoffset, svga->bpp, svga->interlace, tgui->accel.bpp, tgui->accel.pitch); #endif @@ -2066,6 +2077,19 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *priv) case 0x2123: //pclog("Pitch IO23: val = %02x, rowoffset = %x, pitch = %d.\n", val, svga->rowoffset, tgui->accel.pitch); + switch (svga->bpp) { + case 8: + case 24: + tgui->accel.bpp = 0; + break; + case 15: + case 16: + tgui->accel.bpp = 1; + break; + case 32: + tgui->accel.bpp = 3; + break; + } tgui->accel.ger22 = (tgui->accel.ger22 & 0xff) | (val << 8); if ((val & 0x80) || ((val & 0xc0) == 0x40)) tgui->accel.pitch = svga->rowoffset << 3; @@ -2075,15 +2099,14 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *priv) tgui->accel.pitch = 1024; } + if (tgui->accel.pitch == 800) + tgui->accel.pitch += 32; + if (tgui->accel.bpp == 1) tgui->accel.pitch >>= 1; else if (tgui->accel.bpp == 3) tgui->accel.pitch >>= 2; - - if (tgui->accel.pitch == 800) - tgui->accel.pitch += 32; - svga_recalctimings(svga); break; @@ -2722,7 +2745,19 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *priv) break; case 0x23: - //pclog("Pitch MM23: val = %02x, rowoffset = %x, pitch = %d.\n", val, svga->rowoffset, tgui->accel.pitch); + switch (svga->bpp) { + case 8: + case 24: + tgui->accel.bpp = 0; + break; + case 15: + case 16: + tgui->accel.bpp = 1; + break; + case 32: + tgui->accel.bpp = 3; + break; + } tgui->accel.ger22 = (tgui->accel.ger22 & 0xff) | (val << 8); if ((val & 0x80) || ((val & 0xc0) == 0x40)) tgui->accel.pitch = svga->rowoffset << 3; @@ -2732,14 +2767,15 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *priv) tgui->accel.pitch = 1024; } + if (tgui->accel.pitch == 800) + tgui->accel.pitch += 32; + if (tgui->accel.bpp == 1) tgui->accel.pitch >>= 1; else if (tgui->accel.bpp == 3) tgui->accel.pitch >>= 2; - if (tgui->accel.pitch == 800) - tgui->accel.pitch += 32; - + //pclog("Pitch MM23: fullval = %04x, rowoffset = %x, pitch = %d.\n", tgui->accel.ger22, svga->rowoffset, tgui->accel.pitch); svga_recalctimings(svga); break; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 1747bb13c..2c1749402 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -49,6 +49,7 @@ static uint8_t xga_ext_inb(uint16_t addr, void *priv); static void xga_writew(uint32_t addr, uint16_t val, void *priv); static uint16_t xga_readw(uint32_t addr, void *priv); +static void xga_render_4bpp(svga_t *svga); static void xga_render_8bpp(svga_t *svga); static void xga_render_16bpp(svga_t *svga); @@ -376,7 +377,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) case 0x51: xga_log("Reg51 write = %02x.\n", val); xga->disp_cntl_2 = val; - xga->on = ((val & 7) >= 3); + xga->on = ((val & 7) >= 2); vga_on = !xga->on; svga_recalctimings(svga); break; @@ -406,7 +407,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) if ((xga->sprite_pos >= 0) && (xga->sprite_pos <= 16)) { if ((xga->op_mode & 7) >= 5) xga->cursor_data_on = 1; - else if ((xga->sprite_pos >= 1) || ((xga->disp_cntl_2 & 7) == 4)) + else if ((xga->sprite_pos >= 1) || (((xga->disp_cntl_2 & 7) == 2) || (xga->disp_cntl_2 & 7) == 4)) xga->cursor_data_on = 1; else if (xga->aperture_cntl == 0) { if (xga->linear_endian_reverse && !(xga->access_mode & 8)) @@ -888,7 +889,7 @@ xga_ext_inb(uint16_t addr, void *priv) d = MIN(s, d); \ break; \ case 0x12: \ - d = MIN(0xff, s + d); \ + d = MIN(~0, s + d); \ break; \ case 0x13: \ d = MAX(0, d - s); \ @@ -908,7 +909,7 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t b const xga_t *xga = &svga->xga; uint32_t addr = base; int bits; - uint32_t byte; + uint8_t byte; uint8_t px; int skip = 0; @@ -978,6 +979,15 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int } px = (byte >> bits) & 1; return px; + case 2: /*4-bit*/ + addr += (y * (width >> 1)); + addr += (x >> 1); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + return byte; case 3: /*8-bit*/ addr += (y * width); addr += x; @@ -1060,6 +1070,29 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui } mem_writeb_phys(addr, byte); break; + case 2: /*4-bit*/ + addr += (y * (width >> 1)); + addr += (x >> 1); + if (!skip) { + READ(addr, byte); + } else { + byte = mem_readb_phys(addr); + } + if (xga->linear_endian_reverse) { + mask = 0x0f << ((1 - (x & 1)) << 2); + } else { + if ((xga->accel.px_map_format[map] & 8) && !(xga->access_mode & 8)) { + mask = 0x0f << ((x & 1) << 2); + } else { + mask = 0x0f << ((1 - (x & 1)) << 2); + } + } + byte = (byte & ~mask) | (pixel & mask); + if (!skip) { + WRITE(addr, byte); + } + mem_writeb_phys(addr, byte); + break; case 3: /*8-bit*/ addr += (y * width); addr += x; @@ -1076,14 +1109,12 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); else if (xga->access_mode & 8) pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8); - - mem_writew_phys(addr, pixel); } else { if (!skip) { WRITEW(addr, pixel); } - mem_writew_phys(addr, pixel); } + mem_writew_phys(addr, pixel); break; default: @@ -1257,7 +1288,7 @@ xga_line_draw_write(svga_t *svga) err = (xga->accel.bres_err_term); if (xga->accel.bres_err_term & 0x2000) - destxtmp |= ~0x1fff; + err |= ~0x1fff; if (xga->accel.octant & 0x02) { ydir = -1; @@ -1279,6 +1310,9 @@ xga_line_draw_write(svga_t *svga) if (xga->accel.dst_map_y >= 0x1800) dy |= ~0x17ff; + if ((xga->accel.command & 0x30) == 0x30) + xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err); + if (xga->accel.octant & 0x01) { steep = 0; SWAP(dx, dy); @@ -1287,6 +1321,7 @@ xga_line_draw_write(svga_t *svga) if (xga->accel.pat_src == 8) { while (y >= 0) { + draw_pixel = 1; if (xga->accel.command & 0xc0) { if (steep) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { @@ -1303,6 +1338,21 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (err < 0) + draw_pixel = 0; + else { + if (ydir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } } } } else { @@ -1320,6 +1370,17 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (xdir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } } } } @@ -1338,6 +1399,21 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (err < 0) + draw_pixel = 0; + else { + if (ydir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } } } else { src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; @@ -1353,6 +1429,17 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + else if ((xga->accel.command & 0x30) == 0x30) { + if (xdir == -1) { /*Bottom-to-Top*/ + if (!x) + draw_pixel = 0; + } else { /*Top-to-Bottom*/ + if (!y) + draw_pixel = 0; + } + if (draw_pixel) + xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } } } } @@ -1361,7 +1448,7 @@ xga_line_draw_write(svga_t *svga) break; } - while (err > 0) { + while (err >= 0) { dy += ydir; err -= (dmajor << 1); } @@ -1383,10 +1470,13 @@ xga_line_draw_write(svga_t *svga) } } +#undef SWAP + static void xga_bitblt(svga_t *svga) { xga_t *xga = &svga->xga; + uint8_t area_state = 0; uint32_t src_dat; uint32_t dest_dat; uint32_t old_dest_dat; @@ -1405,9 +1495,12 @@ xga_bitblt(svga_t *svga) #endif uint32_t frgdcol = xga->accel.frgd_color; uint32_t bkgdcol = xga->accel.bkgd_color; - int mix = 0; + int mix = 0; int xdir; int ydir; + int skip = 0; + int x = 0; + int y = 0; if (xga->accel.octant & 0x02) { ydir = -1; @@ -1556,17 +1649,105 @@ xga_bitblt(svga_t *svga) xga_log("Pattern Map = %d: CMD = %08x: PATBase = %08x, SRCBase = %08x, DSTBase = %08x\n", xga->accel.pat_src, xga->accel.command, patbase, srcbase, dstbase); xga_log("CMD = %08x: Y = %d, X = %d, patsrc = %02x, srcmap = %d, dstmap = %d, py = %d, " - "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d\n", + "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d, bkgdcol = %02x\n", xga->accel.command, xga->accel.y, xga->accel.x, xga->accel.pat_src, xga->accel.src_map, xga->accel.dst_map, xga->accel.py, xga->accel.sy, xga->accel.dy, xga->accel.px_map_width[0], xga->accel.px_map_width[1], - xga->accel.px_map_width[2], xga->accel.px_map_width[3]); + xga->accel.px_map_width[2], xga->accel.px_map_width[3], bkgdcol); - while (xga->accel.y >= 0) { - mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); + if (((xga->accel.command >> 24) & 0x0f) == 0x0a) { + while (xga->accel.y >= 0) { + mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); + if (mix) + area_state ^= 1; - if (xga->accel.command & 0xc0) { - if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + if (xga->accel.command & 0xc0) { + if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + if (area_state) + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + else + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) + src_dat &= 0xff; + + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(area_state, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_log("1SRCDat=%02x, DSTDat=%02x, Old=%02x, MIX=%d.\n", src_dat, dest_dat, old_dest_dat, area_state); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + } else { + if (area_state) + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + else + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + + if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) + src_dat &= 0xff; + + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(area_state, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_log("2Fill: NumXY(%d,%d): DXY(%d,%d): SRCDat=%02x, DSTDat=%02x, Old=%02x, frgdcol=%02x, bkgdcol=%02x, MIX=%d, frgdmix=%02x, bkgdmix=%02x, dstmapfmt=%02x, srcmapfmt=%02x, srcmapnum=%d.\n", x, y, xga->accel.dx, xga->accel.dy, src_dat, dest_dat, old_dest_dat, frgdcol, bkgdcol, area_state, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.src_map); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + + xga->accel.sx = ((xga->accel.sx + 1) & srcwidth) | (xga->accel.sx & ~srcwidth); + xga->accel.px = ((xga->accel.px + 1) & patwidth) | (xga->accel.px & ~patwidth); + xga->accel.dx++; + xga->accel.x--; + x++; + if (xga->accel.x < 0) { + area_state = 0; + x = 0; + xga->accel.y--; + xga->accel.x = xga->accel.blt_width & 0xfff; + + xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + xga->accel.dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; + xga->accel.px = xga->accel.pat_map_x & 0xfff; + + xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); + xga->accel.py += ydir; + xga->accel.dy += ydir; + y++; + + if (xga->accel.y < 0) { + xga->accel.dst_map_x = xga->accel.dx; + xga->accel.dst_map_y = xga->accel.dy; + return; + } + } + } + } else { + while (xga->accel.y >= 0) { + mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); + + if (xga->accel.command & 0xc0) { + if ((xga->accel.dx >= xga->accel.mask_map_origin_x_off) && (xga->accel.dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (xga->accel.dy >= xga->accel.mask_map_origin_y_off) && (xga->accel.dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + if (mix) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + } else { + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; + } + dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(mix, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } + } + } else { if (mix) { src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; } else { @@ -1580,49 +1761,36 @@ xga_bitblt(svga_t *svga) xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); } } - } else { - if (mix) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - } else { - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - } - dest_dat = xga_accel_read_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(mix, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_accel_write_map_pixel(svga, xga->accel.dx, xga->accel.dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); - } - } - xga->accel.sx += xdir; - if (xga->accel.pattern) - xga->accel.px = ((xga->accel.px + xdir) & patwidth) | (xga->accel.px & ~patwidth); - else - xga->accel.px += xdir; - xga->accel.dx += xdir; - xga->accel.x--; - if (xga->accel.x < 0) { - xga->accel.y--; - xga->accel.x = (xga->accel.blt_width & 0xfff); - - xga->accel.dx = xga->accel.dst_map_x & 0x1fff; - if (xga->accel.dst_map_x >= 0x1800) - xga->accel.dx |= ~0x17ff; - xga->accel.sx = xga->accel.src_map_x & 0xfff; - xga->accel.px = xga->accel.pat_map_x & 0xfff; - - xga->accel.sy += ydir; + xga->accel.sx += xdir; if (xga->accel.pattern) - xga->accel.py = ((xga->accel.py + ydir) & patheight) | (xga->accel.py & ~patheight); + xga->accel.px = ((xga->accel.px + xdir) & patwidth) | (xga->accel.px & ~patwidth); else - xga->accel.py += ydir; - xga->accel.dy += ydir; + xga->accel.px += xdir; + xga->accel.dx += xdir; + xga->accel.x--; + if (xga->accel.x < 0) { + xga->accel.y--; + xga->accel.x = (xga->accel.blt_width & 0xfff); - if (xga->accel.y < 0) { - xga->accel.dst_map_x = xga->accel.dx; - xga->accel.dst_map_y = xga->accel.dy; - return; + xga->accel.dx = xga->accel.dst_map_x & 0x1fff; + if (xga->accel.dst_map_x >= 0x1800) + xga->accel.dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; + xga->accel.px = xga->accel.pat_map_x & 0xfff; + + xga->accel.sy += ydir; + if (xga->accel.pattern) + xga->accel.py = ((xga->accel.py + ydir) & patheight) | (xga->accel.py & ~patheight); + else + xga->accel.py += ydir; + xga->accel.dy += ydir; + + if (xga->accel.y < 0) { + xga->accel.dst_map_x = xga->accel.dx; + xga->accel.dst_map_y = xga->accel.dy; + return; + } } } } @@ -2054,24 +2222,29 @@ exec_command: #endif switch ((xga->accel.command >> 24) & 0x0f) { + case 2: /*Short Stroke Vectors Read */ + xga_log("Short Stroke Vectors Read.\n"); + break; case 3: /*Bresenham Line Draw Read*/ xga_log("Line Draw Read\n"); break; - case 4: /*Short Stroke Vectors*/ - xga_log("Short Stroke Vectors.\n"); + case 4: /*Short Stroke Vectors Write*/ + xga_log("Short Stroke Vectors Write.\n"); break; case 5: /*Bresenham Line Draw Write*/ xga_log("Line Draw Write.\n"); xga_line_draw_write(svga); break; case 8: /*BitBLT*/ + xga_log("BitBLT.\n"); xga_bitblt(svga); break; case 9: /*Inverting BitBLT*/ xga_log("Inverting BitBLT\n"); break; case 0x0a: /*Area Fill*/ - xga_log("Area Fill.\n"); + xga_log("Area Fill BitBLT.\n"); + xga_bitblt(svga); break; default: @@ -2355,6 +2528,47 @@ xga_render_overscan_right(xga_t *xga, svga_t *svga) *line_ptr++ = svga->overscan_color; } +static void +xga_render_4bpp(svga_t *svga) +{ + xga_t *xga = &svga->xga; + uint32_t *p; + uint32_t dat; + + if ((xga->displine + svga->y_add) < 0) + return; + + if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + + if (xga->firstline_draw == 2000) + xga->firstline_draw = xga->displine; + xga->lastline_draw = xga->displine; + + for (int x = 0; x <= xga->h_disp; x += 16) { + dat = *(uint32_t *) (&xga->vram[xga->ma & xga->vram_mask]); + p[0] = xga->pallook[(dat >> 4) & 0x0f]; + p[1] = xga->pallook[dat & 0x0f]; + p[2] = xga->pallook[(dat >> 12) & 0x0f]; + p[3] = xga->pallook[(dat >> 8) & 0x0f]; + p[4] = xga->pallook[(dat >> 20) & 0x0f]; + p[5] = xga->pallook[(dat >> 16) & 0x0f]; + p[6] = xga->pallook[(dat >> 28) & 0x0f]; + p[7] = xga->pallook[(dat >> 24) & 0x0f]; + + dat = *(uint32_t *) (&xga->vram[(xga->ma + 4) & xga->vram_mask]); + p[9] = xga->pallook[dat & 0x0f]; + p[11] = xga->pallook[(dat >> 8) & 0x0f]; + p[13] = xga->pallook[(dat >> 16) & 0x0f]; + p[15] = xga->pallook[(dat >> 24) & 0x0f]; + + xga->ma += 8; + p += 16; + } + xga->ma &= xga->vram_mask; + } +} + static void xga_render_8bpp(svga_t *svga) { @@ -2449,7 +2663,7 @@ xga_write(uint32_t addr, uint8_t val, void *priv) if (addr >= xga->vram_size) return; - cycles -= video_timing_write_b; + cycles -= svga->monitor->mon_video_timing_write_b; if (xga->access_mode & 8) { if ((xga->access_mode & 7) == 4) @@ -2510,7 +2724,7 @@ xga_read(uint32_t addr, void *priv) if (addr >= xga->vram_size) return ret; - cycles -= video_timing_read_b; + cycles -= svga->monitor->mon_video_timing_read_b; if (xga->access_mode & 8) { if ((xga->access_mode & 7) == 4) @@ -2695,6 +2909,9 @@ xga_do_render(svga_t *svga) xga_log("DISPCNTL = %d, vga = %d.\n", xga->disp_cntl_2 & 7, vga_on); switch (xga->disp_cntl_2 & 7) { + case 2: + xga_render_4bpp(svga); + break; case 3: xga_render_8bpp(svga); break; @@ -2773,15 +2990,9 @@ xga_poll(xga_t *xga, svga_t *svga) if (xga->sc == xga->rowcount) { xga->sc = 0; - if ((xga->disp_cntl_2 & 7) == 4) { - xga->maback += (xga->rowoffset << 4); - if (xga->interlace) - xga->maback += (xga->rowoffset << 4); - } else { - xga->maback += (xga->rowoffset << 3); - if (xga->interlace) - xga->maback += (xga->rowoffset << 3); - } + xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + if (xga->interlace) + xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); xga->maback &= xga->vram_mask; xga->ma = xga->maback; } else {