From 68a2d8cb3c91a992882c2f3de6f9e30fe04563a0 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 1 Feb 2020 16:30:34 +0000 Subject: [PATCH] Added Cirrus Logic GD5428 emulation. As part of this, added emulation of the GD5428-based IBM 1MB SVGA Adapter/A, along with support for external graphics cards on MCA platforms, adding the ability to override the onboard VGA controller. --- src/hdd_esdi.c | 2 +- src/ibm.h | 4 +- src/mca.c | 18 +++- src/mca.h | 3 +- src/model.c | 14 +-- src/ps2_mca.c | 15 ++- src/sound_adlib.c | 2 +- src/sound_sb.c | 4 +- src/vid_cl5429.c | 257 ++++++++++++++++++++++++++++++++++++++++++---- src/vid_cl5429.h | 2 + src/vid_vga.c | 30 ++++++ src/vid_vga.h | 6 ++ src/video.c | 23 ++++- src/wx-config.c | 5 +- 14 files changed, 342 insertions(+), 43 deletions(-) diff --git a/src/hdd_esdi.c b/src/hdd_esdi.c index 6eb239a..04c4317 100644 --- a/src/hdd_esdi.c +++ b/src/hdd_esdi.c @@ -917,7 +917,7 @@ static void *esdi_init() timer_add(&esdi->callback_timer, esdi_callback, esdi, 0); - mca_add(esdi_mca_read, esdi_mca_write, esdi); + mca_add(esdi_mca_read, esdi_mca_write, NULL, esdi); esdi->pos_regs[0] = 0xff; esdi->pos_regs[1] = 0xdd; diff --git a/src/ibm.h b/src/ibm.h index 661d950..f801989 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -165,7 +165,7 @@ int driveempty[2]; #define PCJR (romset == ROM_IBMPCJR) int GAMEBLASTER, GUS, SSI2001, voodoo_enabled; -extern int AMSTRAD, AT, is386, PCI, TANDY; +extern int AMSTRAD, AT, is386, PCI, TANDY, MCA; enum { @@ -304,6 +304,8 @@ enum GFX_EGAWONDER800, /*ATI EGA Wonder 800+*/ GFX_MYSTIQUE, /*Matrox Mystique*/ GFX_AVGA2, /*Acumos AVGA2 / Cirrus Logic CL-GD5402*/ + GFX_CL_GD5428, /*Cirrus Logic CL-GD5428*/ + GFX_IBM_GD5428, /*IBM 1MB SVGA Adapter/A*/ GFX_MAX }; diff --git a/src/mca.c b/src/mca.c index ebd8ccb..11f8268 100644 --- a/src/mca.c +++ b/src/mca.c @@ -6,6 +6,7 @@ void (*mca_card_write[8])(int addr, uint8_t val, void *priv); uint8_t (*mca_card_read[8])(int addr, void *priv); +void (*mca_card_reset[8])(void *priv); void *mca_priv[8]; static int mca_index; static int mca_nr_cards; @@ -14,10 +15,13 @@ void mca_init(int nr_cards) { int c; + MCA = 1; + for (c = 0; c < 8; c++) { mca_card_read[c] = NULL; mca_card_write[c] = NULL; + mca_card_reset[c] = NULL; mca_priv[c] = NULL; } @@ -47,7 +51,18 @@ void mca_write(uint16_t port, uint8_t val) mca_card_write[mca_index](port, val, mca_priv[mca_index]); } -void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv) +void mca_reset(void) +{ + int c; + + for (c = 0; c < 8; c++) + { + if (mca_card_reset[c]) + mca_card_reset[c](mca_priv[c]); + } +} + +void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void (*reset)(void *priv), void *priv) { int c; @@ -57,6 +72,7 @@ void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint { mca_card_read[c] = read; mca_card_write[c] = write; + mca_card_reset[c] = reset; mca_priv[c] = priv; return; } diff --git a/src/mca.h b/src/mca.h index cf9361f..a298d24 100644 --- a/src/mca.h +++ b/src/mca.h @@ -1,5 +1,6 @@ void mca_init(int nr_cards); -void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv); +void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void (*reset)(void *priv), void *priv); void mca_set_index(int index); uint8_t mca_read(uint16_t port); void mca_write(uint16_t port, uint8_t val); +void mca_reset(void); diff --git a/src/model.c b/src/model.c index 5d582f5..669fb37 100644 --- a/src/model.c +++ b/src/model.c @@ -127,7 +127,7 @@ void xt_zenith_init(); void at_mvp3_init(); int model; -int AMSTRAD, AT, PCI, TANDY; +int AMSTRAD, AT, PCI, TANDY, MCA; MODEL models[] = { @@ -174,7 +174,7 @@ MODEL models[] = {"[286] IBM AT", ROM_IBMAT, "ibmat", { {"", cpus_ibmat}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, ibm_at_init, NULL}, {"[286] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", { {"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2, 512,16384, 512, ps1_m2011_init, NULL}, {"[286] IBM PS/2 Model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2, 1, 16, 1, ps2_m30_286_init, NULL}, - {"[286] IBM PS/2 Model 50", ROM_IBMPS2_M50, "ibmps2_m50", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 16, 1, ps2_model_50_init, NULL}, + {"[286] IBM PS/2 Model 50", ROM_IBMPS2_M50, "ibmps2_m50", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 16, 1, ps2_model_50_init, NULL}, {"[286] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", { {"", cpus_ibmxt286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, ibm_at_init, NULL}, {"[286] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 512, 2048, 128, at_scat_init, NULL}, {"[286] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 5, 1, at_scat_init, NULL}, @@ -190,21 +190,21 @@ MODEL models[] = {"[386SX] DTK 386SX clone", ROM_DTK386, "dtk386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512,16384, 128, at_neat_init, NULL}, {"[386SX] Epson PC AX3", ROM_EPSON_PCAX3, "epson_pcax3", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, at_init, NULL}, {"[386SX] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, ps1_m2121_init, NULL}, - {"[386SX] IBM PS/2 Model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 8, 1, ps2_model_55sx_init, NULL}, + {"[386SX] IBM PS/2 Model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 8, 1, ps2_model_55sx_init, NULL}, {"[386SX] KMX-C-02", ROM_KMXC02, "kmxc02", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT, 512,16384, 512, at_scatsx_init, NULL}, {"[386SX] Packard Bell Legend 300SX", ROM_PB_L300SX, "pb_l300sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, pb_l300sx_init, NULL}, {"[386DX] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL}, {"[386DX] Compaq Deskpro 386", ROM_DESKPRO_386, "deskpro386", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT, 1, 15, 1, deskpro386_init, NULL}, - {"[386DX] IBM PS/2 Model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, - {"[386DX] IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 12, 1, ps2_model_80_init, NULL}, + {"[386DX] IBM PS/2 Model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, + {"[386DX] IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 12, 1, ps2_model_80_init, NULL}, {"[386DX] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL}, {"[486] AMI 486 clone", ROM_AMI486, "ami486", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_ali1429_init, NULL}, {"[486] AMI WinBIOS 486", ROM_WIN486, "win486", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_ali1429_init, NULL}, {"[486] Award SiS 496/497", ROM_SIS496, "sis496", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_HAS_IDE, 1, 256, 1, at_sis496_init, NULL}, {"[486] Elonex PC-425X", ROM_ELX_PC425X, "elx_pc425x", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_sl82c460_init, NULL}, - {"[486] IBM PS/2 Model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, + {"[486] IBM PS/2 Model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL}, {"[486] Packard Bell PB410A", ROM_PB410A, "pb410a", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 64, 1, at_pb410a_init, NULL}, {"[Socket 4] Intel Premiere/PCI", ROM_REVENGE, "revenge", { {"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_batman_init, NULL}, @@ -788,7 +788,7 @@ void at_mvp3_init() void model_init() { pclog("Initting as %s\n", model_getname()); - AMSTRAD = AT = PCI = TANDY = 0; + AMSTRAD = AT = PCI = TANDY = MCA = 0; ide_set_bus_master(NULL, NULL, NULL, NULL); models[model].init(); diff --git a/src/ps2_mca.c b/src/ps2_mca.c index 1e8b77f..f510e46 100644 --- a/src/ps2_mca.c +++ b/src/ps2_mca.c @@ -9,6 +9,7 @@ #include "ps2_nvr.h" #include "rom.h" #include "serial.h" +#include "vid_vga.h" #include "x86.h" //static uint8_t ps2_92, ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190; @@ -652,6 +653,8 @@ static void ps2_mca_write(uint16_t port, uint8_t val, void *p) ps2.setup = val; break; case 0x96: + if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) + mca_reset(); ps2.adapter_setup = val; mca_set_index(val & 7); break; @@ -671,7 +674,15 @@ static void ps2_mca_write(uint16_t port, uint8_t val, void *p) if (!(ps2.setup & PS2_SETUP_IO)) ps2.planar_write(port, val); else if (!(ps2.setup & PS2_SETUP_VGA)) + { + if (mb_vga) + { + vga_disable(mb_vga); + if (val & 1) + vga_enable(mb_vga); + } ps2.pos_vga = val; + } else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) mca_write(port, val); break; @@ -1018,7 +1029,7 @@ void ps2_mca_board_model_70_type34_init(int is_type4) break; } - mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL); + mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL, NULL); mem_mapping_add(&ps2.expansion_mapping, 0x800000, (mem_size - 8192)*1024, @@ -1119,7 +1130,7 @@ void ps2_mca_board_model_80_type2_init() break; } - mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL); + mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL, NULL); mem_mapping_add(&ps2.expansion_mapping, 0x400000, (mem_size - 4096)*1024, diff --git a/src/sound_adlib.c b/src/sound_adlib.c index 0be5259..da3de33 100644 --- a/src/sound_adlib.c +++ b/src/sound_adlib.c @@ -76,7 +76,7 @@ void *adlib_mca_init() adlib_t *adlib = adlib_init(); io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); - mca_add(adlib_mca_read, adlib_mca_write, adlib); + mca_add(adlib_mca_read, adlib_mca_write, NULL, adlib); adlib->pos_regs[0] = 0xd7; adlib->pos_regs[1] = 0x70; diff --git a/src/sound_sb.c b/src/sound_sb.c index 0fb5d48..9766291 100644 --- a/src/sound_sb.c +++ b/src/sound_sb.c @@ -999,7 +999,7 @@ void *sb_mcv_init() sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sound_add_handler(sb_get_buffer_sb2, sb); /* I/O handlers activated in sb_mcv_write */ - mca_add(sb_mcv_read, sb_mcv_write, sb); + mca_add(sb_mcv_read, sb_mcv_write, NULL, sb); sb->pos_regs[0] = 0x84; sb->pos_regs[1] = 0x50; return sb; @@ -1124,7 +1124,7 @@ void *sb_pro_mcv_init() sound_add_handler(sb_get_buffer_sbpro, sb); /* I/O handlers activated in sb_pro_mcv_write */ - mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb); + mca_add(sb_pro_mcv_read, sb_pro_mcv_write, NULL, sb); sb->pos_regs[0] = 0x03; sb->pos_regs[1] = 0x51; diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index f94fddf..8dafa52 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -4,6 +4,7 @@ #include "cpu.h" #include "device.h" #include "io.h" +#include "mca.h" #include "mem.h" #include "pci.h" #include "rom.h" @@ -11,11 +12,13 @@ #include "vid_cl5429.h" #include "vid_svga.h" #include "vid_svga_render.h" +#include "vid_vga.h" #include "vid_unk_ramdac.h" enum { CL_TYPE_AVGA2 = 0, + CL_TYPE_GD5428, CL_TYPE_GD5429, CL_TYPE_GD5430, CL_TYPE_GD5434 @@ -25,6 +28,10 @@ enum #define BLIT_DEPTH_16 1 #define BLIT_DEPTH_32 3 +#define CL_GD5428_SYSTEM_BUS_MCA 5 +#define CL_GD5428_SYSTEM_BUS_VESA 6 +#define CL_GD5428_SYSTEM_BUS_ISA 7 + #define CL_GD5429_SYSTEM_BUS_VESA 5 #define CL_GD5429_SYSTEM_BUS_ISA 7 @@ -50,7 +57,8 @@ typedef struct gd5429_t struct { - uint32_t bg_col, fg_col; + uint32_t bg_col, fg_col; + uint16_t trans_col, trans_mask; uint16_t width, height; uint16_t dst_pitch, src_pitch; uint32_t dst_addr, src_addr; @@ -60,6 +68,9 @@ typedef struct gd5429_t uint16_t width_backup, height_internal; int x_count, y_count; int depth; + + int mem_word_sel; + uint16_t mem_word_save; } blt; uint8_t hidden_dac_reg; @@ -69,6 +80,9 @@ typedef struct gd5429_t uint8_t int_line; int card; + uint8_t pos_regs[8]; + svga_t *mb_vga; + uint32_t lfb_base; int mmio_vram_overlap; @@ -76,6 +90,8 @@ typedef struct gd5429_t uint8_t sr10_read, sr11_read; uint8_t latch_ext[4]; + + int vidsys_ena; } gd5429_t; #define GRB_X8_ADDRESSING (1 << 1) @@ -97,6 +113,8 @@ void gd5429_recalc_mapping(gd5429_t *gd5429); uint8_t gd5429_read_linear(uint32_t addr, void *p); +static void ibm_gd5428_mapping_update(gd5429_t *gd5429); + void gd5429_out(uint16_t addr, uint8_t val, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; @@ -110,6 +128,14 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) switch (addr) { + case 0x3c3: + if (MCA) + { + gd5429->vidsys_ena = val & 1; + ibm_gd5428_mapping_update(gd5429); + } + break; + case 0x3c4: svga->seqaddr = val; break; @@ -206,7 +232,7 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) if (svga->gdcaddr > 8) { svga->gdcreg[svga->gdcaddr & 0x3f] = val; - if (gd5429->type < CL_TYPE_GD5429 && (svga->gdcaddr > 0xb)) + if (gd5429->type < CL_TYPE_GD5428 && (svga->gdcaddr > 0xb)) return; switch (svga->gdcaddr) { @@ -296,7 +322,24 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) case 0x31: gd5429_mmio_write(0xb8040, val, gd5429); break; - } + + case 0x34: + if (gd5429->type <= CL_TYPE_GD5428) + gd5429->blt.trans_col = (gd5429->blt.trans_col & 0xff00) | val; + break; + case 0x35: + if (gd5429->type <= CL_TYPE_GD5428) + gd5429->blt.trans_col = (gd5429->blt.trans_col & 0x00ff) | (val << 8); + break; + case 0x36: + if (gd5429->type <= CL_TYPE_GD5428) + gd5429->blt.trans_mask = (gd5429->blt.trans_mask & 0xff00) | val; + break; + case 0x37: + if (gd5429->type <= CL_TYPE_GD5428) + gd5429->blt.trans_mask = (gd5429->blt.trans_mask & 0x00ff) | (val << 8); + break; + } return; } break; @@ -337,6 +380,11 @@ uint8_t gd5429_in(uint16_t addr, void *p) switch (addr) { + case 0x3c3: + if (MCA) + return gd5429->vidsys_ena; + break; + case 0x3c4: if ((svga->seqaddr & 0x1f) == 0x10) return (svga->seqaddr & 0x1f) | gd5429->sr10_read; @@ -355,11 +403,20 @@ uint8_t gd5429_in(uint16_t addr, void *p) return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f; case 0x17: - if (gd5429->type < CL_TYPE_GD5429) + if (gd5429->type < CL_TYPE_GD5428) break; temp = svga->seqregs[0x17]; temp &= ~(7 << 3); - if (gd5429->type == CL_TYPE_GD5429) + if (gd5429->type == CL_TYPE_GD5428) + { + if (MCA) + temp |= (CL_GD5428_SYSTEM_BUS_MCA << 3); + else if (has_vlb) + temp |= (CL_GD5428_SYSTEM_BUS_VESA << 3); + else + temp |= (CL_GD5428_SYSTEM_BUS_ISA << 3); + } + else if (gd5429->type == CL_TYPE_GD5429) { if (has_vlb) temp |= (CL_GD5429_SYSTEM_BUS_VESA << 3); @@ -411,6 +468,8 @@ uint8_t gd5429_in(uint16_t addr, void *p) { case CL_TYPE_AVGA2: return 0x18; /*AVGA2*/ + case CL_TYPE_GD5428: + return 0x98; /*GD5428*/ case CL_TYPE_GD5429: return 0x9c; /*GD5429*/ case CL_TYPE_GD5430: @@ -453,7 +512,8 @@ void gd5429_recalc_mapping(gd5429_t *gd5429) { svga_t *svga = &gd5429->svga; - if (PCI && gd5429->type >= CL_TYPE_GD5430 && !(gd5429->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + if ((PCI && gd5429->type >= CL_TYPE_GD5430 && !(gd5429->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) || + (MCA && (!(gd5429->pos_regs[2] & 0x01) || !gd5429->vidsys_ena))) { mem_mapping_disable(&svga->mapping); mem_mapping_disable(&gd5429->linear_mapping); @@ -487,7 +547,7 @@ void gd5429_recalc_mapping(gd5429_t *gd5429) gd5429->mmio_vram_overlap = 1; break; } - if (svga->seqregs[0x17] & 0x04) + if (gd5429->type >= CL_TYPE_GD5429 && svga->seqregs[0x17] & 0x04) mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100); else mem_mapping_disable(&gd5429->mmio_mapping); @@ -516,7 +576,7 @@ void gd5429_recalc_mapping(gd5429_t *gd5429) } mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&gd5429->linear_mapping, base, size); - if (svga->seqregs[0x17] & 0x04) + if (gd5429->type >= CL_TYPE_GD5429 && svga->seqregs[0x17] & 0x04) mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100); else mem_mapping_disable(&gd5429->mmio_mapping); @@ -1448,9 +1508,18 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) } //pclog("%02X %02X\n", dst, mask); - if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask && - !((gd5429->blt.mode & 0x08) && !mask)) - svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst; + if (gd5429->type <= CL_TYPE_GD5428) + { + if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask && + (!(gd5429->blt.mode & 0x08) || (dst & gd5429->blt.trans_mask) != gd5429->blt.trans_col)) + svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst; + } + else + { + if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask && + !((gd5429->blt.mode & 0x08) && !mask)) + svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst; + } gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1); @@ -1708,14 +1777,22 @@ static uint32_t gd5429_mmio_readl(uint32_t addr, void *p) void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p) { + gd5429_t *gd5429 = (gd5429_t *)p; + // pclog("gd5429_blt_write_w %08X %08X\n", addr, val); - gd5429_start_blit(val, 16, p); + if (!gd5429->blt.mem_word_sel) + gd5429->blt.mem_word_save = val; + else + gd5429_start_blit(gd5429->blt.mem_word_save | (val << 16), 32, p); + gd5429->blt.mem_word_sel = !gd5429->blt.mem_word_sel; + } void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; - + + gd5429->blt.mem_word_sel = 0; // pclog("gd5429_blt_write_l %08X %08X %04X %04X\n", addr, val, ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00), ((val >> 24) & 0x00ff) | ((val >> 8) & 0xff00)); if ((gd5429->blt.mode & 0x84) == 0x84) { @@ -1728,6 +1805,78 @@ void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p) gd5429_start_blit(val, 32, p); } +uint8_t ibm_gd5428_mca_read(int port, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + +// pclog("gd5429_pro_mcv_read: port=%04x %02x %04x:%04x\n", port, gd5429->pos_regs[port & 7], CS, cpu_state.pc); + + return gd5429->pos_regs[port & 7]; +} + +static void ibm_gd5428_mapping_update(gd5429_t *gd5429) +{ + gd5429_recalc_mapping(gd5429); + + io_removehandler(0x03a0, 0x0023, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + io_removehandler(0x03c4, 0x001c, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + if ((gd5429->pos_regs[2] & 0x01) && gd5429->vidsys_ena) + { +// pclog(" GD5429 enable registers\n"); + io_sethandler(0x03c0, 0x0003, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + io_sethandler(0x03c4, 0x001c, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + if (!(gd5429->svga.miscout & 1)) + io_sethandler(0x03a0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + gd5429->svga.override = 0; + if (mb_vga) + svga_set_override(mb_vga, 1); + } + else + { +// pclog(" GD5429 disable registers\n"); + gd5429->svga.override = 1; + if (mb_vga) + svga_set_override(mb_vga, 0); + } +} + +void ibm_gd5428_mca_write(int port, uint8_t val, void *p) +{ +// svga_set_override(voodoo->svga, val & 1); + gd5429_t *gd5429 = (gd5429_t *)p; + +// pclog("gd5429_pro_mcv_write: port=%04x val=%02x\n", port, val); + + if (port < 0x102) + return; + gd5429->pos_regs[port & 7] = val; + + if ((port & 7) == 2) + { + mem_mapping_disable(&gd5429->bios_rom.mapping); + io_removehandler(0x03c3, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + if (gd5429->pos_regs[2] & 0x01) + { +// pclog("Enable BIOS mapping\n"); + mem_mapping_enable(&gd5429->bios_rom.mapping); + io_sethandler(0x03c3, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + } +// else +// pclog("Disable BIOS mapping\n"); + } + + ibm_gd5428_mapping_update(gd5429); +} + +static void ibm_gd5428_mca_reset(void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + +// pclog("ibm_gd5428_mca_reset\n"); + gd5429->vidsys_ena = 0; + ibm_gd5428_mca_write(0x102, 0, gd5429); +} + static uint8_t cl_pci_read(int func, int addr, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; @@ -1813,14 +1962,17 @@ static void cl_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *cl_init(int type, char *fn, int pci_card) +static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size) { gd5429_t *gd5429 = malloc(sizeof(gd5429_t)); svga_t *svga = &gd5429->svga; int vram_size; memset(gd5429, 0, sizeof(gd5429_t)); - vram_size = device_get_config_int("memory"); + if (force_vram_size) + vram_size = force_vram_size; + else + vram_size = device_get_config_int("memory"); if (vram_size >= 256) gd5429->vram_mask = (vram_size << 10) - 1; else @@ -1849,6 +2001,8 @@ static void *cl_init(int type, char *fn, int pci_card) io_sethandler(0x46e8, 0x0002, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); svga->decode_mask = svga->vram_mask; } + if (type == CL_TYPE_GD5428) + svga->decode_mask = svga->vram_mask; svga->hwcursor.yoff = 32; svga->hwcursor.xoff = 0; @@ -1888,37 +2042,70 @@ static void *cl_init(int type, char *fn, int pci_card) static void *avga2_init() { - return cl_init(CL_TYPE_AVGA2, "avga2vram.vbi", -1); + return cl_init(CL_TYPE_AVGA2, "avga2vram.vbi", -1, 0); } static void *avga2_cbm_sl386sx_init() { - return cl_init(CL_TYPE_AVGA2, "cbm_sl386sx25/c000.rom", -1); + return cl_init(CL_TYPE_AVGA2, "cbm_sl386sx25/c000.rom", -1, 0); +} +static void *gd5428_init() +{ + return cl_init(CL_TYPE_GD5428, "Machspeed_VGA_GUI_2100_VLB.vbi", -1, 0); +} +static void *ibm_gd5428_init() +{ + gd5429_t *gd5429; + svga_t *mb_vga = svga_get_pri(); + + gd5429 = cl_init(CL_TYPE_GD5428, "SVGA141.ROM", -1, 1); /*Only supports 1MB*/ + gd5429->mb_vga = mb_vga; + + mca_add(ibm_gd5428_mca_read, ibm_gd5428_mca_write, ibm_gd5428_mca_reset, gd5429); + gd5429->pos_regs[0] = 0x7b; + gd5429->pos_regs[1] = 0x91; + gd5429->pos_regs[2] = 0; + + gd5429_recalc_mapping(gd5429); + io_removehandler(0x03a0, 0x0040, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + gd5429->svga.override = 1; + mem_mapping_disable(&gd5429->bios_rom.mapping); + io_sethandler(0x46e8, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + + return gd5429; } static void *gd5429_init() { - return cl_init(CL_TYPE_GD5429, "5429.vbi", -1); + return cl_init(CL_TYPE_GD5429, "5429.vbi", -1, 0); } static void *gd5430_init() { - return cl_init(CL_TYPE_GD5430, "gd5430/pci.bin", -1); + return cl_init(CL_TYPE_GD5430, "gd5430/pci.bin", -1, 0); } static void *gd5430_pb570_init() { - return cl_init(CL_TYPE_GD5430, "pb570/gd5430.bin", 8); + return cl_init(CL_TYPE_GD5430, "pb570/gd5430.bin", 8, 0); } static void *gd5434_init() { - return cl_init(CL_TYPE_GD5434, "gd5434.bin", -1); + return cl_init(CL_TYPE_GD5434, "gd5434.bin", -1, 0); } static void *gd5434_pb520r_init() { - return cl_init(CL_TYPE_GD5434, "pb520r/gd5434.bin", 3); + return cl_init(CL_TYPE_GD5434, "pb520r/gd5434.bin", 3, 0); } static int avga2_available() { return rom_present("avga2vram.vbi"); } +static int gd5428_available() +{ + return rom_present("Machspeed_VGA_GUI_2100_VLB.vbi"); +} +static int ibm_gd5428_available() +{ + return rom_present(/*"FILE.ROM"*/"SVGA141.ROM"); +} static int gd5429_available() { return rom_present("5429.vbi"); @@ -2068,6 +2255,32 @@ device_t avga2_cbm_sl386sx_device = avga2_config }; +device_t gd5428_device = +{ + "Cirrus Logic GD5428", + 0, + gd5428_init, + gd5429_close, + gd5428_available, + gd5429_speed_changed, + gd5429_force_redraw, + gd5429_add_status_info, + gd5429_config +}; + +device_t ibm_gd5428_device = +{ + "IBM 1MB SVGA Adapter/A (Cirrus Logic GD5428)", + DEVICE_MCA, + ibm_gd5428_init, + gd5429_close, + ibm_gd5428_available, + gd5429_speed_changed, + gd5429_force_redraw, + gd5429_add_status_info, + NULL +}; + device_t gd5429_device = { "Cirrus Logic GD5429", diff --git a/src/vid_cl5429.h b/src/vid_cl5429.h index 7ba0941..1dc6ef0 100644 --- a/src/vid_cl5429.h +++ b/src/vid_cl5429.h @@ -1,5 +1,7 @@ extern device_t avga2_device; extern device_t avga2_cbm_sl386sx_device; +extern device_t gd5428_device; +extern device_t ibm_gd5428_device; extern device_t gd5429_device; extern device_t gd5430_device; extern device_t gd5430_pb570_device; diff --git a/src/vid_vga.c b/src/vid_vga.c index 241166f..64bd67c 100644 --- a/src/vid_vga.c +++ b/src/vid_vga.c @@ -9,6 +9,8 @@ #include "vid_svga.h" #include "vid_vga.h" +svga_t *mb_vga = NULL; + typedef struct vga_t { svga_t svga; @@ -84,6 +86,30 @@ uint8_t vga_in(uint16_t addr, void *p) return temp; } +void vga_disable(void *p) +{ + vga_t *vga = (vga_t *)p; + svga_t *svga = &vga->svga; + +// pclog("vga_disable\n"); + io_removehandler(0x03a0, 0x0040, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + mem_mapping_disable(&svga->mapping); +} + +void vga_enable(void *p) +{ + vga_t *vga = (vga_t *)p; + svga_t *svga = &vga->svga; + +// pclog("vga_enable\n"); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + if (!(svga->miscout & 1)) + io_sethandler(0x03a0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + + mem_mapping_enable(&svga->mapping); +} + + void *vga_init() { vga_t *vga = malloc(sizeof(vga_t)); @@ -122,6 +148,8 @@ void *ps1vga_init() vga->svga.bpp = 8; vga->svga.miscout = 1; + mb_vga = &vga->svga; + return vga; } @@ -134,6 +162,8 @@ void vga_close(void *p) { vga_t *vga = (vga_t *)p; + mb_vga = NULL; + svga_close(&vga->svga); free(vga); diff --git a/src/vid_vga.h b/src/vid_vga.h index 3bf9459..cf58f72 100644 --- a/src/vid_vga.h +++ b/src/vid_vga.h @@ -1,2 +1,8 @@ extern device_t vga_device; extern device_t ps1vga_device; + +void vga_disable(void *p); +void vga_enable(void *p); + +struct svga_t; +extern struct svga_t *mb_vga; diff --git a/src/video.c b/src/video.c index 0105b48..d159715 100644 --- a/src/video.c +++ b/src/video.c @@ -90,6 +90,7 @@ static VIDEO_CARD video_cards[] = {"ATI VGA Charger (ATI-28800)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, {"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"CGA", "cga", &cga_device, GFX_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + {"Cirrus Logic CL-GD5428", "cl_gd5428", &gd5428_device, GFX_CL_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"Cirrus Logic CL-GD5429", "cl_gd5429", &gd5429_device, GFX_CL_GD5429, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"Cirrus Logic CL-GD5430", "cl_gd5430", &gd5430_device, GFX_CL_GD5430, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"Cirrus Logic CL-GD5434", "cl_gd5434", &gd5434_device, GFX_CL_GD5434, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, @@ -99,6 +100,7 @@ static VIDEO_CARD video_cards[] = {"EGA", "ega", &ega_device, GFX_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"Hercules", "hercules", &hercules_device, GFX_HERCULES, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + {"IBM 1MB SVGA Adapter/A (CL GD5428)", "ibm1mbsvga", &ibm_gd5428_device, GFX_IBM_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"Image Manager 1024", "im1024", &im1024_device, GFX_IM1024, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"Matrox Mystique", "mystique", &mystique_device, GFX_MYSTIQUE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, {"MDA", "mda", &mda_device, GFX_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, @@ -218,13 +220,17 @@ device_t *video_card_getdevice(int card, int romset) case ROM_IBMPS1_2011: case ROM_IBMPS2_M30_286: + return &ps1vga_device; + case ROM_IBMPS2_M50: case ROM_IBMPS2_M55SX: case ROM_IBMPS2_M70_TYPE3: case ROM_IBMPS2_M70_TYPE4: case ROM_IBMPS2_M80: - return &ps1vga_device; - + if (card == GFX_BUILTIN) + return &ps1vga_device; + break; + case ROM_IBMPS1_2121: return &ps1_m2121_svga_device; @@ -588,12 +594,16 @@ void video_updatetiming() case ROM_IBMPS1_2011: case ROM_IBMPS2_M30_286: + timing = &timing_vga; + break; + case ROM_IBMPS2_M50: case ROM_IBMPS2_M55SX: case ROM_IBMPS2_M70_TYPE3: case ROM_IBMPS2_M70_TYPE4: case ROM_IBMPS2_M80: - timing = &timing_vga; + if (gfxcard == GFX_BUILTIN) + timing = &timing_vga; break; case ROM_IBMPS1_2121: @@ -776,13 +786,18 @@ void video_init() case ROM_IBMPS1_2011: case ROM_IBMPS2_M30_286: + device_add(&ps1vga_device); + return; + case ROM_IBMPS2_M50: case ROM_IBMPS2_M55SX: case ROM_IBMPS2_M70_TYPE3: case ROM_IBMPS2_M70_TYPE4: case ROM_IBMPS2_M80: device_add(&ps1vga_device); - return; + if (gfxcard == GFX_BUILTIN) + return; + break; case ROM_IBMPS1_2121: device_add(&ps1_m2121_svga_device); diff --git a/src/wx-config.c b/src/wx-config.c index 09fea3e..cd24749 100644 --- a/src/wx-config.c +++ b/src/wx-config.c @@ -147,7 +147,10 @@ static void recalc_vid_list(void* hdlg, int model, int force_builtin_video) break; if (video_card_available(c) && gfx_present[video_new_to_old(c)] && - ((models[model].flags & MODEL_PCI) || !(video_card_getdevice(c, romset)->flags & DEVICE_PCI))) + ((models[model].flags & MODEL_PCI) || !(video_card_getdevice(c, romset)->flags & DEVICE_PCI)) && + ((models[model].flags & MODEL_MCA) || !(video_card_getdevice(c, romset)->flags & DEVICE_MCA)) && + (!(models[model].flags & MODEL_MCA) || (video_card_getdevice(c, romset)->flags & DEVICE_MCA)) + ) { wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)s); if (video_new_to_old(c) == gfxcard && !found_card)