diff --git a/src/Makefile.am b/src/Makefile.am index 3a83dae..89e5664 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,7 +38,7 @@ jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c joysti keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c laserxt.c lpt.c lpt_dac.c lpt_dss.c \ mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c mvp3.c \ neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \ -ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c \ +ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scamp.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c \ scsi_zip.c serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c \ sound_cms.c sound_emu8k.c sound_gus.c sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c \ sound_sb.c sound_sb_dsp.c sound_sn76489.c sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 3f8ce14..61af689 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -24,7 +24,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \ mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \ mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \ - piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o \ + piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \ scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \ sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network index a0e2415..60dd89c 100644 --- a/src/Makefile.mingw-wx-sdl2-network +++ b/src/Makefile.mingw-wx-sdl2-network @@ -24,7 +24,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \ mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \ mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \ - piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o \ + piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \ scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \ sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ diff --git a/src/ibm.h b/src/ibm.h index e59b322..370ccbf 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -252,7 +252,8 @@ enum ROM_PPC512, ROM_BULL_MICRAL_45, ROM_FIC_VA503P, - + ROM_CBM_SL386SX25, + ROM_MAX }; diff --git a/src/mem_bios.c b/src/mem_bios.c index 8f787ea..66d0f38 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -1008,6 +1008,13 @@ int loadbios() fclose(f); biosmask = 0x1ffff; return 1; + + case ROM_CBM_SL386SX25: + f = romfopen("cbm_sl386sx25/f000.rom", "rb"); + if (!f) break; + romfread(rom, 0x10000, 1, f); + fclose(f); + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index 33b65c1..5d582f5 100644 --- a/src/model.c +++ b/src/model.c @@ -54,6 +54,7 @@ #include "ps1.h" #include "ps2.h" #include "ps2_mca.h" +#include "scamp.h" #include "scat.h" #include "serial.h" #include "sio.h" @@ -96,6 +97,7 @@ void ps2_model_55sx_init(); void ps2_model_70_init(); void ps2_model_80_init(); void at_neat_init(); +void at_scamp_init(); void at_scat_init(); void at_scatsx_init(); void at_acer386sx_init(); @@ -184,6 +186,7 @@ MODEL models[] = {"[386SX] AMA-932J", ROM_AMA932J, "ama932j", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 512, 8192, 128, at_headland_init, NULL}, {"[386SX] AMI 386SX clone", ROM_AMI386SX, "ami386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512,16384, 128, at_headland_init, NULL}, {"[386SX] Amstrad MegaPC", ROM_MEGAPC, "megapc", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_DISABLE_HW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, at_wd76c10_init, NULL}, + {"[386SX] Commodore SL386SX-25", ROM_CBM_SL386SX25, "cbm_sl386sx25", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1024,16384, 512, at_scamp_init, NULL}, {"[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}, @@ -567,6 +570,12 @@ void at_neat_init() neat_init(); } +void at_scamp_init() +{ + at_init(); + scamp_init(); +} + void at_scat_init() { at_init(); diff --git a/src/nvr.c b/src/nvr.c index f080247..3a15a55 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -347,6 +347,7 @@ void loadnvr() case ROM_PB410A: f = nvrfopen("pb410a.nvr", "rb"); nvrmask = 127; break; case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "rb"); break; case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break; + case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "rb"); nvrmask = 127; break; default: return; } @@ -445,6 +446,7 @@ void savenvr() case ROM_PB410A: f = nvrfopen("pb410a.nvr", "wb"); break; case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "wb"); break; case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break; + case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "wb"); break; default: return; } diff --git a/src/scamp.c b/src/scamp.c new file mode 100644 index 0000000..6fe9570 --- /dev/null +++ b/src/scamp.c @@ -0,0 +1,230 @@ +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "scamp.h" + +static struct +{ + int cfg_index; + uint8_t cfg_regs[256]; + int cfg_enable; + + uint8_t port_92; +} scamp; + +#define CFG_ID 0x00 +#define CFG_SLTPTR 0x02 +#define CFG_RAMMAP 0x03 +#define CFG_ABAXS 0x0e +#define CFG_CAXS 0x0f +#define CFG_DAXS 0x10 +#define CFG_FEAXS 0x11 + +#define ID_VL82C311 0xd6 + +#define RAMMAP_REMP386 (1 << 4) + +static void shadow_control(uint32_t addr, uint32_t size, int state) +{ +// pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state); + switch (state) + { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + +void scamp_write(uint16_t addr, uint8_t val, void *p) +{ +// pclog("scamp_write: addr=%04x val=%02x\n", addr, val); + switch (addr) + { + case 0x92: + if ((mem_a20_alt ^ val) & 2) + { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~scamp.port_92 & val) & 1) + { + softresetx86(); + cpu_set_edx(); + } + scamp.port_92 = val; + break; + + case 0xec: + if (scamp.cfg_enable) + scamp.cfg_index = val; + break; + + case 0xed: + if (scamp.cfg_enable) + { + if (scamp.cfg_index >= 0x02 && scamp.cfg_index <= 0x16) + { + scamp.cfg_regs[scamp.cfg_index] = val; +// pclog("SCAMP CFG[%02x]=%02x\n", scamp.cfg_index, val); + switch (scamp.cfg_index) + { + case CFG_SLTPTR: +#if 0 + if (!val) + { + /*Disable all RAM*/ + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_high_mapping); + } + else if (val < 0x10) + { + mem_mapping_set_addr(&ram_low_mapping, 0, (val > 9) ? 0xa0000 : (val << 16)); + mem_mapping_disable(&ram_high_mapping); + } + else + { + mem_mapping_enable(&ram_low_mapping); + mem_mapping_enable(&ram_high_mapping); + } +#endif + break; + + case CFG_RAMMAP: + mem_mapping_disable(&ram_remapped_mapping); + if (scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) + { + /*Enabling remapping will disable all shadowing*/ + mem_remap_top_384k(); + shadow_control(0xa0000, 0x60000, 0); + } + else + { + shadow_control(0xa0000, 0x8000, scamp.cfg_regs[CFG_ABAXS] & 3); + shadow_control(0xa8000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 2) & 3); + shadow_control(0xb0000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 4) & 3); + shadow_control(0xb8000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 6) & 3); + + shadow_control(0xc0000, 0x4000, scamp.cfg_regs[CFG_ABAXS] & 3); + shadow_control(0xc4000, 0x4000, (scamp.cfg_regs[CFG_ABAXS] >> 2) & 3); + shadow_control(0xc8000, 0x4000, (scamp.cfg_regs[CFG_ABAXS] >> 4) & 3); + shadow_control(0xcc000, 0x4000, (scamp.cfg_regs[CFG_ABAXS] >> 6) & 3); + + shadow_control(0xd0000, 0x4000, scamp.cfg_regs[CFG_ABAXS] & 3); + shadow_control(0xd4000, 0x4000, (scamp.cfg_regs[CFG_ABAXS] >> 2) & 3); + shadow_control(0xd8000, 0x4000, (scamp.cfg_regs[CFG_ABAXS] >> 4) & 3); + shadow_control(0xdc000, 0x4000, (scamp.cfg_regs[CFG_ABAXS] >> 6) & 3); + + shadow_control(0xe0000, 0x8000, scamp.cfg_regs[CFG_ABAXS] & 3); + shadow_control(0xe8000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 2) & 3); + shadow_control(0xf0000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 4) & 3); + shadow_control(0xf8000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 6) & 3); + } + break; + + case CFG_ABAXS: + if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) + { + shadow_control(0xa0000, 0x8000, val & 3); + shadow_control(0xa8000, 0x8000, (val >> 2) & 3); + shadow_control(0xb0000, 0x8000, (val >> 4) & 3); + shadow_control(0xb8000, 0x8000, (val >> 6) & 3); + } + break; + + case CFG_CAXS: + if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) + { + shadow_control(0xc0000, 0x4000, val & 3); + shadow_control(0xc4000, 0x4000, (val >> 2) & 3); + shadow_control(0xc8000, 0x4000, (val >> 4) & 3); + shadow_control(0xcc000, 0x4000, (val >> 6) & 3); + } + break; + + case CFG_DAXS: + if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) + { + shadow_control(0xd0000, 0x4000, val & 3); + shadow_control(0xd4000, 0x4000, (val >> 2) & 3); + shadow_control(0xd8000, 0x4000, (val >> 4) & 3); + shadow_control(0xdc000, 0x4000, (val >> 6) & 3); + } + break; + + case CFG_FEAXS: + if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) + { + shadow_control(0xe0000, 0x8000, val & 3); + shadow_control(0xe8000, 0x8000, (val >> 2) & 3); + shadow_control(0xf0000, 0x8000, (val >> 4) & 3); + shadow_control(0xf8000, 0x8000, (val >> 6) & 3); + } + break; + } + } + } + break; + + case 0xee: + if (scamp.cfg_enable && mem_a20_alt) + { + scamp.port_92 &= ~2; + mem_a20_alt = 0; + mem_a20_recalc(); + } + break; + } +} + +uint8_t scamp_read(uint16_t addr, void *p) +{ + uint8_t ret = 0xff; + + switch (addr) + { + case 0x92: + ret = scamp.port_92; + break; + + case 0xee: + if (!mem_a20_alt) + { + scamp.port_92 |= 2; + mem_a20_alt = 1; + mem_a20_recalc(); + } + break; + + case 0xef: + softresetx86(); + cpu_set_edx(); + break; + } + +// pclog("scamp_read: addr=%04x ret=%02x\n", addr, ret); + return ret; +} + +void scamp_init(void) +{ + memset(&scamp, 0, sizeof(scamp)); + scamp.cfg_regs[CFG_ID] = ID_VL82C311; + scamp.cfg_enable = 1; + + io_sethandler(0x0092, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL); + io_sethandler(0x00e8, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL); + io_sethandler(0x00ea, 0x0006, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL); + io_sethandler(0x00f4, 0x0002, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL); + io_sethandler(0x00f9, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL); + io_sethandler(0x00fb, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL); +} diff --git a/src/scamp.h b/src/scamp.h new file mode 100644 index 0000000..a4785ca --- /dev/null +++ b/src/scamp.h @@ -0,0 +1 @@ +void scamp_init(void); diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c index 081dc46..70c0635 100644 --- a/src/vid_cl5429.c +++ b/src/vid_cl5429.c @@ -15,7 +15,8 @@ enum { - CL_TYPE_GD5429 = 0, + CL_TYPE_AVGA2 = 0, + CL_TYPE_GD5429, CL_TYPE_GD5430, CL_TYPE_GD5434 }; @@ -73,8 +74,14 @@ typedef struct gd5429_t int mmio_vram_overlap; uint8_t sr10_read, sr11_read; + + uint8_t latch_ext[4]; } gd5429_t; +#define GRB_X8_ADDRESSING (1 << 1) +#define GRB_WRITEMODE_EXT (1 << 2) +#define GRB_8B_LATCHES (1 << 3) + static void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p); static void gd5429_mmio_writew(uint32_t addr, uint16_t val, void *p); static void gd5429_mmio_writel(uint32_t addr, uint32_t val, void *p); @@ -88,13 +95,15 @@ void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p); void gd5429_recalc_banking(gd5429_t *gd5429); void gd5429_recalc_mapping(gd5429_t *gd5429); +uint8_t gd5429_read_linear(uint32_t addr, void *p); + void gd5429_out(uint16_t addr, uint8_t val, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; svga_t *svga = &gd5429->svga; uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; // pclog("gd5429 out %04X %02X\n", addr, val); @@ -143,7 +152,8 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) case 0x07: svga->set_reset_disabled = svga->seqregs[7] & 1; case 0x17: - gd5429_recalc_mapping(gd5429); + if (gd5429->type >= CL_TYPE_GD5429) + gd5429_recalc_mapping(gd5429); break; } return; @@ -196,6 +206,8 @@ 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)) + return; switch (svga->gdcaddr) { case 0x09: case 0x0a: case 0x0b: @@ -318,7 +330,7 @@ uint8_t gd5429_in(uint16_t addr, void *p) gd5429_t *gd5429 = (gd5429_t *)p; svga_t *svga = &gd5429->svga; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1)) + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; // if (addr != 0x3da) pclog("IN gd5429 %04X\n", addr); @@ -343,6 +355,8 @@ 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) + break; temp = svga->seqregs[0x17]; temp &= ~(7 << 3); if (gd5429->type == CL_TYPE_GD5429) @@ -395,6 +409,8 @@ uint8_t gd5429_in(uint16_t addr, void *p) case 0x27: /*ID*/ switch (gd5429->type) { + case CL_TYPE_AVGA2: + return 0x18; /*AVGA2*/ case CL_TYPE_GD5429: return 0x9c; /*GD5429*/ case CL_TYPE_GD5430: @@ -654,10 +670,10 @@ static void gd5429_write(uint32_t addr, uint8_t val, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; svga_t *svga = &gd5429->svga; -// pclog("gd5429_write : %05X %02X ", addr, val); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; -// pclog("%08X\n", addr); + gd5429_write_linear(addr, val, p); } static void gd5429_writew(uint32_t addr, uint16_t val, void *p) @@ -668,7 +684,7 @@ static void gd5429_writew(uint32_t addr, uint16_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; - if (svga->writemode < 4) + if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) svga_writew_linear(addr, val, svga); else { @@ -684,7 +700,7 @@ static void gd5429_writel(uint32_t addr, uint32_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; - if (svga->writemode < 4) + if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) svga_writel_linear(addr, val, svga); else { @@ -699,13 +715,10 @@ static uint8_t gd5429_read(uint32_t addr, void *p) { gd5429_t *gd5429 = (gd5429_t *)p; svga_t *svga = &gd5429->svga; - uint8_t ret; -// pclog("gd5429_read : %05X ", addr); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; - ret = svga_read_linear(addr, &gd5429->svga); -// pclog("%08X %02X\n", addr, ret); - return ret; + return gd5429_read_linear(addr, gd5429); } static uint16_t gd5429_readw(uint32_t addr, void *p) { @@ -714,7 +727,10 @@ static uint16_t gd5429_readw(uint32_t addr, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; - return svga_readw_linear(addr, &gd5429->svga); + + if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) + return svga_readw_linear(addr, &gd5429->svga); + return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8); } static uint32_t gd5429_readl(uint32_t addr, void *p) { @@ -723,7 +739,11 @@ static uint32_t gd5429_readl(uint32_t addr, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1]; - return svga_readl_linear(addr, &gd5429->svga); + + if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) + return svga_readl_linear(addr, &gd5429->svga); + return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8) | + (gd5429_read_linear(addr+2, gd5429) << 16) | (gd5429_read_linear(addr+3, gd5429) << 24); } void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) @@ -731,7 +751,7 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) gd5429_t *gd5429 = (gd5429_t *)p; svga_t *svga = &gd5429->svga; uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; + int writemask2 = svga->seqregs[2]; cycles -= video_timing_write_b; cycles_lost += video_timing_write_b; @@ -741,7 +761,9 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) // if (svga_output) pclog("Write LFB %08X %02X ", addr, val); if (!(svga->gdcreg[6] & 1)) svga->fullchange = 2; - if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) + if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) + addr <<= 3; + else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { writemask2 = 1 << (addr & 3); addr &= ~3; @@ -818,7 +840,6 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) else { // pclog("Writemode 4 : %X ", addr); - addr <<= 1; svga->changedvram[addr >> 12] = changeframecount; // pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]); if (val & svga->seqregs[2] & 0x80) @@ -891,7 +912,6 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) else { // pclog("Writemode 5 : %X ", addr); - addr <<= 1; svga->changedvram[addr >> 12] = changeframecount; // pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]); if (svga->seqregs[2] & 0x80) @@ -914,10 +934,27 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) break; case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; + if (svga->gdcreg[0xb] & GRB_WRITEMODE_EXT) + { + if (writemask2 & 0x80) svga->vram[addr] = svga->la; + if (writemask2 & 0x40) svga->vram[addr | 0x1] = svga->lb; + if (writemask2 & 0x20) svga->vram[addr | 0x2] = svga->lc; + if (writemask2 & 0x10) svga->vram[addr | 0x3] = svga->ld; + if (svga->gdcreg[0xb] & GRB_8B_LATCHES) + { + if (writemask2 & 0x08) svga->vram[addr | 0x4] = gd5429->latch_ext[0]; + if (writemask2 & 0x04) svga->vram[addr | 0x5] = gd5429->latch_ext[1]; + if (writemask2 & 0x02) svga->vram[addr | 0x6] = gd5429->latch_ext[2]; + if (writemask2 & 0x01) svga->vram[addr | 0x7] = gd5429->latch_ext[3]; + } + } + else + { + if (writemask2 & 1) svga->vram[addr] = svga->la; + if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; + if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; + if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; + } break; case 0: if (svga->gdcreg[3] & 7) @@ -1055,13 +1092,92 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) } } +uint8_t gd5429_read_linear(uint32_t addr, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + svga_t *svga = &gd5429->svga; + uint8_t temp, temp2, temp3, temp4; + int readplane = svga->readplane; + uint32_t latch_addr = (addr << 2) & svga->decode_mask; + + cycles -= video_timing_read_b; + cycles_lost += video_timing_read_b; + + egareads++; + + if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) + addr <<= 3; + else if (svga->chain4 || svga->fb_only) + { + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + return svga->vram[addr & svga->vram_mask]; + } + else if (svga->chain2_read) + { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; + } + else + addr<<=2; + + addr &= svga->decode_mask; + + if (latch_addr >= svga->vram_max) + { + svga->la = svga->lb = svga->lc = svga->ld = 0xff; + if (svga->gdcreg[0xb] & GRB_8B_LATCHES) + gd5429->latch_ext[0] = gd5429->latch_ext[1] = gd5429->latch_ext[2] = gd5429->latch_ext[3] = 0xff; + } + else + { + latch_addr &= svga->vram_mask; + svga->la = svga->vram[latch_addr]; + svga->lb = svga->vram[latch_addr | 0x1]; + svga->lc = svga->vram[latch_addr | 0x2]; + svga->ld = svga->vram[latch_addr | 0x3]; + if (svga->gdcreg[0xb] & GRB_8B_LATCHES) + { + gd5429->latch_ext[0] = svga->vram[latch_addr | 0x4]; + gd5429->latch_ext[1] = svga->vram[latch_addr | 0x5]; + gd5429->latch_ext[2] = svga->vram[latch_addr | 0x6]; + gd5429->latch_ext[3] = svga->vram[latch_addr | 0x7]; + } + } + + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + + if (svga->readmode) + { + temp = svga->la; + temp ^= (svga->colourcompare & 1) ? 0xff : 0; + temp &= (svga->colournocare & 1) ? 0xff : 0; + temp2 = svga->lb; + temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; + temp2 &= (svga->colournocare & 2) ? 0xff : 0; + temp3 = svga->lc; + temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; + temp3 &= (svga->colournocare & 4) ? 0xff : 0; + temp4 = svga->ld; + temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; + temp4 &= (svga->colournocare & 8) ? 0xff : 0; + return ~(temp | temp2 | temp3 | temp4); + } +//printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane); + return svga->vram[addr | readplane]; +} + 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) + if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) svga_write_linear(addr, val, svga); else gd5429_write_linear(addr, val & 0xff, gd5429); @@ -1071,8 +1187,7 @@ 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) + if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) svga_writew_linear(addr, val, svga); else { @@ -1085,8 +1200,7 @@ 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) + if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) svga_writel_linear(addr, val, svga); else { @@ -1096,7 +1210,36 @@ static void gd5429_writel_linear(uint32_t addr, uint32_t val, void *p) gd5429_write_linear(addr+3, val >> 24, gd5429); } } - + +static uint8_t gd5429_readb_linear(uint32_t addr, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + svga_t *svga = &gd5429->svga; + + if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) + return svga_read_linear(addr, &gd5429->svga); + return gd5429_read_linear(addr, gd5429); +} +static uint16_t gd5429_readw_linear(uint32_t addr, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + svga_t *svga = &gd5429->svga; + + if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) + return svga_readw_linear(addr, &gd5429->svga); + return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8); +} +static uint32_t gd5429_readl_linear(uint32_t addr, void *p) +{ + gd5429_t *gd5429 = (gd5429_t *)p; + svga_t *svga = &gd5429->svga; + + if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES))) + return svga_readl_linear(addr, &gd5429->svga); + return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8) | + (gd5429_read_linear(addr+2, gd5429) << 16) | (gd5429_read_linear(addr+3, gd5429) << 24); +} + void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) { @@ -1685,13 +1828,16 @@ static void *cl_init(int type, char *fn, int pci_card) memset(gd5429, 0, sizeof(gd5429_t)); vram_size = device_get_config_int("memory"); - gd5429->vram_mask = (vram_size << 20) - 1; + if (vram_size >= 256) + gd5429->vram_mask = (vram_size << 10) - 1; + else + gd5429->vram_mask = (vram_size << 20) - 1; gd5429->type = type; rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - svga_init(&gd5429->svga, gd5429, vram_size << 20, + svga_init(&gd5429->svga, gd5429, (vram_size >= 256) ? (vram_size << 10) : (vram_size << 20), gd5429_recalctimings, gd5429_in, gd5429_out, gd5429_hwcursor_draw, @@ -1701,9 +1847,15 @@ static void *cl_init(int type, char *fn, int pci_card) mem_mapping_set_p(&gd5429->svga.mapping, gd5429); mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, gd5429_mmio_readw, gd5429_mmio_readl, gd5429_mmio_write, gd5429_mmio_writew, gd5429_mmio_writel, 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); + mem_mapping_add(&gd5429->linear_mapping, 0, 0, gd5429_readb_linear, gd5429_readw_linear, gd5429_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); + if (type == CL_TYPE_AVGA2) + { + io_sethandler(0x0102, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + io_sethandler(0x46e8, 0x0002, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429); + svga->decode_mask = svga->vram_mask; + } svga->hwcursor.yoff = 32; svga->hwcursor.xoff = 0; @@ -1741,6 +1893,10 @@ static void *cl_init(int type, char *fn, int pci_card) } +static void *avga2_cbm_sl386sx_init() +{ + return cl_init(CL_TYPE_AVGA2, "cbm_sl386sx25/c000.rom", -1); +} static void *gd5429_init() { return cl_init(CL_TYPE_GD5429, "5429.vbi", -1); @@ -1805,6 +1961,33 @@ void gd5429_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &gd5429->svga); } +static device_config_t avga2_config[] = +{ + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "" + } + }, + .default_int = 512 + }, + { + .type = -1 + } +}; + static device_config_t gd5429_config[] = { { @@ -1858,6 +2041,19 @@ static device_config_t gd5434_config[] = } }; +device_t avga2_cbm_sl386sx_device = +{ + "AVGA2 (Commodore SL386SX-25)", + 0, + avga2_cbm_sl386sx_init, + gd5429_close, + gd5430_available, + gd5429_speed_changed, + gd5429_force_redraw, + gd5429_add_status_info, + avga2_config +}; + device_t gd5429_device = { "Cirrus Logic GD5429", diff --git a/src/vid_cl5429.h b/src/vid_cl5429.h index a045e6e..9398b27 100644 --- a/src/vid_cl5429.h +++ b/src/vid_cl5429.h @@ -1,3 +1,4 @@ +extern device_t avga2_cbm_sl386sx_device; extern device_t gd5429_device; extern device_t gd5430_device; extern device_t gd5430_pb570_device; diff --git a/src/video.c b/src/video.c index 3b31973..9200938 100644 --- a/src/video.c +++ b/src/video.c @@ -130,6 +130,7 @@ static video_timings_t timing_pc200 = {VIDEO_ISA, 8,16,32, 8,16,32}; static video_timings_t timing_m24 = {VIDEO_ISA, 8,16,32, 8,16,32}; static video_timings_t timing_pvga1a = {VIDEO_ISA, 6, 8,16, 6, 8,16}; static video_timings_t timing_wd90c11 = {VIDEO_ISA, 3, 3, 6, 5, 5,10}; +static video_timings_t timing_avga2 = {VIDEO_ISA, 3, 3, 6, 5, 5,10}; static video_timings_t timing_oti067 = {VIDEO_ISA, 6, 8,16, 6, 8,16}; static video_timings_t timing_vga = {VIDEO_ISA, 8,16,32, 8,16,32}; static video_timings_t timing_ps1_svga = {VIDEO_ISA, 6, 8,16, 6, 8,16}; @@ -242,6 +243,9 @@ device_t *video_card_getdevice(int card, int romset) case ROM_PB520R: return &gd5434_pb520r_device; + + case ROM_CBM_SL386SX25: + return &avga2_cbm_sl386sx_device; } return video_cards[card].device; } @@ -365,6 +369,7 @@ int video_is_mda() case ROM_PB410A: case ROM_PB570: case ROM_PB520R: + case ROM_CBM_SL386SX25: return 0; } return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_MDA; @@ -411,6 +416,7 @@ int video_is_cga() case ROM_PB410A: case ROM_PB570: case ROM_PB520R: + case ROM_CBM_SL386SX25: return 0; } return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_CGA; @@ -449,6 +455,7 @@ int video_is_ega_vga() case ROM_PB410A: case ROM_PB570: case ROM_PB520R: + case ROM_CBM_SL386SX25: return 1; } return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_SPECIAL; @@ -614,6 +621,10 @@ void video_updatetiming() case ROM_PB520R: timing = &timing_pb520r; break; + + case ROM_CBM_SL386SX25: + timing = &timing_avga2; + break; } @@ -813,6 +824,10 @@ void video_init() break; } return; + + case ROM_CBM_SL386SX25: + device_add(&avga2_cbm_sl386sx_device); + return; } device_add(video_cards[video_old_to_new(gfxcard)].device); }