From 8c705b4ad191d7b837cd68ad1664ae7b5a423a8d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 04:32:46 +0200 Subject: [PATCH 01/27] Flush on writes to hard disk images, fixes partition creation on the Samsung SPC7700LP-W. --- src/disk/hdd_image.c | 3 +++ src/disk/minivhd/minivhd_io.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index f82b2d3f2..7c2618969 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -577,6 +577,7 @@ hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) } num_write = fwrite(buffer, 512, count, hdd_images[id].file); + fflush(hdd_images[id].file); hdd_images[id].pos = sector + num_write; } } @@ -618,6 +619,8 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) hdd_images[id].pos = sector + i; fwrite(empty_sector, 512, 1, hdd_images[id].file); } + + fflush(hdd_images[id].file); } } diff --git a/src/disk/minivhd/minivhd_io.c b/src/disk/minivhd/minivhd_io.c index ffc6aba44..1a349dbc4 100644 --- a/src/disk/minivhd/minivhd_io.c +++ b/src/disk/minivhd/minivhd_io.c @@ -89,6 +89,8 @@ mvhd_write_empty_sectors(FILE *f, int sector_count) for (int i = 0; i < sector_count; i++) fwrite(zero_bytes, sizeof zero_bytes, 1, f); + + fflush(f); } /** @@ -141,6 +143,7 @@ write_bat_entry(MVHDMeta *vhdm, int blk) mvhd_fseeko64(vhdm->f, table_offset, SEEK_SET); fwrite(&offset, sizeof offset, 1, vhdm->f); + fflush(vhdm->f); } /** @@ -197,6 +200,8 @@ create_block(MVHDMeta *vhdm, int blk) /* We no longer have a sparse block. Update that BAT! */ vhdm->block_offset[blk] = sect_offset; write_bat_entry(vhdm, blk); + + fflush(vhdm->f); } int @@ -317,6 +322,7 @@ mvhd_fixed_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *in_buff addr = (int64_t)offset * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); fwrite(in_buff, transfer_sectors * MVHD_SECTOR_SIZE, 1, vhdm->f); + fflush(vhdm->f); return truncated_sectors; } @@ -376,6 +382,8 @@ mvhd_sparse_diff_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *i /* And write the sector bitmap for the last block we visited to disk */ write_curr_sect_bitmap(vhdm); + fflush(vhdm->f); + return truncated_sectors; } From 7639d8b031a4d3c09d7674e5f6aef2077d664eba Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 04:36:01 +0200 Subject: [PATCH 02/27] Flush on write to floppy images as well. --- src/floppy/fdd_86f.c | 2 ++ src/floppy/fdd_imd.c | 2 ++ src/floppy/fdd_img.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 5a5eec398..3fe1428a1 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -3225,6 +3225,8 @@ d86f_writeback(int drive) free(dev->filebuf); } #endif + + fflush(dev->fp); } void diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index fd6c59d01..0839c2900 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -549,6 +549,8 @@ imd_writeback(int drive) } } } + + fflush(dev->fp); } static uint8_t diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 404cbf9fa..62b05a944 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -431,6 +431,8 @@ write_back(int drive) if (fwrite(dev->track_data[side], 1, size, dev->fp) != size) fatal("IMG write_back(): Error writing data\n"); } + + fflush(dev->fp); } static uint16_t From 9c1d9e2d82ca93dec5487bf85eaa615ad36eb161 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 04:37:26 +0200 Subject: [PATCH 03/27] MO and ZIP. --- src/disk/mo.c | 4 ++++ src/disk/zip.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/disk/mo.c b/src/disk/mo.c index 44f68effa..ed1ab2472 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -951,6 +951,8 @@ mo_blocks(mo_t *dev, int32_t *len, UNUSED(int first_batch), int out) if (out) { if (fwrite(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) fatal("mo_blocks(): Error writing data\n"); + + fflush(dev->drv->fp); } else { if (fread(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) fatal("mo_blocks(): Error reading data\n"); @@ -1069,6 +1071,8 @@ mo_erase(mo_t *dev) fwrite(dev->buffer, 1, dev->drv->sector_size, dev->drv->fp); } + fflush(dev->drv->fp); + mo_log("MO %i: Erased %i bytes of blocks...\n", dev->id, i * dev->drv->sector_size); dev->sector_pos += i; diff --git a/src/disk/zip.c b/src/disk/zip.c index 764dc1f53..a948cab2f 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1134,6 +1134,8 @@ zip_blocks(zip_t *dev, int32_t *len, UNUSED(int first_batch), int out) if (out) { if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) fatal("zip_blocks(): Error writing data\n"); + + fflush(dev->drv->fp); } else { if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) fatal("zip_blocks(): Error reading data\n"); @@ -2125,6 +2127,8 @@ zip_phase_data_out(scsi_common_t *sc) if (fwrite(dev->buffer, 1, 512, dev->drv->fp) != 512) fatal("zip_phase_data_out(): Error writing data\n"); } + + fflush(dev->drv->fp); break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: From 17f6ddecb319ae2ea1a4de0e333001b3cce7560b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 04:41:45 +0200 Subject: [PATCH 04/27] More UM888x fixes. --- src/chipset/umc_8886.c | 48 ++++++++++------------ src/chipset/umc_hb4.c | 93 +++++++++++++++++++++++++++++++++++------- 2 files changed, 100 insertions(+), 41 deletions(-) diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index 3ec6885b6..4242062c6 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -126,10 +126,10 @@ umc_8886_ide_handler(umc_8886_t *dev) ide_sec_disable(); if (dev->pci_conf_sb[1][0x04] & 0x01) { - if (dev->pci_conf_sb[1][0x40] & 0x80) + if (dev->pci_conf_sb[1][0x41] & 0x80) ide_pri_enable(); - if (dev->pci_conf_sb[1][0x40] & 0x40) + if (dev->pci_conf_sb[1][0x41] & 0x40) ide_sec_enable(); } } @@ -204,7 +204,7 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) case 0x50 ... 0x55: case 0x57: case 0x70 ... 0x76: - case 0x80 ... 0x82: + case 0x80 ... 0x83: case 0x90 ... 0x92: case 0xa0 ... 0xa1: case 0xa5 ... 0xa8: @@ -270,13 +270,13 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) break; case 0x3c: - case 0x41 ... 0x4b: - case 0x54 ... 0x59: + case 0x40: + case 0x42 ... 0x59: if (dev->ide_id == 0x673a) dev->pci_conf_sb[func][addr] = val; break; - case 0x40: + case 0x41: if (dev->ide_id == 0x673a) { dev->pci_conf_sb[func][addr] = val; umc_8886_ide_handler(dev); @@ -322,25 +322,17 @@ umc_8886_reset(void *priv) dev->pci_conf_sb[0][0x09] = 0x00; dev->pci_conf_sb[0][0x0a] = 0x01; dev->pci_conf_sb[0][0x0b] = 0x06; + dev->pci_conf_sb[0][0x40] = 0x01; - dev->pci_conf_sb[0][0x41] = 0x06; + dev->pci_conf_sb[0][0x41] = 0x04; dev->pci_conf_sb[0][0x42] = 0x08; - dev->pci_conf_sb[0][0x43] = 0x00; - dev->pci_conf_sb[0][0x44] = 0x00; - dev->pci_conf_sb[0][0x45] = 0x04; - dev->pci_conf_sb[0][0x46] = 0x00; - dev->pci_conf_sb[0][0x47] = 0x40; - dev->pci_conf_sb[0][0x50] = 0x01; - dev->pci_conf_sb[0][0x51] = 0x03; - dev->pci_conf_sb[0][0x56] = dev->pci_conf_sb[0][0x57] = 0x00; - dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00; - dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00; - dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x76] = 0x00; - dev->pci_conf_sb[0][0x82] = 0x00; - dev->pci_conf_sb[0][0x90] = dev->pci_conf_sb[0][0x91] = 0x00; - dev->pci_conf_sb[0][0xa0] = dev->pci_conf_sb[0][0xa2] = 0x00; - dev->pci_conf_sb[0][0xa4] = 0x00; - dev->pci_conf_sb[0][0xa8] = 0x20; + dev->pci_conf_sb[0][0x43] = 0x9a; + dev->pci_conf_sb[0][0x44] = 0xbc; + dev->pci_conf_sb[0][0x45] = 0x00; + dev->pci_conf_sb[0][0x46] = 0x10; + dev->pci_conf_sb[0][0x47] = 0x30; + + dev->pci_conf_sb[0][0x51] = 0x02; if (dev->has_ide) { dev->pci_conf_sb[1][0x00] = 0x60; /* UMC */ @@ -363,13 +355,15 @@ umc_8886_reset(void *priv) dev->pci_conf_sb[1][0x21] = 0x10; if (dev->ide_id == 0x673a) { - dev->pci_conf_sb[1][0x40] = 0xc0; - dev->pci_conf_sb[1][0x41] = 0x00; + dev->pci_conf_sb[1][0x40] = 0x00; + dev->pci_conf_sb[1][0x41] = 0xc0; dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00; dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00; dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00; - dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00; - dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x00; + dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x55; + dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x55; + dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x88; + dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0xaa; dev->pci_conf_sb[1][0x54] = dev->pci_conf_sb[1][0x55] = 0x00; dev->pci_conf_sb[1][0x56] = dev->pci_conf_sb[1][0x57] = 0x00; dev->pci_conf_sb[1][0x58] = dev->pci_conf_sb[1][0x59] = 0x00; diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index a7ed0b880..707bbdd45 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -136,6 +136,9 @@ hb4_log(const char *fmt, ...) #endif typedef struct hb4_t { + uint8_t idx; + uint8_t access_data; + uint8_t pci_slot; uint8_t pci_conf[256]; /* PCI Registers */ @@ -176,7 +179,10 @@ hb4_shadow_bios_low(hb4_t *dev) int state; /* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */ - state = shadow_bios[dev->pci_conf[0x55] >> 6]; + // state = shadow_bios[dev->pci_conf[0x55] >> 6]; + state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[dev->pci_conf[0x54] & 0x01] : + MEM_READ_EXTANY; + state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[7]) { mem_set_mem_state_both(0xe0000, 0x10000, state); @@ -194,8 +200,9 @@ hb4_shadow_main(hb4_t *dev) int n = 0; for (uint8_t i = 0; i < 6; i++) { - state = shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] | - shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] : + MEM_READ_EXTANY; + state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[i + 1]) { n++; @@ -212,8 +219,9 @@ hb4_shadow_video(hb4_t *dev) { int state; - state = shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] | - shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] : + MEM_READ_EXTANY; + state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[0]) { mem_set_mem_state_both(0xc0000, 0x8000, state); @@ -302,7 +310,7 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) hb4_shadow(dev); break; - case 0x56 ... 0x5b: + case 0x56 ... 0x5a: case 0x5e ... 0x5f: dev->pci_conf[addr] = val; break; @@ -313,10 +321,14 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) hb4_smram(dev); break; - case 0x61 ... 0x62: + case 0x61: dev->pci_conf[addr] = val; break; + case 0x62: + dev->pci_conf[addr] = val & 0x03; + break; + default: break; } @@ -354,14 +366,16 @@ hb4_reset(void *priv) dev->pci_conf[0x52] = 0x01; dev->pci_conf[0x53] = 0x00; dev->pci_conf[0x54] = 0x00; - dev->pci_conf[0x55] = 0x00; - dev->pci_conf[0x56] = 0x00; - dev->pci_conf[0x57] = 0x00; - dev->pci_conf[0x58] = 0x00; - dev->pci_conf[0x59] = 0x00; - dev->pci_conf[0x5a] = 0x04; + dev->pci_conf[0x55] = 0x40; + dev->pci_conf[0x56] = 0xff; + dev->pci_conf[0x57] = 0x0f; + dev->pci_conf[0x58] = 0xff; + dev->pci_conf[0x59] = 0x0f; + dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5b] = 0x2c; dev->pci_conf[0x5c] = 0x00; - dev->pci_conf[0x5d] = 0x20; + dev->pci_conf[0x5d] = 0x0f; + dev->pci_conf[0x5e] = 0x00; dev->pci_conf[0x5f] = 0xff; dev->pci_conf[0x60] = 0x00; dev->pci_conf[0x61] = 0x00; @@ -385,6 +399,55 @@ hb4_close(void *priv) free(dev); } +static void +ims8848_write(uint16_t addr, uint8_t val, void *priv) +{ + hb4_t *dev = (hb4_t *) priv; + + switch (addr) { + case 0x22: + dev->idx = val; + break; + case 0x23: + if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) + dev->access_data = 1; + break; + case 0x24: + if (dev->access_data) + dev->access_data = 0; + break; + + default: + break; + } +} + +static uint8_t +ims8848_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + hb4_t *dev = (hb4_t *) priv; + + switch (addr) { + case 0x22: + ret = dev->idx; + break; + case 0x23: + ret = (dev->idx >> 4) | (dev->idx << 4); + break; + case 0x24: + if (dev->access_data) { + ret = dev->pci_conf[dev->idx]; + dev->access_data = 0; + } + break; + default: + break; + } + + return ret; +} + static void * hb4_init(UNUSED(const device_t *info)) { @@ -402,6 +465,8 @@ hb4_init(UNUSED(const device_t *info)) dev->smram_base = 0x000a0000; hb4_reset(dev); + io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); + return dev; } From 24c6ebc6dd6df5b3c7e7d189f7ea714eeede7b31 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 04:50:41 +0200 Subject: [PATCH 05/27] Samsung SPC7700P-LW: reset SMBASE on soft reset via the keyboard controller, fixes segmentation fault on soft reset after FDISK. --- src/device/kbc_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index ad63099fb..5c3c9ac6e 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -821,7 +821,7 @@ write_p2(atkbc_t *dev, uint8_t val) softresetx86(); /* Pulse reset! */ cpu_set_edx(); flushmmucache(); - if (kbc_ven == KBC_VEN_ALI) + if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw")) smbase = 0x00030000; /* Yes, this is a hack, but until someone gets ahold of the real PCD-2L From 83d4997e5cd0c85b6ac98926b0a02b08ad577ad9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 04:53:10 +0200 Subject: [PATCH 06/27] UMC 8881: Remove an excess commented out line. --- src/chipset/umc_hb4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index 707bbdd45..c1f359f26 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -179,7 +179,6 @@ hb4_shadow_bios_low(hb4_t *dev) int state; /* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */ - // state = shadow_bios[dev->pci_conf[0x55] >> 6]; state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[dev->pci_conf[0x54] & 0x01] : MEM_READ_EXTANY; state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; From 13e18a067adfc0237d45ea1dc1e988fe4db67b2d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Sep 2024 08:39:13 +0200 Subject: [PATCH 07/27] SN76489: Remove some wrong code, fixes #4821. --- src/sound/snd_sn76489.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 5ccc0cd10..32f81c596 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -189,12 +189,6 @@ void sn74689_set_extra_divide(sn76489_t *sn76489, int enable) { sn76489->extra_divide = enable; - - if (!enable) { - for (uint8_t c = 1; c < 4; c++) - sn76489->latch[c] &= ~(0x400 << 6); - sn76489->latch[0] &= ~(0x400 << 6); - } } void From 5fd1d0be9fe21c56bcf3d32ff7895965be1dd96c Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 24 Sep 2024 20:39:20 +0200 Subject: [PATCH 08/27] XGA aperture fixes of the day (September 24th, 2024) Fixed 1MB aperture vram access. --- src/video/vid_xga.c | 64 ++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 824a3dbf0..8946d7122 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -168,12 +168,14 @@ xga_updatemapping(svga_t *svga) xga_log("XGA: Extended Graphics mode.\n"); switch (xga->aperture_cntl) { case 0: - xga_log("XGA: No 64KB aperture.\n"); - if (xga->base_addr_1mb) + xga_log("XGA: No 64KB aperture: 1MB=%x, 4MB=%x.\n", xga->base_addr_1mb, xga->linear_base); + if (xga->base_addr_1mb) { mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); - else if (xga->linear_base) + mem_mapping_enable(&xga->linear_mapping); + } else if (xga->linear_base) { mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); - else + mem_mapping_enable(&xga->linear_mapping); + } else mem_mapping_disable(&xga->linear_mapping); mem_mapping_disable(&xga->video_mapping); @@ -912,13 +914,8 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t b uint8_t px; int skip = 0; - if (xga->base_addr_1mb) { - if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) - skip = 1; - } else { - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) - skip = 1; - } + if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + skip = 1; addr += (y * (width >> 3)); addr += (x >> 3); @@ -956,13 +953,8 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int uint8_t px; int skip = 0; - if (xga->base_addr_1mb) { - if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) - skip = 1; - } else { - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) - skip = 1; - } + if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + skip = 1; switch (xga->accel.px_map_format[map] & 7) { case 0: /*1-bit*/ @@ -1033,13 +1025,8 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui uint8_t mask; int skip = 0; - if (xga->base_addr_1mb) { - if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) - skip = 1; - } else { - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) - skip = 1; - } + if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + skip = 1; switch (xga->accel.px_map_format[map] & 7) { case 0: /*1-bit*/ @@ -1476,7 +1463,8 @@ xga_bitblt(svga_t *svga) if (xga->accel.dst_map_x >= 0x1800) dx |= ~0x17ff; if (xga->accel.dst_map_y >= 0x1800) - dy |= ~0x17ff; + dy -= 0x1800; + xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth); xga->accel.pattern = 0; @@ -2776,8 +2764,10 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv) addr &= svga->decode_mask; - if (addr >= xga->vram_size) + if (addr >= xga->vram_size) { + xga_log("Write Linear Over!.\n"); return; + } cycles -= svga->monitor->mon_video_timing_write_b; @@ -2839,8 +2829,10 @@ xga_read_linear(uint32_t addr, void *priv) addr &= svga->decode_mask; - if (addr >= xga->vram_size) + if (addr >= xga->vram_size) { + xga_log("Read Linear Over!.\n"); return ret; + } cycles -= svga->monitor->mon_video_timing_read_b; @@ -3369,9 +3361,9 @@ xga_init(const device_t *info) free(rom); } - xga->base_addr_1mb = 0; if (info->flags & DEVICE_MCA) { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_mca); + xga->base_addr_1mb = 0; xga->linear_base = 0; xga->instance = 0; xga->rom_addr = 0; @@ -3384,7 +3376,19 @@ xga_init(const device_t *info) xga->pos_regs[2] = 1 | (xga->instance_isa << 1) | xga->ext_mem_addr; xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; - xga->pos_regs[4] = 1 | 2; + xga->pos_regs[4] = 2; + if (mem_size >= 16384) { + xga->pos_regs[4] |= 1; + xga->pos_regs[5] = 0; + } else { + xga->pos_regs[5] = ((mem_size * 64) >> 0x10) + 1; + if (xga->pos_regs[5] == 0x10) { + xga->pos_regs[5] = 0; + xga->pos_regs[4] |= 1; + } + } + + xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); } From 6d84c4d33c7bb95cffca81a7f3e66fc5f8c8ef60 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 25 Sep 2024 07:57:02 +0200 Subject: [PATCH 09/27] FIC VA-503+: The Winbond W83877TF Super I/O chip needs to have bit 0 of HEFRAS set at power on, fixes #4855. --- src/machine/m_at_sockets7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index fe6983733..0360b5650 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -263,7 +263,7 @@ machine_at_mvp3_init(const machine_t *model) device_add(&via_mvp3_device); device_add(&via_vt82c586b_device); device_add(&keyboard_ps2_pci_device); - device_add(&w83877tf_device); + device_add(&w83877tf_acorp_device); device_add(&sst_flash_39sf010_device); spd_register(SPD_TYPE_SDRAM, 0x3, 256); From 26b7053318ad6d3f37459eac29e33753ffbe029c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 25 Sep 2024 08:58:40 +0200 Subject: [PATCH 10/27] CGA and Tandy 1000 SX/HX: Implement light pen latch readout with a sane value, fixes #4856. --- src/machine/m_tandy.c | 18 +++++++++++++++++- src/video/vid_cga.c | 12 +++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 6c478b37a..bc20a4510 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -864,7 +864,23 @@ vid_in(uint16_t addr, void *priv) break; case 0x03d5: - ret = vid->crtc[vid->crtcreg]; + switch (vid->crtcreg) { + default: + ret = vid->crtc[vid->crtcreg]; + break; + case 0x10: + if (dev->is_sl2) + ret = vid->crtc[vid->crtcreg]; + else + ret = 0x0f; + break; + case 0x11: + if (dev->is_sl2) + ret = vid->crtc[vid->crtcreg]; + else + ret = 0x78; + break; + } break; case 0x03da: diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 2ea07c346..b5590c2c0 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -131,7 +131,17 @@ cga_in(uint16_t addr, void *priv) ret = cga->crtcreg; break; case 0x3D5: - ret = cga->crtc[cga->crtcreg]; + switch (cga->crtcreg) { + default: + ret = cga->crtc[cga->crtcreg]; + break; + case 0x10: + ret = 0x0f; + break; + case 0x11: + ret = 0x78; + break; + } break; case 0x3DA: ret = cga->cgastat; From 32ed6a30d42fe5663750ad496a172547d00a65f9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 25 Sep 2024 11:11:52 +0200 Subject: [PATCH 11/27] Fixed the AdLib Gold regression that were causing noise. --- src/sound/snd_adlibgold.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 488dcb8a6..8f62d0417 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -791,8 +791,8 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv) adgold_update(adgold); for (c = 0; c < len * 2; c += 2) { - adgold_buffer[c] += ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4; - adgold_buffer[c + 1] += ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4; + adgold_buffer[c] = ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4; + adgold_buffer[c + 1] = ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4; } if (adgold->surround_enabled) @@ -904,7 +904,6 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv) int c; const int32_t *opl_buf = adgold->opl.update(adgold->opl.priv); - adgold_update(adgold); for (c = 0; c < len * 2; c += 2) { adgold_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2; From d6a01a102b6dfc5ca91542e88120b30101145db3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 25 Sep 2024 14:13:00 +0200 Subject: [PATCH 12/27] CGA and Tandy 1000 HX/SX: Properly implement the light pen strobe. Jungle Hunt's palette changed area still moves, that's a PIT bug, I'm going to look into that again in 5.0 when I go back to porting 808x etc. from MartyPC. --- src/include/86box/vid_cga.h | 2 ++ src/machine/m_tandy.c | 54 ++++++++++++++++++++++++------------- src/video/vid_cga.c | 48 +++++++++++++++++++++++---------- 3 files changed, 72 insertions(+), 32 deletions(-) diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 5b6a2dea2..a503d12ba 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -31,6 +31,8 @@ typedef struct cga_t { uint8_t cgamode; uint8_t cgacol; + uint8_t lp_strobe; + int fontbase; int linepos; int displine; diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index bc20a4510..2fdc491f9 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -84,6 +84,7 @@ typedef struct t1kvid_t { uint32_t b8000_mask; uint32_t b8000_limit; uint8_t planar_ctrl; + uint8_t lp_strobe; int linepos; int displine; @@ -770,6 +771,15 @@ recalc_address_sl(tandy_t *dev) } } +static void +vid_update_latch(t1kvid_t *vid) +{ + uint32_t lp_latch = vid->displine * vid->crtc[1]; + + vid->crtc[0x10] = (lp_latch >> 8) & 0x3f; + vid->crtc[0x11] = lp_latch & 0xff; +} + static void vid_out(uint16_t addr, uint8_t val, void *priv) { @@ -816,6 +826,18 @@ vid_out(uint16_t addr, uint8_t val, void *priv) vid->array_index = val & 0x1f; break; + case 0x3db: + if (dev->is_sl2 && (vid->lp_strobe == 1)) + vid->lp_strobe = 0; + break; + + case 0x3dc: + if (dev->is_sl2 && (vid->lp_strobe == 0)) { + vid->lp_strobe = 1; + vid_update_latch(vid); + } + break; + case 0x03de: if (vid->array_index & 16) val &= 0xf; @@ -852,7 +874,7 @@ static uint8_t vid_in(uint16_t addr, void *priv) { const tandy_t *dev = (tandy_t *) priv; - const t1kvid_t *vid = dev->vid; + t1kvid_t *vid = dev->vid; uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) @@ -864,29 +886,25 @@ vid_in(uint16_t addr, void *priv) break; case 0x03d5: - switch (vid->crtcreg) { - default: - ret = vid->crtc[vid->crtcreg]; - break; - case 0x10: - if (dev->is_sl2) - ret = vid->crtc[vid->crtcreg]; - else - ret = 0x0f; - break; - case 0x11: - if (dev->is_sl2) - ret = vid->crtc[vid->crtcreg]; - else - ret = 0x78; - break; - } + ret = vid->crtc[vid->crtcreg]; break; case 0x03da: ret = vid->stat; break; + case 0x3db: + if (dev->is_sl2 && (vid->lp_strobe == 1)) + vid->lp_strobe = 0; + break; + + case 0x3dc: + if (dev->is_sl2 && (vid->lp_strobe == 0)) { + vid->lp_strobe = 1; + vid_update_latch(vid); + } + break; + default: break; } diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index b5590c2c0..c58c319df 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -70,6 +70,15 @@ static video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w void cga_recalctimings(cga_t *cga); +static void +cga_update_latch(cga_t *cga) +{ + uint32_t lp_latch = cga->displine * cga->crtc[1]; + + cga->crtc[0x10] = (lp_latch >> 8) & 0x3f; + cga->crtc[0x11] = lp_latch & 0xff; +} + void cga_out(uint16_t addr, uint8_t val, void *priv) { @@ -87,7 +96,7 @@ cga_out(uint16_t addr, uint8_t val, void *priv) old = cga->crtc[cga->crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; if (old != val) { - if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) { + if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) { cga->fullchange = changeframecount; cga_recalctimings(cga); } @@ -111,6 +120,17 @@ cga_out(uint16_t addr, uint8_t val, void *priv) cga_recalctimings(cga); return; + case 0x3DB: + if (cga->lp_strobe == 1) + cga->lp_strobe = 0; + return; + case 0x3DC: + if (cga->lp_strobe == 0) { + cga->lp_strobe = 1; + cga_update_latch(cga); + } + return; + default: break; } @@ -119,8 +139,7 @@ cga_out(uint16_t addr, uint8_t val, void *priv) uint8_t cga_in(uint16_t addr, void *priv) { - const cga_t *cga = (cga_t *) priv; - + cga_t *cga = (cga_t *) priv; uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) @@ -131,22 +150,23 @@ cga_in(uint16_t addr, void *priv) ret = cga->crtcreg; break; case 0x3D5: - switch (cga->crtcreg) { - default: - ret = cga->crtc[cga->crtcreg]; - break; - case 0x10: - ret = 0x0f; - break; - case 0x11: - ret = 0x78; - break; - } + ret = cga->crtc[cga->crtcreg]; break; case 0x3DA: ret = cga->cgastat; break; + case 0x3DB: + if (cga->lp_strobe == 1) + cga->lp_strobe = 0; + break; + case 0x3DC: + if (cga->lp_strobe == 0) { + cga->lp_strobe = 1; + cga_update_latch(cga); + } + break; + default: break; } From 4c086d543c515141d90900158fe1b94faea7d984 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 26 Sep 2024 07:16:05 +0200 Subject: [PATCH 13/27] Tandy 1000 SX/HX: Fix the condition for the latch pen strobe reads and writes, fixes Jungle Hunt freezing on Tandy again. --- src/machine/m_tandy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 2fdc491f9..11bd41a66 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -827,12 +827,12 @@ vid_out(uint16_t addr, uint8_t val, void *priv) break; case 0x3db: - if (dev->is_sl2 && (vid->lp_strobe == 1)) + if (!dev->is_sl2 && (vid->lp_strobe == 1)) vid->lp_strobe = 0; break; case 0x3dc: - if (dev->is_sl2 && (vid->lp_strobe == 0)) { + if (!dev->is_sl2 && (vid->lp_strobe == 0)) { vid->lp_strobe = 1; vid_update_latch(vid); } @@ -894,12 +894,12 @@ vid_in(uint16_t addr, void *priv) break; case 0x3db: - if (dev->is_sl2 && (vid->lp_strobe == 1)) + if (!dev->is_sl2 && (vid->lp_strobe == 1)) vid->lp_strobe = 0; break; case 0x3dc: - if (dev->is_sl2 && (vid->lp_strobe == 0)) { + if (!dev->is_sl2 && (vid->lp_strobe == 0)) { vid->lp_strobe = 1; vid_update_latch(vid); } From 625da7cab6f7abfe4ee972c57c05c3f33ef1cd53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 26 Sep 2024 22:14:28 +0200 Subject: [PATCH 14/27] PIIX3: Fix MIRQ0 / legacy IRQ switch, fixes #4861. --- src/chipset/intel_piix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 1f95c28b3..c6a6fc0ac 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -599,9 +599,9 @@ piix_write(int func, int addr, uint8_t val, void *priv) pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); if (dev->type == 3) { if (val & 0x20) - sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); - else sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); } piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled"); } From 962c9cdf2ff43fdab96d444930a1c0dbad0cee3d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 26 Sep 2024 23:18:38 +0200 Subject: [PATCH 15/27] S3 Pre-ViRGE changes of the day (September 26th, 2024) 1. Actually fix the remaining pinkish/reddish stuff in 32bpp modes properly (for real, especially OS/2 and possibly other stuff). 2. The Compare accel stuff is more sanitized. 3. When the BitBLT DY coordinates are negative, don't draw the pixels. This fixes some software cursor issues with OS/2's S3 3.03.xx drivers. 4. Reset the FIFO when the card is reset. 5. Indentation fixes (to be improved further however). 6. Implement bit 5 functionality of 0xBEE8 index 0xE (MULT_MISC) (and currently only in the Rectangle Fill command). This fixes missing text on I-O Data Vision968 specific drivers for Windows 3.10 Japanese (PC/AT compatible) 7. Moved the Streams engine out of the FIFO (like the ViRGE) as well as making all CRTC's of the Trio64V2 writable and SEQREGs from 0x10 onwards to make sure the Streams engine works properly. 8. Added a missing break from the RAMDAC read stuff. 9. Remove a leftover of PCem. --- src/video/vid_s3.c | 1920 ++++++++++++++++++++++++++++++-------------- 1 file changed, 1307 insertions(+), 613 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 27d4f023e..4a0ffc993 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -365,7 +365,7 @@ typedef struct s3_t { event_t *wake_fifo_thread; event_t *fifo_not_full_event; - int blitter_busy; + atomic_int blitter_busy; uint64_t blitter_time; uint64_t status_time; @@ -950,6 +950,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x9ae9: s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3->accel.ssv_state = 0; + if (s3->bpp == 3) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] &= ~0x10; + } s3->accel_start(-1, 0, 0xffffffff, 0, s3); break; @@ -985,20 +989,50 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xa148: case 0xa2e8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } + } else s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; break; case 0xa149: case 0xa2e9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } if (s3->accel.color_16bit_check) s3->accel.bkgd_color_actual[1] = s3->accel.bkgd_color & 0xff; else @@ -1006,43 +1040,79 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa14a: case 0xa2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } } break; case 0xa14b: case 0xa2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xa548: case 0xa6e8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } + } else s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; break; case 0xa549: case 0xa6e9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } if (s3->accel.color_16bit_check) s3->accel.frgd_color_actual[1] = s3->accel.frgd_color & 0xff; @@ -1051,43 +1121,79 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa54a: case 0xa6ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if ((s3->accel.multifunc[0xe] & 0x10)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } } break; case 0xa54b: case 0xa6eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xa948: case 0xaae8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } + } else s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; break; case 0xa949: case 0xaae9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } if (s3->accel.color_16bit_check) s3->accel.wrt_mask_actual[1] = s3->accel.wrt_mask & 0xff; @@ -1096,83 +1202,296 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa94a: case 0xaaea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } } break; case 0xa94b: case 0xaaeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xad48: case 0xaee8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } + } else s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; break; case 0xad49: case 0xaee9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } break; case 0xad4a: case 0xaeea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } } break; case 0xad4b: case 0xaeeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xb148: case 0xb2e8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } + } else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } else { + s3->accel.b2e8_pix = 1; + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[0] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3->accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else { + if (s3->accel.color_16bit_check_rectfill) { + if (s3->accel.color_16bit_check) { + if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) { + s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, " + "check=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val; + s3->accel.pix_trans_x_count++; + s3->accel.pix_trans_x_count2 = s3->accel.pix_trans_x_count; + } + } else { + if (s3->accel.pix_trans_x_count2 < s3->accel.pix_trans_ptr_cnt) { + s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, " + "check=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count2, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2] = val; + s3->accel.pix_trans_x_count2++; + } + s3_log("WriteCNT=%d, TotalCNT=%d.\n", s3->accel.pix_trans_x_count2, + s3->accel.pix_trans_ptr_cnt); + if (s3->accel.pix_trans_x_count2 == s3->accel.pix_trans_ptr_cnt) { + for (int i = 0; i < s3->accel.pix_trans_ptr_cnt; i += 2) { + s3_log("Transferring write count=%d, bytes=%04x.\n", i, + s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8)); + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8), s3); + } + + s3->accel.pix_trans_x_count2 = 0; + s3->accel.color_16bit_check_rectfill = 0; + if (s3->accel.pix_trans_ptr != NULL) { + free(s3->accel.pix_trans_ptr); + s3->accel.pix_trans_ptr = NULL; + } + } + } + break; + } + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + break; + + default: + break; + } + } + } break; case 0xb149: case 0xb2e9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } + } else { + s3->accel.b2e8_pix = 1; + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[1] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || + ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3->accel_start(8, 1, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + } else + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || + ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3->accel_start(16, 1, s3->accel.pix_trans[1] | + (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3->accel_start(16, 1, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | + (s3->accel.pix_trans[0] << 8), s3); + else + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | + (s3->accel.pix_trans[0] << 8), s3); + else + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3->accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3->accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } else + s3->accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3->accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3->accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + } + } + break; + + default: + break; + } + + } + } break; case 0xb14a: case 0xb2ea: @@ -1194,6 +1513,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); else s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; } break; @@ -1391,9 +1711,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[1] = val; if (s3->accel.cmd & 0x100) { - s3_log("S3 PIXTRANS_B write (E2E9): cmd=%03x, pixelcntl=%02x, frgdmix=%02x, " - "bkgdmix=%02x, curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a], - s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val); switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -1541,13 +1858,26 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (port != 0x9ee8 && port != 0x9d48) { - if (port == 0xb2e8 || port == 0xb148) { - s3->accel.b2e8_pix = 1; + if ((port != 0x9ee8) && (port != 0x9d48)) { + if ((port == 0xb2e8) || (port == 0xb148)) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + } else { + s3->accel.b2e8_pix = 1; + s3_accel_out_pixtrans_w(s3, val); + } } else { + s3_log("Port WriteW FIFO=%04x, val=%04x, bussize=%03x.\n", port, val, s3->accel.cmd & 0x600); s3->accel.b2e8_pix = 0; + if ((port == 0xe2e8) || (port == 0xe2ea) || (port == 0xe148) || (port == 0xe14a)) + s3_accel_out_pixtrans_w(s3, val); + else { + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + } } - s3_accel_out_pixtrans_w(s3, val); } else { s3->accel.short_stroke = val; s3->accel.ssv_state = 1; @@ -1568,12 +1898,29 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { - if (port == 0xb2e8 || port == 0xb148) - s3->accel.b2e8_pix = 1; - else + if ((port == 0xb2e8) || (port == 0xb148)) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + s3_accel_out_fifo(s3, port + 2, val >> 16); + s3_accel_out_fifo(s3, port + 3, val >> 24); + } else { + s3->accel.b2e8_pix = 1; + s3_accel_out_pixtrans_l(s3, val); + } + } else { s3->accel.b2e8_pix = 0; - - s3_accel_out_pixtrans_l(s3, val); + s3_log("Port WriteL FIFO=%04x, val=%08x, bussize=%03x.\n", port, val, s3->accel.cmd & 0x600); + if ((port == 0xe2e8) || (port == 0xe148)) + s3_accel_out_pixtrans_l(s3, val); + else { + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + s3_accel_out_fifo(s3, port + 2, val >> 16); + s3_accel_out_fifo(s3, port + 3, val >> 24); + } + } } static void @@ -1749,77 +2096,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3->accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } else { - switch (addr & 0x1ffff) { - case 0x83b0: - case 0x83b1: - case 0x83b2: - case 0x83b3: - case 0x83b4: - case 0x83b5: - case 0x83b6: - case 0x83b7: - case 0x83b8: - case 0x83b9: - case 0x83ba: - case 0x83bb: - case 0x83bc: - case 0x83bd: - case 0x83be: - case 0x83bf: - case 0x83c0: - case 0x83c1: - case 0x83c2: - case 0x83c3: - case 0x83c4: - case 0x83c5: - case 0x83c6: - case 0x83c7: - case 0x83c8: - case 0x83c9: - case 0x83ca: - case 0x83cb: - case 0x83cc: - case 0x83cd: - case 0x83ce: - case 0x83cf: - case 0x83d0: - case 0x83d1: - case 0x83d2: - case 0x83d3: - case 0x83d4: - case 0x83d5: - case 0x83d6: - case 0x83d7: - case 0x83d8: - case 0x83d9: - case 0x83da: - case 0x83db: - case 0x83dc: - case 0x83dd: - case 0x83de: - case 0x83df: - s3_out(addr & 0x3ff, val, s3); - break; - case 0x8504: - s3->subsys_stat &= ~val; - s3_update_irqs(s3); - break; - case 0x8505: - s3->subsys_cntl = val; - s3_update_irqs(s3); - break; - case 0x850c: - s3->accel.advfunc_cntl = val; - s3_updatemapping(s3); - break; - case 0xff20: - s3->serialport = val; - i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); - break; - default: - s3_accel_out_fifo(s3, addr & 0xffff, val); - break; - } + s3_accel_out_fifo(s3, addr & 0xffff, val); } } else { if (addr & 0x8000) { @@ -1858,45 +2135,21 @@ mmio_byte_write: static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { - const svga_t *svga = &s3->svga; - - if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1fffe) < 0x8000) { - s3_accel_out_pixtrans_w(s3, val); - } else { - switch (addr & 0x1fffe) { - default: - case 0x83d4: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - break; - case 0xff20: - s3_accel_write_fifo(s3, addr, val); - break; - case 0x811c: - s3_accel_out_fifo_w(s3, 0x9ee8, val); - break; - } - } - } else { - if (addr & 0x8000) { - if (addr == 0x811c) - s3_accel_out_fifo_w(s3, 0x9ee8, val); + if ((addr & 0x1fffe) < 0x8000) { + s3_accel_out_pixtrans_w(s3, val); + } else if ((addr & 0x1fffe) == 0x811c) { + s3_accel_out_fifo_w(s3, 0x9ee8, val); + } else if (((addr & 0x1fffe) >= 0x8000) && (addr & 0x1fffe) < 0x10000) { + if (((addr & 0x1fffe) == 0xe2e8) || ((addr & 0x1fffe) == 0xe2ea)) { + if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) + s3_accel_out_pixtrans_w(s3, val); else { - if ((addr == 0xe2e8) || (addr == 0xe2ea)) { - if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) - s3_accel_out_pixtrans_w(s3, val); - else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } - } else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); } } else { - s3_accel_out_pixtrans_w(s3, val); + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); } } } @@ -1904,221 +2157,78 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { - svga_t *svga = &s3->svga; + if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { + s3_visionx68_video_engine_op(val, s3); + } else if ((addr & 0x1fffc) < 0x8000) { + s3_accel_out_pixtrans_l(s3, val); + } else if ((addr & 0x1fffc) >= 0x18000) { + switch (addr & 0x1fffc) { + case 0x18080: + s3->videoengine.nop = 1; + break; - if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1fffc) < 0x8000 || ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000)) { - if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { - s3_visionx68_video_engine_op(val, s3); - } else if ((addr & 0x1fffc) < 0x8000) { - s3_accel_out_pixtrans_l(s3, val); - } - } else { - switch (addr & 0x1fffc) { - case 0x8180: - s3->streams.pri_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x8184: - s3->streams.chroma_ctrl = val; - break; - case 0x8190: - s3->streams.sec_ctrl = val; - s3->streams.dda_horiz_accumulator = val & 0xfff; - if (val & (1 << 11)) - s3->streams.dda_horiz_accumulator |= 0xfffff800; - s3->streams.sdif = (val >> 24) & 7; - break; - case 0x8194: - s3->streams.chroma_upper_bound = val; - break; - case 0x8198: - s3->streams.sec_filter = val; - s3->streams.k1_horiz_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k1_horiz_scale |= 0xfffff800; - s3->streams.k2_horiz_scale = (val >> 16) & 0x7ff; - if ((val >> 16) & (1 << 10)) - s3->streams.k2_horiz_scale |= 0xfffff800; - break; - case 0x81a0: - s3->streams.blend_ctrl = val; - break; - case 0x81c0: - s3->streams.pri_fb0 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81c4: - s3->streams.pri_fb1 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81c8: - s3->streams.pri_stride = val & 0xfff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81cc: - s3->streams.buffer_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81d0: - s3->streams.sec_fb0 = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81d4: - s3->streams.sec_fb1 = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81d8: - s3->streams.sec_stride = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81dc: - s3->streams.overlay_ctrl = val; - break; - case 0x81e0: - s3->streams.k1_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k1_vert_scale |= 0xfffff800; - break; - case 0x81e4: - s3->streams.k2_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k2_vert_scale |= 0xfffff800; - break; - case 0x81e8: - s3->streams.dda_vert_accumulator = val & 0xfff; - if (val & (1 << 11)) - s3->streams.dda_vert_accumulator |= 0xfffff800; - break; - case 0x81ec: - s3->streams.fifo_ctrl = val; - break; - case 0x81f0: - s3->streams.pri_start = val; - s3->streams.pri_x = (val >> 16) & 0x7ff; - s3->streams.pri_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81f4: - s3->streams.pri_size = val; - s3->streams.pri_w = (val >> 16) & 0x7ff; - s3->streams.pri_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81f8: - s3->streams.sec_start = val; - s3->streams.sec_x = (val >> 16) & 0x7ff; - s3->streams.sec_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81fc: - s3->streams.sec_size = val; - s3->streams.sec_w = (val >> 16) & 0x7ff; - s3->streams.sec_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; + case 0x18088: + s3->videoengine.cntl = val; + s3->videoengine.dda_init_accumulator = val & 0xfff; + s3->videoengine.odf = (val >> 16) & 7; + s3->videoengine.yuv = !!(val & (1 << 19)); + s3->videoengine.idf = (val >> 20) & 7; + s3->videoengine.dither = !!(val & (1 << 29)); + s3->videoengine.dm_index = (val >> 23) & 7; + break; - case 0x8504: - s3->subsys_stat &= ~(val & 0xff); - s3->subsys_cntl = (val >> 8); - s3_update_irqs(s3); - break; + case 0x1808c: + s3->videoengine.stretch_filt_const = val; + s3->videoengine.k2 = val & 0x7ff; + s3->videoengine.k1 = (val >> 16) & 0x7ff; + s3->videoengine.host_data = !!(val & (1 << 30)); + s3->videoengine.scale_down = !!(val & (1 << 31)); + break; - case 0x850c: - s3->accel.advfunc_cntl = val & 0xff; - s3_updatemapping(s3); - break; + case 0x18090: + s3->videoengine.src_dst_step = val; + s3->videoengine.dst_step = val & 0x1fff; + s3->videoengine.src_step = (val >> 16) & 0x1fff; + break; - case 0xff20: - s3_accel_write_fifo(s3, addr, val); - break; + case 0x18094: + s3->videoengine.crop = val; + s3->videoengine.len = val & 0xfff; + s3->videoengine.start = (val >> 16) & 0xfff; + s3->videoengine.input = 1; + break; - case 0x18080: - s3->videoengine.nop = 1; - break; + case 0x18098: + s3->videoengine.src_base = val & 0xffffff; + break; - case 0x18088: - s3->videoengine.cntl = val; - s3->videoengine.dda_init_accumulator = val & 0xfff; - s3->videoengine.odf = (val >> 16) & 7; - s3->videoengine.yuv = !!(val & (1 << 19)); - s3->videoengine.idf = (val >> 20) & 7; - s3->videoengine.dither = !!(val & (1 << 29)); - s3->videoengine.dm_index = (val >> 23) & 7; - break; + case 0x1809c: + s3->videoengine.dest_base = val & 0xffffff; + break; - case 0x1808c: - s3->videoengine.stretch_filt_const = val; - s3->videoengine.k2 = val & 0x7ff; - s3->videoengine.k1 = (val >> 16) & 0x7ff; - s3->videoengine.host_data = !!(val & (1 << 30)); - s3->videoengine.scale_down = !!(val & (1 << 31)); - break; - - case 0x18090: - s3->videoengine.src_dst_step = val; - s3->videoengine.dst_step = val & 0x1fff; - s3->videoengine.src_step = (val >> 16) & 0x1fff; - break; - - case 0x18094: - s3->videoengine.crop = val; - s3->videoengine.len = val & 0xfff; - s3->videoengine.start = (val >> 16) & 0xfff; - s3->videoengine.input = 1; - break; - - case 0x18098: - s3->videoengine.src_base = val & 0xffffff; - break; - - case 0x1809c: - s3->videoengine.dest_base = val & 0xffffff; - break; - - default: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - break; - } + default: + break; } - } else { - if (addr & 0x8000) { - if (addr == 0xe2e8) { - if ((s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) - s3_accel_out_pixtrans_l(s3, val); - else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - } else { + } else if (((addr & 0x1fffc) >= 0x8000) && ((addr & 0x1fffc) < 0x10000)) { + if ((addr & 0x1fffc) == 0xe2e8) { + if ((s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) + s3_accel_out_pixtrans_l(s3, val); + else { s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); } } else { - s3_accel_out_pixtrans_l(s3, val); + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); } } } + static void s3_vblank_start(svga_t *svga) { @@ -2148,7 +2258,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) const s3_t *s3 = (s3_t *) svga->priv; int shift = 1; int width = 16; - uint16_t dat[2]; + uint16_t dat[2] = { 0, 0 }; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg; @@ -2481,7 +2591,6 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine) { const s3_t *s3 = (s3_t *) svga->priv; int offset = (s3->streams.sec_x - s3->streams.pri_x) + 1; - int h_acc = s3->streams.dda_horiz_accumulator; int r[8]; int g[8]; int b[8]; @@ -2491,7 +2600,7 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine) uint32_t *p; uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - p = &(buffer32->line[displine][offset + svga->x_add]); + p = &((uint32_t *)buffer32->line[displine])[offset + svga->x_add]; if ((offset + s3->streams.sec_w) > s3->streams.pri_w) x_size = (s3->streams.pri_w - s3->streams.sec_x) + 1; @@ -2503,13 +2612,14 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine) for (int x = 0; x < x_size; x++) { *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - h_acc += s3->streams.k1_horiz_scale; - if (h_acc >= 0) { + svga->overlay_latch.h_acc += s3->streams.k1_horiz_scale; + if (svga->overlay_latch.h_acc >= 0) { if ((x_read ^ (x_read + 1)) & ~3) OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; - h_acc += (s3->streams.k2_horiz_scale - s3->streams.k1_horiz_scale); + svga->overlay_latch.h_acc += (s3->streams.k2_horiz_scale - s3->streams.k1_horiz_scale); } } @@ -2731,16 +2841,24 @@ s3_out(uint16_t addr, uint8_t val, void *priv) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) { - case 0x12: - case 0x13: - svga_recalctimings(svga); - return; + if (s3->chip == S3_TRIO64V2) { + if (svga->seqaddr >= 0x10) { + svga->seqregs[svga->seqaddr] = val; + svga_recalctimings(svga); + return; + } + } else { + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) { + case 0x12: + case 0x13: + svga_recalctimings(svga); + return; - default: - break; + default: + break; + } } } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ @@ -2813,8 +2931,6 @@ s3_out(uint16_t addr, uint8_t val, void *priv) return; if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - if ((s3->chip == S3_TRIO64V2) && (svga->crtcreg >= 0x80)) - return; if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50)) return; @@ -2833,6 +2949,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x50: s3->bpp = (svga->crtc[0x50] >> 4) & 3; + s3_log("S3 BPP=%d.\n", s3->bpp); if (s3->bpp == 3) { if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/ s3->accel.multifunc[0xe] &= ~0x10; @@ -3084,7 +3201,7 @@ s3_in(uint16_t addr, void *priv) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + if ((svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) && (s3->chip < S3_TRIO64V2)) { temp = svga->seqregs[svga->seqaddr]; /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not get stuck in an infinite loop. */ @@ -3093,6 +3210,8 @@ s3_in(uint16_t addr, void *priv) (s3->card_type == S3_CARDEX_TRIO64VPLUS)) && (svga->seqaddr == 0x17)) svga->seqregs[svga->seqaddr] ^= 0x01; return temp; + } if ((svga->seqaddr >= 0x10) && (s3->chip >= S3_TRIO64V2)) { + return svga->seqregs[svga->seqaddr]; } else if ((svga->seqaddr >= 5) && (svga->seqaddr < 8)) return 0xff; else @@ -3131,6 +3250,7 @@ s3_in(uint16_t addr, void *priv) return sc1502x_ramdac_in(addr, svga->ramdac, svga); else return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); + break; case 0x3d4: return svga->crtcreg; @@ -3382,7 +3502,6 @@ s3_recalctimings(svga_t *svga) #endif if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { - svga->vram_display_mask = s3->vram_mask; s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " "attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4, @@ -4144,12 +4263,11 @@ s3_recalctimings(svga_t *svga) default: break; } + svga->vram_display_mask = s3->vram_mask; } else { - svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if (svga->crtc[0x31] & 0x08) { - svga->vram_display_mask = s3->vram_mask; if (svga->bpp == 8) { if (!(svga->crtc[0x5e] & 0x04)) svga->vblankstart = svga->dispend; /*Applies only to Enhanced modes*/ @@ -4158,9 +4276,13 @@ s3_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_highres; svga->rowoffset <<= 1; } - } - } - } + svga->vram_display_mask = s3->vram_mask; + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; } if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_VISION864)) @@ -4272,7 +4394,6 @@ s3_trio64v_recalctimings(svga_t *svga) svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { - svga->vram_display_mask = s3->vram_mask; switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -4299,9 +4420,9 @@ s3_trio64v_recalctimings(svga_t *svga) default: break; } + svga->vram_display_mask = s3->vram_mask; } else svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; - } else /*Streams mode*/ { if (s3->streams.buffer_ctrl & 1) @@ -4323,20 +4444,22 @@ s3_trio64v_recalctimings(svga_t *svga) svga->overlay.addr = s3->streams.sec_fb0; svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.h_acc = s3->streams.dda_horiz_accumulator; svga->overlay.v_acc = s3->streams.dda_vert_accumulator; svga->rowoffset = s3->streams.pri_stride >> 3; - svga->vram_display_mask = s3->vram_mask; + if (svga->overlay.ena) { + svga->overlay.ena = (((s3->streams.blend_ctrl >> 24) & 7) == 0b000) || + (((s3->streams.blend_ctrl >> 24) & 7) == 0b101); + } switch ((s3->streams.pri_ctrl >> 24) & 0x7) { case 0: /*RGB-8 (CLUT)*/ svga->render = svga_render_8bpp_highres; break; case 3: /*KRGB-16 (1.5.5.5)*/ - svga->multiplier = 0.5; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ - svga->multiplier = 0.5; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -4349,6 +4472,7 @@ s3_trio64v_recalctimings(svga_t *svga) default: break; } + svga->vram_display_mask = s3->vram_mask; } svga->hoverride = 1; @@ -4411,8 +4535,6 @@ s3_updatemapping(s3_t *s3) else s3->linear_base &= 0x00ffffff; } - - s3_log("LinearBase=%x, crtc58bits=%x.\n", s3->linear_base, svga->crtc[0x58] & 0x13); if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10)) { /*Linear framebuffer*/ mem_mapping_disable(&svga->mapping); @@ -4478,8 +4600,8 @@ s3_updatemapping(s3_t *s3) mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } - mem_mapping_enable(&s3->mmio_mapping); + } else + mem_mapping_enable(&s3->mmio_mapping); } else { mem_mapping_disable(&s3->mmio_mapping); } @@ -4536,11 +4658,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv) case 0x4148: case 0x42e8: s3->subsys_stat &= ~val; + s3->accel.subsys_cntl = (s3->accel.subsys_cntl & 0xff00) | val; s3_update_irqs(s3); break; case 0x4149: case 0x42e9: - s3->subsys_cntl = val; + s3->accel.subsys_cntl = (s3->accel.subsys_cntl & 0xff) | (val << 8); s3_update_irqs(s3); break; case 0x4548: @@ -4612,7 +4735,7 @@ s3_accel_in(uint16_t port, void *priv) return s3->subsys_stat; case 0x4149: case 0x42e9: - return s3->subsys_cntl; + return s3->accel.subsys_cntl >> 8; case 0x8148: case 0x82e8: @@ -4684,6 +4807,8 @@ s3_accel_in(uint16_t port, void *priv) case 0x9548: case 0x96e8: if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt & 0xff; } break; @@ -4787,9 +4912,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color >> 16; + else + temp2 = s3->accel.bkgd_color & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 16; + else + temp2 = s3->accel.bkgd_color & 0xff; + } + } else temp2 = s3->accel.bkgd_color & 0xff; return temp2; @@ -4800,13 +4936,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color >> 24; + else + temp2 = s3->accel.bkgd_color >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 24; + else + temp2 = s3->accel.bkgd_color >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.bkgd_color >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -4814,32 +4971,51 @@ s3_accel_in(uint16_t port, void *priv) case 0xa2ea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color & 0xff; - else - temp2 = s3->accel.bkgd_color >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.bkgd_color >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color & 0xff; + else + temp2 = s3->accel.bkgd_color >> 16; + } return temp2; case 0xa14b: case 0xa2eb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color >> 8; - else - temp2 = s3->accel.bkgd_color >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.bkgd_color >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color >> 8; + else + temp2 = s3->accel.bkgd_color >> 24; + s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xa548: case 0xa6e8: if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color >> 16; + else + temp2 = s3->accel.frgd_color & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 16; + else + temp2 = s3->accel.frgd_color & 0xff; + } + } else temp2 = s3->accel.frgd_color & 0xff; return temp2; @@ -4850,13 +5026,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color >> 24; + else + temp2 = s3->accel.frgd_color >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 24; + else + temp2 = s3->accel.frgd_color >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.frgd_color >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -4864,23 +5061,31 @@ s3_accel_in(uint16_t port, void *priv) case 0xa6ea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color & 0xff; - else - temp2 = s3->accel.frgd_color >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.frgd_color >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color & 0xff; + else + temp2 = s3->accel.frgd_color >> 16; + } return temp2; case 0xa54b: case 0xa6eb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color >> 8; - else - temp2 = s3->accel.frgd_color >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.frgd_color >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color >> 8; + else + temp2 = s3->accel.frgd_color >> 24; + s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xa948: @@ -4888,9 +5093,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask >> 16; + else + temp2 = s3->accel.wrt_mask & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 16; + else + temp2 = s3->accel.wrt_mask & 0xff; + } + } else temp2 = s3->accel.wrt_mask & 0xff; return temp2; @@ -4901,13 +5117,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask >> 24; + else + temp2 = s3->accel.wrt_mask >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 24; + else + temp2 = s3->accel.wrt_mask >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.wrt_mask >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -4915,23 +5152,31 @@ s3_accel_in(uint16_t port, void *priv) case 0xaaea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask & 0xff; - else - temp2 = s3->accel.wrt_mask >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.wrt_mask >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask & 0xff; + else + temp2 = s3->accel.wrt_mask >> 16; + } return temp2; case 0xa94b: case 0xaaeb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask >> 8; - else - temp2 = s3->accel.wrt_mask >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.wrt_mask >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask >> 8; + else + temp2 = s3->accel.wrt_mask >> 24; + s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xad48: @@ -4939,9 +5184,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask >> 16; + else + temp2 = s3->accel.rd_mask & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 16; + else + temp2 = s3->accel.rd_mask & 0xff; + } + } else temp2 = s3->accel.rd_mask & 0xff; return temp2; @@ -4952,13 +5208,35 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask >> 24; + else + temp2 = s3->accel.rd_mask >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 24; + else + temp2 = s3->accel.rd_mask >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.rd_mask >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } + return temp2; } break; @@ -4966,23 +5244,31 @@ s3_accel_in(uint16_t port, void *priv) case 0xaeea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask & 0xff; - else - temp2 = s3->accel.rd_mask >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.rd_mask >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask & 0xff; + else + temp2 = s3->accel.rd_mask >> 16; + } return temp2; case 0xad4b: case 0xaeeb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask >> 8; - else - temp2 = s3->accel.rd_mask >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.rd_mask >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask >> 8; + else + temp2 = s3->accel.rd_mask >> 24; + s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xb148: @@ -5059,33 +5345,58 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - switch (temp) { - case 0x0: - return s3->accel.multifunc[0x0] & 0xff; - case 0x1: - return s3->accel.multifunc[0x1] & 0xff; - case 0x2: - return s3->accel.multifunc[0x2] & 0xff; - case 0x3: - return s3->accel.multifunc[0x3] & 0xff; - case 0x4: - return s3->accel.multifunc[0x4] & 0xff; - case 0x5: - return s3->accel.multifunc[0xa] & 0xff; - case 0x6: - return s3->accel.multifunc[0xe] & 0xff; - case 0x7: - return s3->accel.cmd & 0xff; - case 0x8: - return s3->accel.subsys_cntl & 0xff; - case 0x9: - return s3->accel.setup_md & 0xff; - case 0xa: - return s3->accel.multifunc[0xd] & 0xff; + if (s3->chip >= S3_VISION964) { + temp = s3->accel.multifunc[0xf] & 0xf; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] & 0xff; + case 0x1: + return s3->accel.multifunc[0x1] & 0xff; + case 0x2: + return s3->accel.multifunc[0x2] & 0xff; + case 0x3: + return s3->accel.multifunc[0x3] & 0xff; + case 0x4: + return s3->accel.multifunc[0x4] & 0xff; + case 0x5: + return s3->accel.multifunc[0xa] & 0xff; + case 0x6: + return s3->accel.multifunc[0xe] & 0xff; + case 0x7: + return s3->accel.cmd & 0xff; + case 0x8: + return s3->accel.subsys_cntl & 0xff; + case 0x9: + return s3->accel.setup_md & 0xff; + case 0xa: + return s3->accel.multifunc[0xd] & 0xff; - default: - break; + default: + break; + } + } else { + temp = s3->accel.multifunc[0xf] & 7; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] & 0xff; + case 0x1: + return s3->accel.multifunc[0x1] & 0xff; + case 0x2: + return s3->accel.multifunc[0x2] & 0xff; + case 0x3: + return s3->accel.multifunc[0x3] & 0xff; + case 0x4: + return s3->accel.multifunc[0x4] & 0xff; + case 0x5: + return s3->accel.multifunc[0xa] & 0xff; + case 0x6: + return s3->accel.multifunc[0xe] & 0xff; + case 0x7: + return s3->accel.cmd & 0xff; + + default: + break; + } } return 0xff; } @@ -5095,34 +5406,60 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - s3->accel.multifunc[0xf]++; - switch (temp) { - case 0x0: - return s3->accel.multifunc[0x0] >> 8; - case 0x1: - return s3->accel.multifunc[0x1] >> 8; - case 0x2: - return s3->accel.multifunc[0x2] >> 8; - case 0x3: - return s3->accel.multifunc[0x3] >> 8; - case 0x4: - return s3->accel.multifunc[0x4] >> 8; - case 0x5: - return s3->accel.multifunc[0xa] >> 8; - case 0x6: - return s3->accel.multifunc[0xe] >> 8; - case 0x7: - return s3->accel.cmd >> 8; - case 0x8: - return (s3->accel.subsys_cntl >> 8) & ~0xe000; - case 0x9: - return (s3->accel.setup_md >> 8) & ~0xf000; - case 0xa: - return s3->accel.multifunc[0xd] >> 8; + if (s3->chip >= S3_VISION964) { + temp = s3->accel.multifunc[0xf] & 0xf; + s3->accel.multifunc[0xf] = (s3->accel.multifunc[0xf] + 1) & 0xf; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] >> 8; + case 0x1: + return s3->accel.multifunc[0x1] >> 8; + case 0x2: + return s3->accel.multifunc[0x2] >> 8; + case 0x3: + return s3->accel.multifunc[0x3] >> 8; + case 0x4: + return s3->accel.multifunc[0x4] >> 8; + case 0x5: + return s3->accel.multifunc[0xa] >> 8; + case 0x6: + return s3->accel.multifunc[0xe] >> 8; + case 0x7: + return s3->accel.cmd >> 8; + case 0x8: + return (s3->accel.subsys_cntl >> 8) & ~0xe000; + case 0x9: + return (s3->accel.setup_md >> 8) & ~0xf000; + case 0xa: + return s3->accel.multifunc[0xd] >> 8; - default: - break; + default: + break; + } + } else { + temp = s3->accel.multifunc[0xf] & 7; + s3->accel.multifunc[0xf] = (s3->accel.multifunc[0xf] + 1) & 7; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] >> 8; + case 0x1: + return s3->accel.multifunc[0x1] >> 8; + case 0x2: + return s3->accel.multifunc[0x2] >> 8; + case 0x3: + return s3->accel.multifunc[0x3] >> 8; + case 0x4: + return s3->accel.multifunc[0x4] >> 8; + case 0x5: + return s3->accel.multifunc[0xa] >> 8; + case 0x6: + return s3->accel.multifunc[0xe] >> 8; + case 0x7: + return s3->accel.cmd >> 8; + + default: + break; + } } return 0xff; } @@ -5515,15 +5852,40 @@ s3_accel_write(uint32_t addr, uint8_t val, void *priv) { s3_t *s3 = (s3_t *) priv; const svga_t *svga = &s3->svga; + uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff; if (!s3->enable_8514) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + if ((addr & addr_mask) < 0x8000) { + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_BYTE); + } else { + switch (addr & addr_mask) { + case 0x83b0 ... 0x83df: + s3_out(addr & 0x3ff, val, s3); + break; + case 0x8504: + s3->subsys_stat &= ~val; + s3_update_irqs(s3); + break; + case 0x8505: + s3->subsys_cntl = val; + s3_update_irqs(s3); + break; + case 0x850c: + s3->accel.advfunc_cntl = val; + s3_updatemapping(s3); + break; + case 0xff20: + s3->serialport = val; + i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); + break; + default: + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_BYTE); + break; + } + } } else s3_accel_write_fifo(s3, addr & 0xffff, val); } @@ -5533,15 +5895,28 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *priv) { s3_t *s3 = (s3_t *) priv; const svga_t *svga = &s3->svga; + uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff; if (!s3->enable_8514) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + if ((addr & (addr_mask - 1)) < 0x8000) { + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_WORD); + } else { + switch (addr & (addr_mask - 1)) { + case 0x83d4: + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + break; + case 0xff20: + s3_accel_write_fifo(s3, addr, val); + break; + default: + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_WORD); + break; + } + } } else s3_accel_write_fifo_w(s3, addr & 0xffff, val); } @@ -5550,16 +5925,162 @@ static void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv) { s3_t *s3 = (s3_t *) priv; - const svga_t *svga = &s3->svga; + svga_t *svga = &s3->svga; + uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff; if (!s3->enable_8514) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + if ((addr & (addr_mask - 3)) < 0x8000) { + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_DWORD); + } else { + switch (addr & (addr_mask - 3)) { + case 0x8180: + s3->streams.pri_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x8184: + s3->streams.chroma_ctrl = val; + break; + case 0x8190: + s3->streams.sec_ctrl = val; + s3->streams.dda_horiz_accumulator = val & 0xfff; + if (val & 0x1000) + s3->streams.dda_horiz_accumulator |= ~0xfff; + + s3->streams.sdif = (val >> 24) & 7; + break; + case 0x8194: + s3->streams.chroma_upper_bound = val; + break; + case 0x8198: + s3->streams.sec_filter = val; + s3->streams.k1_horiz_scale = val & 0x7ff; + if (val & 0x800) + s3->streams.k1_horiz_scale |= ~0x7ff; + + s3->streams.k2_horiz_scale = (val >> 16) & 0x7ff; + if ((val >> 16) & 0x800) + s3->streams.k2_horiz_scale |= ~0x7ff; + + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81a0: + s3->streams.blend_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81c0: + s3->streams.pri_fb0 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81c4: + s3->streams.pri_fb1 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81c8: + s3->streams.pri_stride = val & 0xfff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81cc: + s3->streams.buffer_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81d0: + s3->streams.sec_fb0 = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81d4: + s3->streams.sec_fb1 = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81d8: + s3->streams.sec_stride = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81dc: + s3->streams.overlay_ctrl = val; + break; + case 0x81e0: + s3->streams.k1_vert_scale = val & 0x7ff; + if (val & 0x800) + s3->streams.k1_vert_scale |= ~0x7ff; + break; + case 0x81e4: + s3->streams.k2_vert_scale = val & 0x7ff; + if (val & 0x800) + s3->streams.k2_vert_scale |= ~0x7ff; + break; + case 0x81e8: + s3->streams.dda_vert_accumulator = val & 0xfff; + if (val & 0x1000) + s3->streams.dda_vert_accumulator |= ~0xfff; + + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81ec: + s3->streams.fifo_ctrl = val; + break; + case 0x81f0: + s3->streams.pri_start = val; + s3->streams.pri_x = (val >> 16) & 0x7ff; + s3->streams.pri_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81f4: + s3->streams.pri_size = val; + s3->streams.pri_w = (val >> 16) & 0x7ff; + s3->streams.pri_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81f8: + s3->streams.sec_start = val; + s3->streams.sec_x = (val >> 16) & 0x7ff; + s3->streams.sec_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81fc: + s3->streams.sec_size = val; + s3->streams.sec_w = (val >> 16) & 0x7ff; + s3->streams.sec_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + + case 0x8504: + s3->subsys_stat &= ~(val & 0xff); + s3->subsys_cntl = (val >> 8); + s3_update_irqs(s3); + break; + + case 0x850c: + s3->accel.advfunc_cntl = val & 0xff; + s3_updatemapping(s3); + break; + + case 0xff20: + s3_accel_write_fifo(s3, addr, val); + break; + + default: + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_DWORD); + break; + } + } } else s3_accel_write_fifo_l(s3, addr & 0xffff, val); } @@ -7987,12 +8508,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi uint32_t *vram_l = (uint32_t *) svga->vram; uint32_t compare = s3->accel.color_cmp; uint8_t rop = s3->accel.ropmix & 0xff; - int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; uint32_t wrt_mask = s3->accel.wrt_mask; uint32_t frgd_color = s3->accel.frgd_color; uint32_t bkgd_color = s3->accel.bkgd_color; int cmd = s3->accel.cmd >> 13; + int update = 1; uint32_t srcbase; uint32_t dstbase; @@ -8075,6 +8596,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi /*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)*/ + s3_log("CMD=%d, full=%04x, s3bpp=%x, multifuncE=%03x, sourcedisplay=%x, mmio=%02x, srcbase=%08x, dstbase=%08x.\n", cmd, s3->accel.cmd, s3->bpp, s3->accel.multifunc[0x0e] & 0x230, vram_mask, svga->crtc[0x53] & 0x18, srcbase, dstbase); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (s3->accel.ssv_state == 0) @@ -8105,7 +8627,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8203,7 +8740,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8292,7 +8844,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8381,9 +8948,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && count == 16) { /*Stupid undocumented 0xB2E8 on 911/924*/ + if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Stupid undocumented 0xB2E8 on 911/924*/ count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; + s3_log("CMD2: B2E8 pixtrans, frgdmix=%d, bkgdmix=%d.\n", frgd_mix, bkgd_mix); } while (count-- && s3->accel.sy >= 0) { @@ -8392,7 +8960,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.temp_cnt = 16; } - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + if ((((s3->accel.cx) >= clip_l && (s3->accel.cx) <= clip_r && (s3->accel.cy) >= clip_t && (s3->accel.cy) <= clip_b) && !(s3->accel.multifunc[0xe] & 0x20)) || + (((s3->accel.cx) < clip_l && (s3->accel.cx) > clip_r && (s3->accel.cy) < clip_t && (s3->accel.cy) > clip_b) && (s3->accel.multifunc[0xe] & 0x20)) ) { if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (s3_cpu_dest(s3) && vram_mask) { @@ -8426,7 +8995,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.cx, dest_dat); MIX @@ -8462,11 +9046,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); else - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + if (s3->accel.cmd & 0x80) s3->accel.cy++; else @@ -8536,7 +9121,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); MIX @@ -8571,11 +9171,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cur_x = s3->accel.poly_cx & 0xfff; s3->accel.cur_y = s3->accel.poly_cy & 0xfff; s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; - s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy2 & 0xfff; } break; - case 6: /*BitBlt*/ + case 6: /*BitBlt*/ if (!cpu_input) { /*!cpu_input is trigger to start operation*/ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; @@ -8597,15 +9197,17 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) { + if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { while (1) { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && (s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b) { READ(s3->accel.src + s3->accel.cx, src_dat); READ(s3->accel.dest + s3->accel.dx, dest_dat); dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } } s3->accel.cx++; @@ -8620,7 +9222,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy++; s3->accel.dy++; - s3->accel.dy &= 0xfff; s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -8635,7 +9236,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } else { while (count-- && s3->accel.sy >= 0) { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && ((s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)) { + if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { READ(s3->accel.src + s3->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); @@ -8661,7 +9262,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); MIX @@ -8706,7 +9322,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy--; s3->accel.dy--; } - s3->accel.dy &= 0xfff; s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -8755,7 +9370,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; while (count-- && s3->accel.sy >= 0) { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && (s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b) { if (vram_mask) { READ(s3->accel.src + s3->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); @@ -8781,7 +9396,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); MIX @@ -8872,7 +9502,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { src_dat = s3->accel.frgd_color; - if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) && (s3->accel.cmd & 0x10)) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8906,7 +9551,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { src_dat = s3->accel.frgd_color; - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8995,7 +9655,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); MIX @@ -9128,7 +9803,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); ROPMIX @@ -9309,16 +9999,18 @@ s3_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) + if (val & PCI_COMMAND_IO) { s3_io_set(s3); - else + } else s3_io_remove(s3); + if (s3->chip >= S3_TRIO64V) s3->pci_regs[PCI_REG_COMMAND] = (val & 0x27); else s3->pci_regs[PCI_REG_COMMAND] = (val & 0x23); + s3_updatemapping(s3); - break; + return; case 0x07: if (s3->chip == S3_TRIO64V2) { @@ -9470,6 +10162,10 @@ s3_reset(void *priv) if (reset_state != NULL) { s3->accel.multifunc[0xe] &= ~(0x200 | 0x10); s3_disable_handlers(s3); + s3->force_busy = 0; + s3->blitter_busy = 0; + s3->fifo_read_idx = 0; + s3->fifo_write_idx = 0; if (s3->pci) reset_state->pci_slot = s3->pci_slot; @@ -9751,6 +10447,7 @@ s3_init(const device_t *info) vram_size = vram << 20; else vram_size = 512 << 10; + s3->vram_mask = vram_size - 1; s3->vram = vram; @@ -10039,6 +10736,7 @@ s3_init(const device_t *info) stepping = 0xc0; /*Vision864*/ else stepping = 0xc1; /*Vision864P*/ + s3->id = stepping; s3->id_ext = s3->id_ext_pci = stepping; s3->packed_mmio = 0; @@ -10164,10 +10862,6 @@ s3_init(const device_t *info) case S3_CARDEX_TRIO64VPLUS: case S3_DIAMOND_STEALTH64_764: case S3_SPEA_MIRAGE_P64: - if (device_get_config_int("memory") == 1) - svga->vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ - /* Fall over. */ - fallthrough; case S3_NUMBER9_9FX: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio64*/ From 9ff72338d1476d9c107de4457d04c5f7325110b1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Sep 2024 13:33:43 +0200 Subject: [PATCH 16/27] Voodoo: Attempt to implement the 16bpp + depth combined writes. --- src/include/86box/vid_voodoo_regs.h | 20 ++++++++++++-------- src/video/vid_voodoo_fb.c | 28 +++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/include/86box/vid_voodoo_regs.h b/src/include/86box/vid_voodoo_regs.h index 379219d35..6aeb98bcc 100644 --- a/src/include/86box/vid_voodoo_regs.h +++ b/src/include/86box/vid_voodoo_regs.h @@ -338,18 +338,22 @@ enum { }; enum { - LFB_FORMAT_RGB565 = 0, - LFB_FORMAT_RGB555 = 1, - LFB_FORMAT_ARGB1555 = 2, - LFB_FORMAT_XRGB8888 = 4, - LFB_FORMAT_ARGB8888 = 5, - LFB_FORMAT_DEPTH = 15, - LFB_FORMAT_MASK = 15 + LFB_FORMAT_RGB565 = 0, + LFB_FORMAT_RGB555 = 1, + LFB_FORMAT_ARGB1555 = 2, + LFB_FORMAT_XRGB8888 = 4, + LFB_FORMAT_ARGB8888 = 5, + LFB_FORMAT_DEPTH_RGB565 = 12, + LFB_FORMAT_DEPTH_RGB555 = 13, + LFB_FORMAT_DEPTH_ARGB1555 = 14, + LFB_FORMAT_DEPTH = 15, + LFB_FORMAT_MASK = 15 }; enum { LFB_WRITE_COLOUR = 1, - LFB_WRITE_DEPTH = 2 + LFB_WRITE_DEPTH = 2, + LFB_WRITE_BOTH = 4 }; enum { diff --git a/src/video/vid_voodoo_fb.c b/src/video/vid_voodoo_fb.c index 5156cfdad..5ae26b4c5 100644 --- a/src/video/vid_voodoo_fb.c +++ b/src/video/vid_voodoo_fb.c @@ -373,6 +373,26 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) addr >>= 1; break; + case LFB_FORMAT_DEPTH_RGB565: + colour_data[0] = rgb565[val & 0xffff]; + depth_data[0] = val >> 16; + write_mask = LFB_WRITE_BOTH; + count = 1; + break; + case LFB_FORMAT_DEPTH_RGB555: + colour_data[0] = argb1555[val & 0xffff]; + depth_data[0] = val >> 16; + write_mask = LFB_WRITE_BOTH; + count = 1; + break; + case LFB_FORMAT_DEPTH_ARGB1555: + colour_data[0] = argb1555[val & 0xffff]; + alpha_data[0] = colour_data[0].a; + depth_data[0] = val >> 16; + write_mask = LFB_WRITE_BOTH; + count = 1; + break; + case LFB_FORMAT_DEPTH: depth_data[0] = val; depth_data[1] = val >> 16; @@ -469,9 +489,15 @@ skip_pixel: } else { for (int c = 0; c < count; c++) { if (write_mask & LFB_WRITE_COLOUR) - *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = + do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); if (write_mask & LFB_WRITE_DEPTH) *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; + if (write_mask & LFB_WRITE_BOTH) { + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = + do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); + *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; + } write_addr += 2; write_addr_aux += 2; From 74b398be29ff4d6aa199c9d088903a9ed837b931 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Sep 2024 14:34:45 +0200 Subject: [PATCH 17/27] S3 non-ViRGE: Do not remove I/O handlers on ISA/VLB card reset, fixes soft reset, fixes #4866. --- src/video/vid_s3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 4a0ffc993..2b14284c7 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -10131,7 +10131,8 @@ static int vram_sizes[] = { static void s3_disable_handlers(s3_t *s3) { - s3_io_remove(s3); + if (s3->pci) + s3_io_remove(s3); mem_mapping_disable(&s3->linear_mapping); mem_mapping_disable(&s3->mmio_mapping); From 36bccdf7a92d9e0e8f3c697b8fa29aaf4a46e60b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Sep 2024 18:32:43 +0200 Subject: [PATCH 18/27] Changed the version number to 4.2.2. --- CMakeLists.txt | 2 +- debian/changelog | 4 ++-- src/unix/assets/86Box.spec | 4 ++-- src/unix/assets/net.86box.86Box.metainfo.xml | 2 +- vcpkg.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2a78aa2f..a1fae72e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 4.3 + VERSION 4.2.2 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) diff --git a/debian/changelog b/debian/changelog index 827665880..ae80cfa9d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (4.3) UNRELEASED; urgency=medium +86box (4.2.2) UNRELEASED; urgency=medium * Bump release. - -- Jasmine Iwanek Mon, 02 Sep 2024 00:16:28 +0200 + -- Jasmine Iwanek Sat, 28 Sep 2024 18:31:57 +0200 diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index 86f380d22..e351c017a 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -15,7 +15,7 @@ %global romver 4.1 Name: 86Box -Version: 4.3 +Version: 4.2.2 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -121,5 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Sat Aug 31 Jasmine Iwanek 4.3-1 +* Sat Aug 31 Jasmine Iwanek 4.2.2-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index 7a0786a16..47a0a6b87 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -11,7 +11,7 @@ net.86box.86Box.desktop - + diff --git a/vcpkg.json b/vcpkg.json index 87859869b..af6f9a5c8 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "4.3", + "version-string": "4.2.2", "homepage": "https://86box.net/", "documentation": "https://86box.readthedocs.io/", "license": "GPL-2.0-or-later", From bdc43043003ff39db1547dc3d23fbeef8d79fc0e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 28 Sep 2024 19:17:57 +0200 Subject: [PATCH 19/27] Added more conditions under which control register writes cause MMU cache flushes. --- src/cpu/x86_ops_mov_ctrl.h | 8 ++++---- src/cpu/x86_ops_mov_ctrl_2386.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index f4241feb1..b4f0c498a 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -184,7 +184,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { if (is_p6 || cpu_use_dynarec) @@ -222,7 +222,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; @@ -249,7 +249,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { if (is_p6 || cpu_use_dynarec) @@ -287,7 +287,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h index 03a18caa7..13e08a145 100644 --- a/src/cpu/x86_ops_mov_ctrl_2386.h +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -180,7 +180,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { flushmmucache_nopc(); @@ -214,7 +214,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; @@ -241,7 +241,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { flushmmucache_nopc(); @@ -275,7 +275,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; From c172cc8dbea177b90430f3e106d364a98356ca3b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 29 Sep 2024 10:27:21 +0200 Subject: [PATCH 20/27] RTL8139C+: Fix duplex negotiation so it correctly negotiates full duples, fixes #4867. --- src/network/net_rtl8139.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 0b00d589a..f04f9b7a3 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -1076,10 +1076,11 @@ rtl8139_reset(void *priv) s->cplus_enabled = 0; #if 0 - s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex -#endif + s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation s->BasicModeCtrl = 0x1000; // autonegotiation +#endif + s->BasicModeCtrl = 0x1100; // full duplex, autonegotiation rtl8139_reset_phy(s); From d5f01259bcefff1af5cf70b5d68ad5a0e9a16b97 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 29 Sep 2024 10:31:45 +0200 Subject: [PATCH 21/27] Preferences dialog: make the slider a bit bigger, fixes #4860. --- src/qt/qt_progsettings.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index 16fb439be..ac4327341 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -88,7 +88,7 @@ - + 10 From 250f477200bf03068f29b7cda11795b28bcb0bd3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 29 Sep 2024 13:23:43 +0200 Subject: [PATCH 22/27] MMU: No longer page fault on CPU-initiated writes to write-protected pages (eg. when setting segment accessed bit), fixes OpenBSD 7.0, fixes #1853. --- src/mem/mem.c | 16 ++++++++-------- src/mem/mmu_2386.c | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/mem/mem.c b/src/mem/mem.c index 0b038d640..57dc31e33 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -320,7 +320,7 @@ mmutranslatereal_normal(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -341,7 +341,7 @@ mmutranslatereal_normal(uint32_t addr, int rw) temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -405,7 +405,7 @@ mmutranslatereal_pae(uint32_t addr, int rw) if (temp & 0x80) { /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -426,7 +426,7 @@ mmutranslatereal_pae(uint32_t addr, int rw) addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); temp = rammap64(addr4) & 0x000000ffffffffffULL; temp3 = temp & temp4; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -488,7 +488,7 @@ mmutranslate_noabrt_normal(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (temp & ~0x3fffff) + (addr & 0x3fffff); @@ -497,7 +497,7 @@ mmutranslate_noabrt_normal(uint32_t addr, int rw) temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); @@ -532,7 +532,7 @@ mmutranslate_noabrt_pae(uint32_t addr, int rw) if (temp & 0x80) { /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; @@ -543,7 +543,7 @@ mmutranslate_noabrt_pae(uint32_t addr, int rw) temp3 = temp & temp4; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 43bdd4602..7418a88d8 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -198,7 +198,7 @@ mmutranslatereal_2386(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -219,7 +219,7 @@ mmutranslatereal_2386(uint32_t addr, int rw) temp = mem_readl_map((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -258,7 +258,7 @@ mmutranslate_noabrt_2386(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (temp & ~0x3fffff) + (addr & 0x3fffff); @@ -267,7 +267,7 @@ mmutranslate_noabrt_2386(uint32_t addr, int rw) temp = mem_readl_map((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); From 6c2a667d0cdb080b37893ff2a1a0999c1a7403af Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 29 Sep 2024 18:16:32 +0200 Subject: [PATCH 23/27] x86seg.c: Use the correct memory read/write functions on 486+. --- src/cpu/x86seg.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 61e9e558a..61c0edd9f 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -48,12 +48,12 @@ #define seg_writememwl writememwl_2386 #define seg_writememll writememll_2386 #else -#define seg_readmembl readmembl_2386 -#define seg_readmemwl readmemwl_2386 -#define seg_readmemll readmemll_2386 -#define seg_writemembl writemembl_2386 -#define seg_writememwl writememwl_2386 -#define seg_writememll writememll_2386 +#define seg_readmembl readmembl +#define seg_readmemwl readmemwl +#define seg_readmemll readmemll +#define seg_writemembl writemembl +#define seg_writememwl writememwl +#define seg_writememll writememll #endif #define DPL ((segdat[2] >> 13) & 3) From 2844acee116b983afccb3e45e81c3fb11e34a6b7 Mon Sep 17 00:00:00 2001 From: "Joakim L. Gilje" Date: Sun, 29 Sep 2024 21:57:47 +0200 Subject: [PATCH 24/27] Compile and linker fixes for OpenBSD * link with wxneeded required for DYNAREC, in addition to being installed onto a filesystem with the wxallowed flag (like /usr/local on a default installation) * pthread_setname_np is pthread_set_name_np on OpenBSD --- CMakeLists.txt | 4 ++++ src/qt/qt_platform.cpp | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1fae72e7..a70cbd61f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,10 @@ else() option(CPPTHREADS "C++11 threads" ON) endif() +if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,wxneeded") +endif() + # Development branch features # # Option Description Def. Condition Otherwise diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 98907f07a..e48cb1f3e 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -54,6 +54,10 @@ # include #endif +#ifdef Q_OS_OPENBSD +# include +#endif + #if 0 static QByteArray buf; #endif @@ -804,8 +808,10 @@ plat_set_thread_name(void *thread, const char *name) char truncated[16]; # endif strncpy(truncated, name, sizeof(truncated) - 1); -# ifdef Q_OS_DARWIN +# if defined(Q_OS_DARWIN) pthread_setname_np(truncated); +# elif defined(Q_OS_OPENBSD) + pthread_set_name_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # else pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # endif From 7e0c6e9b698c33a777228e8cfd90e809caec62cc Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 30 Sep 2024 18:08:05 +0200 Subject: [PATCH 25/27] Enable the SYSENTER/SYSEXIT MSR's on Pentium Pro, fixes OpenBSD booting, fixes #4873. --- src/cpu/cpu.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 438e12d5c..878c67b6a 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -3300,26 +3300,17 @@ pentium_invalid_rdmsr: break; /* SYSENTER_CS - SYSENTER target CS */ case 0x174: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; - EAX &= 0xffff0000; EAX |= msr.sysenter_cs; EDX = 0x00000000; break; /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; - EAX = msr.sysenter_esp; EDX = 0x00000000; break; /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; - EAX = msr.sysenter_eip; EDX = 0x00000000; break; @@ -4069,23 +4060,14 @@ pentium_invalid_wrmsr: break; /* SYSENTER_CS - SYSENTER target CS */ case 0x174: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; - msr.sysenter_cs = EAX & 0xFFFF; break; /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; - msr.sysenter_esp = EAX; break; /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; - msr.sysenter_eip = EAX; break; /* MCG_CAP - Machine Check Global Capability */ From 1e84b46a5db15645365f1a6b0aefdb7575946576 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Oct 2024 08:53:57 +0200 Subject: [PATCH 26/27] 86F: Correct the obtaining of the preceding bits in direct writes, fixes bit stream compliance. --- src/floppy/fdd_86f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 3fe1428a1..cf9e83694 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1854,6 +1854,7 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 if (type == 0) { /* Byte write. */ encoded_byte = d86f_encode_byte(drive, 0, dbyte, dpbyte); + dev->preceding_bit[side] = encoded_byte & 1; if (!d86f_reverse_bytes(drive)) { mask_data = encoded_byte >> 8; encoded_byte &= 0xFF; @@ -1863,6 +1864,7 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 } else { /* Word write. */ encoded_byte = byte; + dev->preceding_bit[side] = (encoded_byte >> 8) & 1; if (d86f_reverse_bytes(drive)) { mask_data = encoded_byte >> 8; encoded_byte &= 0xFF; @@ -1871,8 +1873,6 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 } } - dev->preceding_bit[side] = encoded_byte & 1; - if (d86f_has_surface_desc(drive)) { /* Inverted track data, clear bits are now set. */ mask_data = ~dev->track_encoded_data[side][pos]; From 8899b1411b0377aafb8de584f6697a587677559a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 1 Oct 2024 09:56:40 +0200 Subject: [PATCH 27/27] AMD K6-2 onwards: EFER write GPF is now correctly on bits 5 onwards, not on bits 1 onwards. --- src/cpu/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 878c67b6a..0c6d36097 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -3705,7 +3705,7 @@ cpu_WRMSR(void) /* Extended Feature Enable Register */ case 0xc0000080: temp = EAX | ((uint64_t) EDX << 32); - if (temp & ~1ULL) + if (temp & ~0x1fULL) x86gpf(NULL, 0); else msr.amd_efer = temp;