diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 349d8f7b2..44bf94a08 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -285,6 +285,8 @@ extern const device_t et4000w32_device; extern const device_t et4000w32_onboard_device; extern const device_t et4000w32i_isa_device; extern const device_t et4000w32i_vlb_device; +extern const device_t et4000w32p_videomagic_revb_vlb_device; +extern const device_t et4000w32p_videomagic_revb_pci_device; extern const device_t et4000w32p_revc_vlb_device; extern const device_t et4000w32p_revc_pci_device; extern const device_t et4000w32p_vlb_device; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 043d9a4ac..dfc0c242e 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -43,6 +43,7 @@ #define BIOS_ROM_PATH_W32 "roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" #define BIOS_ROM_PATH_W32I_ISA "roms/video/et4000w32/ET4KW32I.VBI" #define BIOS_ROM_PATH_W32I_VLB "roms/video/et4000w32/tseng.u41.bin" +#define BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB "roms/video/et4000w32/VideoMagic-BioS-HXIRTW32PWSRL.BIN" #define BIOS_ROM_PATH_W32P "roms/video/et4000w32/ET4K_W32.BIN" #define BIOS_ROM_PATH_W32P_REVC "roms/video/et4000w32/et4000w32pcardex.BIN" @@ -58,6 +59,7 @@ enum ET4000W32, ET4000W32I, ET4000W32P_REVC, + ET4000W32P_VIDEOMAGIC_REVB, ET4000W32P, ET4000W32P_CARDEX, ET4000W32P_DIAMOND @@ -104,6 +106,8 @@ typedef struct et4000w32p_t int pattern_x, source_x, pattern_x_back, source_x_back, pattern_y, source_y, cpu_dat_pos, pix_pos, cpu_input_num, fifo_queue; + int pattern_x_diff, pattern_y_diff, pattern_x_diff2, pattern_y_diff2; + int patcnt, mmu_start; uint32_t pattern_addr, source_addr, dest_addr, mix_addr, pattern_back, source_back, dest_back, mix_back, @@ -116,7 +120,7 @@ typedef struct et4000w32p_t uint32_t base[3]; uint8_t ctrl; } mmu; - + volatile int busy; } et4000w32p_t; @@ -172,7 +176,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p) uint8_t old; uint32_t add2addr = 0; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { @@ -248,7 +252,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p) } } if (svga->crtcreg == 0x30) { - if (et4000->pci) + if (et4000->pci && (et4000->rev != 5)) et4000->linearbase = (et4000->linearbase & 0xc0000000) | ((val & 0xfc) << 22); else et4000->linearbase = val << 22; @@ -314,12 +318,12 @@ et4000w32p_in(uint16_t addr, void *p) et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_t *svga = &et4000->svga; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { case 0x3c5: - if ((svga->seqaddr & 0xf) == 7) + if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4; break; @@ -376,7 +380,7 @@ et4000w32p_in(uint16_t addr, void *p) break; } if (et4000->index == 0xef) { - if (et4000->type >= ET4000W32P_REVC) + if (et4000->pci) return (et4000->regs[0xef] & 0x0f) | (et4000->rev << 4) | et4000->pci; else return (et4000->regs[0xef] & 0x8f) | (et4000->rev << 4) | et4000->vlb; @@ -439,8 +443,11 @@ et4000w32p_recalctimings(svga_t *svga) svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; else svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else if ((svga->gdcreg[5] & 0x40) == 0) + } else if ((svga->gdcreg[5] & 0x40) == 0) { svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + if (svga->hdisp == 648 || svga->hdisp == 808 || svga->hdisp == 1032) + svga->hdisp -= 8; + } } } @@ -459,7 +466,7 @@ et4000w32p_recalctimings(svga_t *svga) } et4000->adjust_cursor = 0; - + switch (svga->bpp) { case 15: case 16: svga->hdisp >>= 1; @@ -489,11 +496,15 @@ et4000w32p_recalctimings(svga_t *svga) else svga->render = svga_render_text_80; } else { - if (svga->adv_flags & FLAG_NOSKEW) + if (svga->adv_flags & FLAG_NOSKEW) { svga->ma_latch--; + } switch (svga->gdcreg[5] & 0x60) { - case 0x00: + case 0x00: + if (et4000->rev == 5) + svga->ma_latch++; + if (svga->seqregs[1] & 8) /* Low res (320) */ svga->render = svga_render_4bpp_lowres; else @@ -663,7 +674,7 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00ff) | ((val & 0x0f) << 8); break; case 0x8e: - if (et4000->type >= ET4000W32P_REVC) + if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.pixel_depth = val & 0x30; else et4000->acl.queued.vbus = val & 0x03; @@ -731,11 +742,12 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) et4000w32_blit_start(et4000); et4000->acl.cpu_input_num = 0; if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000->acl.mmu_start = 0; et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); } } break; - case 0xa4: + case 0xa4: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; break; case 0xa5: @@ -795,9 +807,10 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uin et4000->acl.queued.dest_addr = ((addr & 0x1fff) + et4000->mmu.base[bank]); et4000->acl.internal = et4000->acl.queued; et4000w32_blit_start(et4000); - et4000w32_log("Accelerated MMU aperture = %i and start XY Block (Implicit), xcnt = %i, ycnt = %i\n", bank, et4000->acl.x_count + 1, et4000->acl.y_count + 1); + et4000w32_log("ET4000W32 Accelerated MMU aperture start XY Block (Implicit): bank = %i, patx = %i, paty = %i, wrap y = %i\n", et4000->bank, et4000->acl.pattern_x, et4000->acl.pattern_y, et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7]); et4000->acl.cpu_input_num = 0; if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000->acl.mmu_start = 1; et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); } } @@ -816,7 +829,7 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uin et4000->acl.cpu_input_num = 0; } - + if ((et4000->acl.internal.ctrl_routing & 7) == 4) /*CPU data is X Count*/ et4000w32_blit(val | (et4000->acl.queued.count_x << 8), 0, 0, 0xffffffff, et4000); if ((et4000->acl.internal.ctrl_routing & 7) == 5) /*CPU data is Y Count*/ @@ -840,8 +853,8 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val, et4000->bank); } else { if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { - svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]] = val; - svga->changedvram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) >> 12] = changeframecount; + svga->vram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask] = val; + svga->changedvram[(((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask) >> 12] = changeframecount; } } break; @@ -850,7 +863,7 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val); } else { switch (addr & 0xff) { - case 0x00: + case 0x00: et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x3fff00) | val; break; case 0x01: @@ -898,7 +911,7 @@ et4000w32p_mmu_read(uint32_t addr, void *p) et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_t *svga = &et4000->svga; uint8_t temp; - + switch (addr & 0x6000) { case 0x0000: /* MMU 0 */ case 0x2000: /* MMU 1 */ @@ -920,7 +933,7 @@ et4000w32p_mmu_read(uint32_t addr, void *p) if ((addr & 0x1fff) + et4000->mmu.base[et4000->bank] >= svga->vram_max) return 0xff; - + return svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]]; case 0x6000: @@ -988,8 +1001,8 @@ et4000w32p_mmu_read(uint32_t addr, void *p) return et4000->acl.internal.dest_off & 0xff; case 0x8d: return et4000->acl.internal.dest_off >> 8; - case 0x8e: - if (et4000->type >= ET4000W32P_REVC) + case 0x8e: + if (et4000->type >= ET4000W32P_REVC) return et4000->acl.internal.pixel_depth; else return et4000->acl.internal.vbus; @@ -1023,7 +1036,7 @@ et4000w32_blit_start(et4000w32p_t *et4000) { et4000->acl.x_count = et4000->acl.internal.count_x; et4000->acl.y_count = et4000->acl.internal.count_y; - + et4000->acl.pattern_addr = et4000->acl.internal.pattern_addr; et4000->acl.source_addr = et4000->acl.internal.source_addr; et4000->acl.dest_addr = et4000->acl.internal.dest_addr; @@ -1085,9 +1098,9 @@ et4000w32p_blit_start(et4000w32p_t *et4000) et4000->acl.internal.pos_x = et4000->acl.internal.pos_y = 0; et4000->acl.pattern_x = et4000->acl.source_x = et4000->acl.pattern_y = et4000->acl.source_y = 0; et4000->acl.status |= ACL_XYST; - + et4000w32_log("ACL status XYST set\n"); - if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40)) + if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40)) et4000->acl.status |= ACL_SSO; if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { @@ -1459,6 +1472,7 @@ et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4 svga_t *svga = &et4000->svga; uint8_t pattern, source, dest; uint8_t rop; + uint8_t out; int mixmap; while (count-- && et4000->acl.y_count >= 0) { @@ -1478,12 +1492,12 @@ et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4 mix_dat >>= 1; mix_dat |= 0x80000000; - ROPMIX(rop, dest, pattern, source, dest); + ROPMIX(rop, dest, pattern, source, out); /*Write the data*/ - svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = dest; + svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; - + if (et4000->acl.internal.xy_dir & 1) { et4000->acl.dest_addr--; et4000->acl.pattern_x--; @@ -1501,7 +1515,7 @@ et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4 if (et4000->acl.source_x >= (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1)) et4000->acl.source_x -= (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1); } - + et4000->acl.x_count--; if (et4000->acl.x_count == 0xffff) { et4000->acl.x_count = et4000->acl.internal.count_x; @@ -1590,14 +1604,14 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 et4000w32_log("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask]); } else { mixdat = mix & 1; - mix >>= 1; + mix >>= 1; mix |= 0x80000000; } et4000->acl.mix_addr++; rop = mixdat ? et4000->acl.internal.rop_fg : et4000->acl.internal.rop_bg; - + ROPMIX(rop, dest, pattern, source, out); - + et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & et4000->vram_mask, out); if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; @@ -1613,9 +1627,9 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 if (et4000->acl.internal.xy_dir & 1) et4000w32_decx(1, et4000); else et4000w32_incx(1, et4000); } else { - if (et4000->acl.internal.xy_dir & 1) + if (et4000->acl.internal.xy_dir & 1) et4000w32_incx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); - else + else et4000w32_decx((et4000->acl.internal.pixel_depth >> 4) & 3, et4000); et4000->acl.pix_pos = 0; @@ -1678,15 +1692,15 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 sdat >>= 8; } else source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; - + dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; out = 0; - + if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & et4000->vram_mask] & (1 << (et4000->acl.mix_addr & 7)); } else { mixdat = mix & 1; - mix >>= 1; + mix >>= 1; mix |= 0x80000000; } @@ -1694,7 +1708,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 ROPMIX(rop, dest, pattern, source, out); - if (!(et4000->acl.internal.ctrl_routing & 0x40)) { + if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & et4000->vram_mask] = out; svga->changedvram[(et4000->acl.dest_addr & et4000->vram_mask) >> 12] = changeframecount; } else { @@ -1706,7 +1720,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 et4000w32_decx(1, et4000); else et4000w32_incx(1, et4000); - + et4000->acl.x_count--; if (et4000->acl.x_count == 0xffff) { if (et4000->acl.internal.xy_dir & 2) { @@ -1734,7 +1748,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 return; if (et4000->acl.internal.ctrl_routing & 0x40) { - if (et4000->acl.cpu_dat_pos & 3) + if (et4000->acl.cpu_dat_pos & 3) et4000->acl.cpu_dat_pos += 4 - (et4000->acl.cpu_dat_pos & 3); return; } @@ -1756,7 +1770,7 @@ et4000w32p_hwcursor_draw(svga_t *svga, int displine) int minus_width = 0; uint8_t dat; offset = svga->hwcursor_latch.xoff; - + if (et4000->type == ET4000W32) { switch (svga->bpp) { case 8: @@ -1902,12 +1916,12 @@ et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) et4000w32p_recalcmapping(et4000); break; - case 0x13: - et4000->linearbase &= 0x00c00000; + case 0x13: + et4000->linearbase &= 0x00c00000; et4000->linearbase |= (et4000->pci_regs[0x13] << 24); svga->crtc[0x30] &= 3; svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); - et4000w32p_recalcmapping(et4000); + et4000w32p_recalcmapping(et4000); break; case 0x30: case 0x31: case 0x32: case 0x33: @@ -1917,11 +1931,11 @@ et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) et4000->pci_regs[0x32] = 0; et4000->pci_regs[0x33] &= 0xf0; if (et4000->pci_regs[0x30] & 0x01) { - uint32_t addr = (et4000->pci_regs[0x33] << 24); - if (!addr) - addr = 0xc0000; - et4000w32_log("ET4000 bios_rom enabled at %08x\n", addr); - mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000); + uint32_t biosaddr = (et4000->pci_regs[0x33] << 24); + if (!biosaddr) + biosaddr = 0xc0000; + et4000w32_log("ET4000 bios_rom enabled at %08x\n", biosaddr); + mem_mapping_set_addr(&et4000->bios_rom.mapping, biosaddr, 0x8000); } else { et4000w32_log("ET4000 bios_rom disabled\n"); mem_mapping_disable(&et4000->bios_rom.mapping); @@ -1940,7 +1954,7 @@ et4000w32p_init(const device_t *info) et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00; et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00; - + /*The ET4000/W32i ISA BIOS seems to not support 2MB of VRAM*/ if ((info->local == ET4000W32) || ((info->local == ET4000W32I) && !(et4000->vlb))) vram_size = 1; @@ -1972,14 +1986,14 @@ et4000w32p_init(const device_t *info) case ET4000W32: /* ET4000/W32 */ et4000->rev = 0; - + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = sdac_getclock; - break; + break; case ET4000W32I: /* ET4000/W32i rev B */ @@ -1987,7 +2001,7 @@ et4000w32p_init(const device_t *info) if (et4000->vlb) { rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + MEM_MAPPING_EXTERNAL); } else { rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -1998,6 +2012,19 @@ et4000w32p_init(const device_t *info) et4000->svga.getclock = sdac_getclock; break; + case ET4000W32P_VIDEOMAGIC_REVB: + /* ET4000/W32p rev B */ + et4000->rev = 5; + + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; + break; + case ET4000W32P_REVC: /* ET4000/W32p rev C */ et4000->rev = 7; @@ -2100,6 +2127,12 @@ et4000w32i_vlb_available(void) return rom_present(BIOS_ROM_PATH_W32I_VLB); } +int +et4000w32p_videomagic_revb_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32P_VIDEOMAGIC_REVB_VLB); +} + int et4000w32p_revc_available(void) @@ -2228,6 +2261,31 @@ const device_t et4000w32i_vlb_device = et4000w32p_config }; +const device_t et4000w32p_videomagic_revb_vlb_device = +{ + "Tseng Labs ET4000/w32p Rev. B VLB (VideoMagic)", + "et4000w32p_videomagic_revb_vlb", + DEVICE_VLB, ET4000W32P_VIDEOMAGIC_REVB, + et4000w32p_init, et4000w32p_close, NULL, + { et4000w32p_videomagic_revb_vlb_available }, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_config +}; + +const device_t et4000w32p_videomagic_revb_pci_device = +{ + "Tseng Labs ET4000/w32p Rev. B PCI (VideoMagic)", + "et4000w32p_videomagic_revb_pci", + DEVICE_PCI, ET4000W32P_VIDEOMAGIC_REVB, + et4000w32p_init, et4000w32p_close, NULL, + { et4000w32p_videomagic_revb_vlb_available }, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_config +}; + + const device_t et4000w32p_revc_vlb_device = { "Tseng Labs ET4000/w32p Rev. C VLB (Cardex)", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index db09d7757..af124f818 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -142,9 +142,11 @@ video_cards[] = { { &radius_svga_multiview_mca_device }, { &mach64gx_pci_device }, { &mach64vt2_device }, + { &et4000w32p_videomagic_revb_pci_device }, { &et4000w32p_revc_pci_device }, { &et4000w32p_cardex_pci_device }, { &et4000w32p_noncardex_pci_device }, + { &et4000w32p_pci_device }, { &gd5430_pci_device, }, { &gd5434_pci_device }, { &gd5436_pci_device }, @@ -153,7 +155,6 @@ video_cards[] = { { &gd5446_stb_pci_device }, { &gd5480_pci_device }, { &creative_voodoo_banshee_device }, - { &et4000w32p_pci_device }, { &s3_spea_mercury_lite_86c928_pci_device }, { &s3_diamond_stealth64_964_pci_device }, { &s3_elsa_winner2000_pro_x_964_pci_device }, @@ -197,6 +198,7 @@ video_cards[] = { { &voodoo_3_3000_device }, { &mach64gx_vlb_device }, { &et4000w32i_vlb_device }, + { &et4000w32p_videomagic_revb_vlb_device }, { &et4000w32p_revc_vlb_device }, { &et4000w32p_cardex_vlb_device }, { &et4000w32p_vlb_device },