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 {