diff --git a/src/include/86box/video.h b/src/include/86box/video.h index ed1df9766..c2064412a 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -259,9 +259,10 @@ extern const device_t et4000k_tg286_isa_device; extern const device_t et4000_kasan_isa_device; extern const device_t et4000_mca_device; -/* Tseng ET4000-W32p */ +/* Tseng ET4000-W32x */ extern const device_t et4000w32_device; -extern const device_t et4000w32i_device; +extern const device_t et4000w32i_isa_device; +extern const device_t et4000w32i_vlb_device; extern const device_t et4000w32p_vlb_device; extern const device_t et4000w32p_pci_device; extern const device_t et4000w32p_noncardex_vlb_device; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 10b3d7fda..ad6084bfc 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * ET4000/W32p emulation (Diamond Stealth 32) + * ET4000/W32 series emulation. * * Known bugs: Accelerator doesn't work in planar modes * @@ -39,10 +39,11 @@ #define BIOS_ROM_PATH_DIAMOND L"roms/video/et4000w32/et4000w32.bin" -#define BIOS_ROM_PATH_CARDEX L"roms/video/et4000w32/et4000w32pcardex.BIN" -#define BIOS_ROM_PATH_W32 L"roms/video/et4000w32/et4000w32isa.BIN" -#define BIOS_ROM_PATH_W32I L"roms/video/et4000w32/ET4KW32I.VBI" -#define BIOS_ROM_PATH_W32P L"roms/video/et4000w32/tsenget4000w32ppci.BIN" +#define BIOS_ROM_PATH_CARDEX L"roms/video/et4000w32/cardex.vbi" +#define BIOS_ROM_PATH_W32 L"roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" +#define BIOS_ROM_PATH_W32I_ISA L"roms/video/et4000w32/ET4KW32I.VBI" +#define BIOS_ROM_PATH_W32I_VLB L"roms/video/et4000w32/tseng.u41.bin" +#define BIOS_ROM_PATH_W32P L"roms/video/et4000w32/ET4K_W32.BIN" #define FIFO_SIZE 65536 #define FIFO_MASK (FIFO_SIZE - 1) @@ -201,7 +202,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (et4000->type != ET4000W32_DIAMOND) + if (et4000->type <= ET4000W32I) sdac_ramdac_out(addr, 1, val, svga->ramdac, svga); else stg_ramdac_out(addr, val, svga->ramdac, svga); @@ -302,7 +303,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) add2addr = svga->hwcursor.yoff * ((svga->hwcursor.xsize == 128) ? 32 : 16); svga->hwcursor.addr += add2addr; - if (et4000->type != ET4000W32_DIAMOND) { + if (et4000->type <= ET4000W32I) { if (svga->bpp == 15 || svga->bpp == 16) svga->hwcursor.x >>= 1; else if (svga->bpp == 24) @@ -330,7 +331,7 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (et4000->type != ET4000W32_DIAMOND) + if (et4000->type <= ET4000W32I) return sdac_ramdac_in(addr, 1, svga->ramdac, svga); else return stg_ramdac_in(addr, svga->ramdac, svga); @@ -355,11 +356,8 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) return (et4000->regs[0xec] & 0xf) | 0x30; /*ET4000/W32i rev B*/ else if (et4000->type == ET4000W32) return (et4000->regs[0xec] & 0xf); /*ET4000/W32*/ - else if (et4000->type == ET4000W32P || et4000->type == ET4000W32_DIAMOND) { - return (et4000->regs[0xec] & 0xf) | 0x60; /*ET4000/W32p rev D*/ - } else { - return (et4000->regs[0xec] & 0xf) | 0x70; /*ET4000/W32p rev C*/ - } + else + return (et4000->regs[0xec] & 0xf) | 0x60; /*ET4000/W32p rev D*/ } if (et4000->index == 0xee) /*Preliminary implementation*/ { @@ -372,20 +370,18 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) } if (et4000->index == 0xef) { - if (et4000->type == ET4000W32I) - return et4000->regs[0xef] | 0x30; /*ET4000/W32i rev B*/ - else if (et4000->type == ET4000W32) - return et4000->regs[0xef]; /*ET4000/W32*/ - else if (et4000->type == ET4000W32P || et4000->type == ET4000W32_DIAMOND) { - if (et4000->pci) - return et4000->regs[0xef] | 0xe0; /*ET4000/W32p rev D*/ - else - return et4000->regs[0xef] | 0x60; /*ET4000/W32p rev D*/ - } else { - if (et4000->pci) - return et4000->regs[0xef] | 0xf0; /*ET4000/W32p rev C*/ + if (et4000->type == ET4000W32I) { + if (et4000->isa) + return et4000->regs[0xef] | 0x30; /*ET4000/W32i rev B (ISA)*/ else - return et4000->regs[0xef] | 0x70; /*ET4000/W32p rev C*/ + return et4000->regs[0xef] | 0x70; /*ET4000/W32i rev B (VLB)*/ + } else if (et4000->type == ET4000W32) + return et4000->regs[0xef]; /*ET4000/W32*/ + else { + if (et4000->pci) + return et4000->regs[0xef] | 0xe0; /*ET4000/W32p rev D (PCI) */ + else + return et4000->regs[0xef] | 0x60; /*ET4000/W32p rev D (VLB) */ } } return et4000->regs[et4000->index]; @@ -409,6 +405,35 @@ void et4000w32p_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + if (svga->adv_flags & FLAG_NOSKEW) { + /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->ma_latch--; + + if ((svga->seqregs[1] & 8)) /*40 column*/ + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + } else { + switch (svga->gdcreg[5] & 0x60) { + case 0x40: case 0x60: /*256+ colours*/ + switch (svga->bpp) { + case 8: + case 24: + svga->hdisp += 8; + break; + case 15: + case 16: + svga->hdisp += 16; + break; + case 32: + break; + } + break; + } + } + } + switch (svga->bpp) { case 15: case 16: @@ -419,9 +444,70 @@ void et4000w32p_recalctimings(svga_t *svga) break; } - if ((svga->gdcreg[5] & 0x60) == 0x40 || (svga->gdcreg[5] & 0x60) == 0x60) { - if (et4000->type != ET4000W32_DIAMOND) - svga->clock /= 2; + svga->render = svga_render_blank; + if (!svga->scrblank && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) /*40 column*/ + svga->render = svga_render_text_40; + else + svga->render = svga_render_text_80; + } else { + if (svga->adv_flags & FLAG_NOSKEW) + svga->ma_latch--; + + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: /*256+ colours*/ + if (et4000->type <= ET4000W32I) + svga->clock /= 2; + + switch (svga->bpp) { + case 8: + svga->map8 = svga->pallook; + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; + case 15: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 24: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + } + break; + } + } } } @@ -1243,14 +1329,14 @@ void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et40 void et4000w32p_hwcursor_draw(svga_t *svga, int displine) { - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; int x, offset; uint8_t dat; + int width = (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff); int pitch = (svga->hwcursor_latch.xsize == 128) ? 32 : 16; offset = svga->hwcursor_latch.xoff; - for (x = 0; x < (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff); x += 4) - { + for (x = 0; x < width; x += 4) + { dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + svga->x_add + x] = (dat & 1) ? 0xFFFFFF : 0; @@ -1312,7 +1398,7 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) case 0x00: return 0x0c; /*Tseng Labs*/ case 0x01: return 0x10; - case 0x02: return (et4000->type == ET4000W32_CARDEX) ? 0x07 : 0x06; /*ET4000W32p Rev C or D*/ + case 0x02: return 0x06; /*ET4000W32p Rev D*/ case 0x03: return 0x32; case PCI_REG_COMMAND: @@ -1320,7 +1406,7 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - case 0x08: return (et4000->type == ET4000W32_CARDEX) ? 0x07 : 0x06; /*Revision ID*/ + case 0x08: return 0x06; /*Revision ID*/ case 0x09: return 0; /*Programming interface*/ case 0x0a: return 0x00; /*Supports VGA interface, XGA compatible*/ @@ -1428,8 +1514,12 @@ void *et4000w32p_init(const device_t *info) break; case ET4000W32I: - rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I, 0xc0000, 0x8000, 0x7fff, 0, - MEM_MAPPING_EXTERNAL); + if (et4000->isa) + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_ISA, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); + else + rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32I_VLB, 0xc0000, 0x8000, 0x7fff, 0, + MEM_MAPPING_EXTERNAL); et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; @@ -1440,18 +1530,20 @@ void *et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32P, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); + et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32_CARDEX: rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5341_ramdac_device); + et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; + et4000->svga.getclock = stg_getclock; + et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32_DIAMOND: @@ -1506,9 +1598,14 @@ int et4000w32_available(void) return rom_present(BIOS_ROM_PATH_W32); } -int et4000w32i_available(void) +int et4000w32i_isa_available(void) { - return rom_present(BIOS_ROM_PATH_W32I); + return rom_present(BIOS_ROM_PATH_W32I_ISA); +} + +int et4000w32i_vlb_available(void) +{ + return rom_present(BIOS_ROM_PATH_W32I_VLB); } int et4000w32p_noncardex_available(void) @@ -1587,12 +1684,23 @@ const device_t et4000w32_device = et4000w32p_config }; -const device_t et4000w32i_device = +const device_t et4000w32i_isa_device = { - "Tseng Labs ET4000/w32i", + "Tseng Labs ET4000/w32i ISA", DEVICE_ISA | DEVICE_AT, ET4000W32I, et4000w32p_init, et4000w32p_close, NULL, - { et4000w32i_available }, + { et4000w32i_isa_available }, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_config +}; + +const device_t et4000w32i_vlb_device = +{ + "Tseng Labs ET4000/w32i VLB", + DEVICE_VLB, ET4000W32I, + et4000w32p_init, et4000w32p_close, NULL, + { et4000w32i_vlb_available }, et4000w32p_speed_changed, et4000w32p_force_redraw, et4000w32p_config diff --git a/src/video/vid_sdac_ramdac.c b/src/video/vid_sdac_ramdac.c index d682fca0d..b4fbfb9b8 100644 --- a/src/video/vid_sdac_ramdac.c +++ b/src/video/vid_sdac_ramdac.c @@ -43,59 +43,58 @@ static void sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val) { ramdac->command = val; - switch (val >> 4) { - case 0x2: - case 0x3: - svga->bpp = 15; - break; - case 0xa: - if (ramdac->type == 2) - svga->bpp = 16; - else - svga->bpp = 15; - break; - case 0x8: - svga->bpp = 15; - break; - case 0x4: - case 0x9: - svga->bpp = 24; - break; - case 0xe: - if (ramdac->type == 1) - svga->bpp = 16; - else - svga->bpp = 24; - break; - case 0x5: - svga->bpp = 16; - break; - case 0x6: - if (ramdac->type == 1) - svga->bpp = 24; - else - svga->bpp = 16; - break; - case 0xc: - if (ramdac->type == 1) - svga->bpp = 15; - else - svga->bpp = 16; - break; - case 0x7: - if (ramdac->type == 1) - svga->bpp = 24; - else - svga->bpp = 32; - break; - case 0x0: - case 0x1: - default: - svga->bpp = 8; - break; - } - pclog("BPP = %i, val = %x, type = %i\n", svga->bpp, val >> 4, ramdac->type); + if (ramdac->type == 1 || ramdac->type == 2) { + switch (val) { + case 0xa0: + svga->bpp = 15; + break; + + case 0xc0: + case 0xe0: + svga->bpp = 16; + break; + + case 0x60: + case 0x90: + svga->bpp = 24; + break; + + case 0x00: + case 0x01: + case 0x10: + default: + svga->bpp = 8; + break; + } + } else { + switch (val >> 4) { + case 0x2: + case 0x3: + case 0xa: + case 0x8: + svga->bpp = 15; + break; + case 0x4: + case 0x9: + case 0xe: + svga->bpp = 24; + break; + case 0x5: + case 0x6: + case 0xc: + svga->bpp = 16; + break; + case 0x7: + svga->bpp = 32; + break; + case 0x0: + case 0x1: + default: + svga->bpp = 8; + break; + } + } } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d6ec2d72f..cd8d20ffa 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -111,7 +111,7 @@ video_cards[] = { { "et2000", &et2000_device }, { "et4000ax", &et4000_isa_device }, { "et4000w32", &et4000w32_device }, - { "et4000w32i", &et4000w32i_device }, + { "et4000w32i", &et4000w32i_isa_device }, { "vga", &vga_device }, { "v7_vga_1024i", &v7_vga_1024i_device }, { "wy700", &wy700_device }, @@ -160,6 +160,7 @@ video_cards[] = { { "voodoo3_2k_pci", &voodoo_3_2000_device }, { "voodoo3_3k_pci", &voodoo_3_3000_device }, { "mach64gx_vlb", &mach64gx_vlb_device }, + { "et4000w32i_vlb", &et4000w32i_vlb_device }, { "et4000w32p_vlb", &et4000w32p_cardex_vlb_device }, { "et4000w32p_nc_vlb", &et4000w32p_noncardex_vlb_device }, { "cl_gd5424_vlb", &gd5424_vlb_device },