diff --git a/CMakeLists.txt b/CMakeLists.txt index f2a78aa2f..a70cbd61f 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) @@ -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/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/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"); } 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..c1f359f26 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,9 @@ 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]; if (state != dev->mem_state[7]) { mem_set_mem_state_both(0xe0000, 0x10000, state); @@ -194,8 +199,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 +218,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 +309,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 +320,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 +365,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 +398,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 +464,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; } diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 354a0644e..05a5cf12e 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -3301,26 +3301,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; @@ -3715,7 +3706,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; @@ -4070,23 +4061,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 */ 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; 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) 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 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; } 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: diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 5a5eec398..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]; @@ -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 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/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/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); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 6c478b37a..11bd41a66 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)) @@ -871,6 +893,18 @@ vid_in(uint16_t addr, void *priv) 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/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)); 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); 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 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 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; 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 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/src/video/vid_cga.c b/src/video/vid_cga.c index 2ea07c346..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)) @@ -137,6 +156,17 @@ cga_in(uint16_t addr, void *priv) 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; } diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 27d4f023e..2b14284c7 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) { @@ -9439,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); @@ -9470,6 +10163,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 +10448,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 +10737,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 +10863,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*/ 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; 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); } 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",