diff --git a/src/ibm.h b/src/ibm.h index 06b2036..a3a5a5f 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -490,6 +490,7 @@ enum GFX_MACH64VT2, /*ATI Mach64 VT2*/ GFX_OLIVETTI_GO481, /*Olivetti GO481 PVGA1A*/ GFX_TGUI9400CXI, + GFX_CL_GD5430, /*Cirrus Logic CL-GD5430*/ GFX_MAX }; diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index dd5e483..71e0974 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -4,6 +4,7 @@ #include "device.h" #include "io.h" #include "mem.h" +#include "pci.h" #include "rom.h" #include "video.h" #include "vid_cl5429.h" @@ -11,9 +12,16 @@ #include "vid_svga_render.h" #include "vid_unk_ramdac.h" +enum +{ + CL_TYPE_GD5429 = 0, + CL_TYPE_GD5430 +}; + typedef struct gd5429_t { mem_mapping_t mmio_mapping; + mem_mapping_t linear_mapping; svga_t svga; @@ -24,6 +32,8 @@ typedef struct gd5429_t uint32_t vram_mask; + int type; + struct { uint16_t bg_col, fg_col; @@ -39,6 +49,12 @@ typedef struct gd5429_t uint8_t hidden_dac_reg; int dac_3c6_count; + + uint8_t pci_regs[256]; + uint8_t int_line; + int card; + + uint32_t lfb_base; } gd5429_t; void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p); @@ -93,6 +109,8 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) // pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr); break; + case 0x07: + svga->set_reset_disabled = svga->seqregs[7] & 1; case 0x17: gd5429_recalc_mapping(gd5429); break; @@ -296,7 +314,18 @@ uint8_t gd5429_in(uint16_t addr, void *p) switch (svga->crtcreg) { case 0x27: /*ID*/ - return 0x9c; /*GD5429*/ + switch (gd5429->type) + { + case CL_TYPE_GD5429: + return 0x9c; /*GD5429*/ + case CL_TYPE_GD5430: + return 0xa0; /*GD5430*/ + } + break; + case 0x28: /*Class ID*/ + if (gd5429->type == CL_TYPE_GD5430) + return 0xff; /*Standard CL-GD5430*/ + break; } return svga->crtc[svga->crtcreg]; } @@ -327,31 +356,73 @@ void gd5429_recalc_mapping(gd5429_t *gd5429) { svga_t *svga = &gd5429->svga; -// pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04); - switch (svga->gdcreg[6] & 0x0C) + if (PCI && !(gd5429->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&gd5429->linear_mapping); mem_mapping_disable(&gd5429->mmio_mapping); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + return; + } + +// pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04); + if (!(svga->seqregs[7] & 0xf0)) + { + mem_mapping_disable(&gd5429->linear_mapping); + switch (svga->gdcreg[6] & 0x0C) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_disable(&gd5429->mmio_mapping); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + if (svga->seqregs[0x17] & 0x04) + mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_mapping_disable(&gd5429->mmio_mapping); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_mapping_disable(&gd5429->mmio_mapping); + svga->banked_mask = 0x7fff; + break; + } + } + else + { + uint32_t base, size; + + if (gd5429->type <= CL_TYPE_GD5429) + { + base = (svga->seqregs[7] & 0xf0) << 16; + if (svga->gdcreg[0xb] & 0x20) + size = 1 * 1024 * 1024; + else + size = 2 * 1024 * 1024; + } + else if (PCI) + { + base = gd5429->lfb_base; + size = 4 * 1024 * 1024; + } + else + { + base = 128*1024*1024; + size = 4 * 1024 * 1024; + } + + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&gd5429->linear_mapping, base, size); if (svga->seqregs[0x17] & 0x04) mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_disable(&gd5429->mmio_mapping); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_disable(&gd5429->mmio_mapping); - svga->banked_mask = 0x7fff; - break; - } + else + mem_mapping_disable(&gd5429->mmio_mapping); + } } void gd5429_recalctimings(svga_t *svga) @@ -728,7 +799,7 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) case 0: if (svga->gdcreg[3] & 7) val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || (svga->seqregs[7] & 1))) + if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { if (writemask2 & 1) svga->vram[addr] = val; if (writemask2 & 2) svga->vram[addr | 0x1] = val; @@ -861,6 +932,49 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) } } +static void gd5429_writeb_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + gd5429_t *gd5429 = (gd5429_t *)svga->p; + +// pclog("gd5429_writeb : %08X %02X\n", addr, val); + if (svga->writemode < 4) + svga_write_linear(addr, val, svga); + else + gd5429_write_linear(addr, val & 0xff, gd5429); +} +static void gd5429_writew_linear(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + gd5429_t *gd5429 = (gd5429_t *)svga->p; + +// pclog("gd5429_writew : %08X %04X\n", addr, val); + if (svga->writemode < 4) + svga_writew_linear(addr, val, svga); + else + { + gd5429_write_linear(addr, val & 0xff, gd5429); + gd5429_write_linear(addr+1, val >> 8, gd5429); + } +} +static void gd5429_writel_linear(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + gd5429_t *gd5429 = (gd5429_t *)svga->p; + +// pclog("gd5429_writel : %08X %08X %i\n", addr, val, svga->writemode); + if (svga->writemode < 4) + svga_writel_linear(addr, val, svga); + else + { + gd5429_write_linear(addr, val & 0xff, gd5429); + gd5429_write_linear(addr+1, val >> 8, gd5429); + gd5429_write_linear(addr+2, val >> 16, gd5429); + gd5429_write_linear(addr+3, val >> 24, gd5429); + } +} + + void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; @@ -887,14 +1001,31 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) if (gd5429->blt.mode & 0x04) { // pclog("blt.mode & 0x04\n"); - mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l); - mem_mapping_set_p(&svga->mapping, gd5429); + if (!(svga->seqregs[7] & 0xf0)) + { + mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l); + mem_mapping_set_p(&svga->mapping, gd5429); + } + else + { + mem_mapping_set_handler(&gd5429->linear_mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l); + mem_mapping_set_p(&gd5429->linear_mapping, gd5429); + } + gd5429_recalc_mapping(gd5429); return; } else { - mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); - mem_mapping_set_p(&gd5429->svga.mapping, gd5429); + if (!(svga->seqregs[7] & 0xf0)) + { + mem_mapping_set_handler(&svga->mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel); + mem_mapping_set_p(&svga->mapping, gd5429); + } + else + { + mem_mapping_set_handler(&gd5429->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear); + mem_mapping_set_p(&gd5429->linear_mapping, svga); + } gd5429_recalc_mapping(gd5429); } } @@ -910,12 +1041,16 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) { if (gd5429->blt.mode & 0x80) { - if (gd5429->blt.mode & 0x10) - fatal("Here blt.mode & 0x10\n"); - src = (cpu_dat & 0x80) ? gd5429->blt.fg_col : gd5429->blt.bg_col; + if ((gd5429->blt.mode & 0x10) && (gd5429->blt.x_count & 1)) + src = (cpu_dat & 0x80) ? (gd5429->blt.fg_col >> 8) : (gd5429->blt.bg_col >> 8); + else + src = (cpu_dat & 0x80) ? gd5429->blt.fg_col : gd5429->blt.bg_col; mask = cpu_dat & 0x80; - cpu_dat <<= 1; - count--; + if (!(gd5429->blt.mode & 0x10) || (gd5429->blt.x_count & 1)) + { + cpu_dat <<= 1; + count--; + } } else { @@ -1043,8 +1178,18 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) { if (gd5429->blt.mode & 0x04) { - mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); - mem_mapping_set_p(&gd5429->svga.mapping, gd5429); + if (!(svga->seqregs[7] & 0xf0)) + { + mem_mapping_set_handler(&svga->mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel); + mem_mapping_set_p(&svga->mapping, gd5429); + } + else + { + mem_mapping_set_handler(&gd5429->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear); + mem_mapping_set_p(&gd5429->linear_mapping, svga); + } +// mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL); +// mem_mapping_set_p(&gd5429->svga.mapping, gd5429); gd5429_recalc_mapping(gd5429); } return; @@ -1175,7 +1320,90 @@ void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p) gd5429_start_blit(val, 32, p); } -void *gd5429_init() +static uint8_t cl_pci_read(int func, int addr, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + +// pclog("CL PCI read %08X\n", addr); + switch (addr) + { + case 0x00: return 0x13; /*Cirrus Logic*/ + case 0x01: return 0x10; + + case 0x02: + switch (gd5429->type) + { + case CL_TYPE_GD5430: + return 0xa0; + } + return 0xff; + case 0x03: return 0x00; + + case PCI_REG_COMMAND: + return gd5429->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x00; /*Supports VGA interface*/ + case 0x0b: return 0x03; + + case 0x10: return 0x08; /*Linear frame buffer address*/ + case 0x11: return 0x00; + case 0x12: return 0x00; + case 0x13: return gd5429->lfb_base >> 24; + + case 0x30: return gd5429->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return gd5429->pci_regs[0x32]; + case 0x33: return gd5429->pci_regs[0x33]; + + case 0x3c: return gd5429->int_line; + case 0x3d: return PCI_INTA; + } + return 0; +} + +static void cl_pci_write(int func, int addr, uint8_t val, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + +// pclog("cl_pci_write: addr=%02x val=%02x\n", addr, val); + switch (addr) + { + case PCI_REG_COMMAND: + gd5429->pci_regs[PCI_REG_COMMAND] = val & 0x23; + io_removehandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + if (val & PCI_COMMAND_IO) + io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + gd5429_recalc_mapping(gd5429); + break; + + case 0x13: + gd5429->lfb_base = val << 24; + gd5429_recalc_mapping(gd5429); + break; + + case 0x30: case 0x32: case 0x33: + gd5429->pci_regs[addr] = val; + if (gd5429->pci_regs[0x30] & 0x01) + { + uint32_t addr = (gd5429->pci_regs[0x32] << 16) | (gd5429->pci_regs[0x33] << 24); + mem_mapping_set_addr(&gd5429->bios_rom.mapping, addr, 0x8000); + } + else + mem_mapping_disable(&gd5429->bios_rom.mapping); + return; + + case 0x3c: + gd5429->int_line = val; + return; + } +} + +static void *cl_init(int type, char *fn) { gd5429_t *gd5429 = malloc(sizeof(gd5429_t)); svga_t *svga = &gd5429->svga; @@ -1184,8 +1412,10 @@ void *gd5429_init() vram_size = device_get_config_int("memory"); gd5429->vram_mask = (vram_size << 20) - 1; + + gd5429->type = type; - rom_init(&gd5429->bios_rom, "5429.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&gd5429->svga, gd5429, vram_size << 20, gd5429_recalctimings, @@ -1197,6 +1427,7 @@ void *gd5429_init() mem_mapping_set_p(&gd5429->svga.mapping, gd5429); mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, NULL, NULL, gd5429_mmio_write, NULL, NULL, NULL, 0, gd5429); + mem_mapping_add(&gd5429->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear, NULL, 0, svga); io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); @@ -1215,10 +1446,30 @@ void *gd5429_init() svga->seqregs[0x1d] = 0x30; svga->seqregs[0x1e] = 0x33; + if (PCI && type >= CL_TYPE_GD5430) + { + gd5429->card = pci_add(cl_pci_read, cl_pci_write, gd5429); + + gd5429->pci_regs[0x04] = 7; + + gd5429->pci_regs[0x30] = 0x00; + gd5429->pci_regs[0x32] = 0x0c; + gd5429->pci_regs[0x33] = 0x00; + } return gd5429; } + +static void *gd5429_init() +{ + return cl_init(CL_TYPE_GD5429, "5429.vbi"); +} +static void *gd5430_init() +{ + return cl_init(CL_TYPE_GD5430, "gd5430/pci.bin"); +} + static int gd5429_available() { return rom_present("5429.vbi"); @@ -1293,3 +1544,16 @@ device_t gd5429_device = gd5429_add_status_info, gd5429_config }; + +device_t gd5430_device = +{ + "Cirrus Logic GD5430", + 0, + gd5430_init, + gd5429_close, + gd5429_available, + gd5429_speed_changed, + gd5429_force_redraw, + gd5429_add_status_info, + gd5429_config +}; diff --git a/src/vid_cl5429.h b/src/vid_cl5429.h index b4a159c..9537552 100644 --- a/src/vid_cl5429.h +++ b/src/vid_cl5429.h @@ -1 +1,2 @@ extern device_t gd5429_device; +extern device_t gd5430_device; diff --git a/src/vid_svga.c b/src/vid_svga.c index b98f460..1780ae3 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -824,7 +824,7 @@ void svga_write(uint32_t addr, uint8_t val, void *p) case 0: if (svga->gdcreg[3] & 7) val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) + if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { if (writemask2 & 1) svga->vram[addr] = val; if (writemask2 & 2) svga->vram[addr | 0x1] = val; @@ -873,7 +873,7 @@ void svga_write(uint32_t addr, uint8_t val, void *p) } break; case 2: - if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); @@ -1083,7 +1083,7 @@ void svga_write_linear(uint32_t addr, uint8_t val, void *p) case 0: if (svga->gdcreg[3] & 7) val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) + if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { if (writemask2 & 1) svga->vram[addr] = val; if (writemask2 & 2) svga->vram[addr | 0x1] = val; @@ -1132,7 +1132,7 @@ void svga_write_linear(uint32_t addr, uint8_t val, void *p) } break; case 2: - if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); diff --git a/src/vid_svga.h b/src/vid_svga.h index 5c89483..db5f817 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -46,6 +46,8 @@ typedef struct svga_t int chain4, chain2_write, chain2_read; uint8_t writemask; uint32_t charseta, charsetb; + + int set_reset_disabled; uint8_t egapal[16]; uint32_t pallook[256]; diff --git a/src/video.c b/src/video.c index 0bc4476..c75ca33 100644 --- a/src/video.c +++ b/src/video.c @@ -74,6 +74,7 @@ static VIDEO_CARD video_cards[] = {"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"CGA", "cga", &cga_device, GFX_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"Cirrus Logic CL-GD5429", "cl_gd5429", &gd5429_device, GFX_CL_GD5429, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, + {"Cirrus Logic CL-GD5430", "cl_gd5430", &gd5430_device, GFX_CL_GD5430, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32", &et4000w32p_device, GFX_ET4000W32, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, {"Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000", &s3_virge_device, GFX_VIRGE, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, {"EGA", "ega", &ega_device, GFX_EGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},