From f41bbb6ba8e7e9ea84a38de172e6b782a64fe46c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 23 Jul 2016 01:48:47 +0200 Subject: [PATCH] Added emulation of Cardex ET4000/W32p with ICS/SDAC RAMDAC; Fixed ET4000/W32p clock (for non-Diamond variants) and banking extension; Brought the code on par with the mainline; Fixed names of the two Cardex ET4000/W32p variants per the BIOS'es; Brought ET4000AX unknown RAMDAC back in line with the mainline (reverted bogus "fix" by Win9xFan); Made 15bpp and 16bpp colors more accurate. --- src/Makefile.mingw | 2 +- src/Makefile.mingw64 | 2 +- src/gameport.c | 16 ++++- src/gameport.h | 5 +- src/ibm.h | 3 +- src/pc.c | 14 ++++ src/plat-joystick.h | 1 + src/vid_cga.c | 21 ++++-- src/vid_et4000w32.c | 77 +++++++++++++++++++--- src/vid_et4000w32.h | 1 + src/vid_sdac_ramdac.c | 58 ++++++----------- src/vid_stg_ramdac.c | 110 +++++++++++++++++++++---------- src/vid_unk_ramdac.c | 17 +++-- src/video.c | 43 ++++++++++++- src/win-joystick.cc | 66 ++++++++++++------- src/win-joystickconfig.c | 135 +++++++++++++++++++++++++++++++++++++++ 16 files changed, 452 insertions(+), 119 deletions(-) diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 33b1bacc3..f078bea9c 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -6,7 +6,7 @@ CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-l OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \ cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \ - i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \ + i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \ mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index f395af9f4..5424a9178 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -6,7 +6,7 @@ CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-l OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \ cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \ - i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \ + i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \ mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ diff --git a/src/gameport.c b/src/gameport.c index fe0003903..ab62d0e9a 100644 --- a/src/gameport.c +++ b/src/gameport.c @@ -7,8 +7,10 @@ #include "timer.h" #include "gameport.h" +#include "joystick_ch_flightstick_pro.h" #include "joystick_standard.h" #include "joystick_sw_pad.h" +#include "joystick_tm_fcs.h" int joystick_type; @@ -18,7 +20,9 @@ static joystick_if_t *joystick_list[] = &joystick_standard_4button, &joystick_standard_6button, &joystick_standard_8button, + &joystick_ch_flightstick_pro, &joystick_sw_pad, + &joystick_tm_fcs, NULL }; @@ -44,7 +48,12 @@ int joystick_get_button_count(int joystick) return joystick_list[joystick]->button_count; } -char *joystick_get_axis_name(int joystick, int id) +int joystick_get_pov_count(int joystick) +{ + return joystick_list[joystick]->pov_count; +} + + char *joystick_get_axis_name(int joystick, int id) { return joystick_list[joystick]->axis_names[id]; } @@ -54,6 +63,11 @@ char *joystick_get_button_name(int joystick, int id) return joystick_list[joystick]->button_names[id]; } +char *joystick_get_pov_name(int joystick, int id) +{ + return joystick_list[joystick]->pov_names[id]; +} + typedef struct gameport_axis_t { int64_t count; diff --git a/src/gameport.h b/src/gameport.h index cca311e25..a8e5abda7 100644 --- a/src/gameport.h +++ b/src/gameport.h @@ -10,10 +10,11 @@ typedef struct void (*write)(void *p); int (*read_axis)(void *p, int axis); void (*a0_over)(void *p); - int axis_count, button_count; + int axis_count, button_count, pov_count; int max_joysticks; char axis_names[8][32]; char button_names[32][32]; + char pov_names[4][32]; } joystick_if_t; extern int joystick_type; @@ -21,8 +22,10 @@ char *joystick_get_name(int joystick); int joystick_get_max_joysticks(int joystick); int joystick_get_axis_count(int joystick); int joystick_get_button_count(int joystick); +int joystick_get_pov_count(int joystick); char *joystick_get_axis_name(int joystick, int id); char *joystick_get_button_name(int joystick, int id); +char *joystick_get_pov_name(int joystick, int id); void gameport_update_joystick_type(); diff --git a/src/ibm.h b/src/ibm.h index a4ed88cc7..c507e1d5b 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -386,7 +386,7 @@ enum GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/ GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/ GFX_INCOLOR, /* Hercules InColor */ - GFX_ET4000W32C, /*Tseng ET4000/W32p (Cardex) */ + GFX_ET4000W32C, /*Tseng ET4000/W32p (Cardex) (STG RAMDAC) */ GFX_COMPAQ_EGA, /*Compaq EGA*/ GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/ GFX_COMPAQ_VGA, /*Compaq/Paradise VGA*/ @@ -395,6 +395,7 @@ enum GFX_VGAWONDERXL, /*Compaq ATI VGA Wonder XL (28800-5)*/ GFX_WD90C11, /*Paradise WD90C11 Standalone*/ GFX_OTI077, /*Oak OTI-077*/ + GFX_ET4000W32CS, /*Tseng ET4000/W32p (Cardex) (ICS RAMDAC) */ GFX_MAX }; diff --git a/src/pc.c b/src/pc.c index 57aa06c20..5754eaf23 100644 --- a/src/pc.c +++ b/src/pc.c @@ -704,6 +704,13 @@ void loadconfig(char *fn) sprintf(s, "joystick_%i_button_%i", c, d); joystick_state[c].button_mapping[d] = config_get_int("Joysticks", s, d); } + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + { + sprintf(s, "joystick_%i_pov_%i_x", c, d); + joystick_state[c].pov_mapping[d][0] = config_get_int("Joysticks", s, d); + sprintf(s, "joystick_%i_pov_%i_y", c, d); + joystick_state[c].pov_mapping[d][1] = config_get_int("Joysticks", s, d); + } } } } @@ -793,6 +800,13 @@ void saveconfig() sprintf(s, "joystick_%i_button_%i", c, d); config_set_int("Joysticks", s, joystick_state[c].button_mapping[d]); } + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + { + sprintf(s, "joystick_%i_pov_%i_x", c, d); + config_set_int("Joysticks", s, joystick_state[c].pov_mapping[d][0]); + sprintf(s, "joystick_%i_pov_%i_y", c, d); + config_set_int("Joysticks", s, joystick_state[c].pov_mapping[d][1]); + } } } diff --git a/src/plat-joystick.h b/src/plat-joystick.h index 2b789f5f8..1560d1295 100644 --- a/src/plat-joystick.h +++ b/src/plat-joystick.h @@ -53,6 +53,7 @@ extern "C" { int plat_joystick_nr; int axis_mapping[8]; int button_mapping[32]; + int pov_mapping[4][2]; } joystick_t; #define MAX_JOYSTICKS 4 diff --git a/src/vid_cga.c b/src/vid_cga.c index 7df116dd5..e0202ff17 100644 --- a/src/vid_cga.c +++ b/src/vid_cga.c @@ -81,8 +81,11 @@ void cga_write(uint32_t addr, uint8_t val, void *p) cga_t *cga = (cga_t *)p; // pclog("CGA_WRITE %04X %02X\n", addr, val); cga->vram[addr & 0x3fff] = val; - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; + if (cga->snow_enabled) + { + cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val; + cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; + } egawrites++; cycles -= 4; } @@ -91,8 +94,11 @@ uint8_t cga_read(uint32_t addr, void *p) { cga_t *cga = (cga_t *)p; cycles -= 4; - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff]; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff]; + if (cga->snow_enabled) + { + cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff]; + cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff]; + } egareads++; // pclog("CGA_READ %04X\n", addr); return cga->vram[addr & 0x3fff]; @@ -443,6 +449,7 @@ void *cga_standalone_init() display_type = device_get_config_int("display_type"); cga->composite = (display_type != CGA_RGB); cga->revision = device_get_config_int("composite_type"); + cga->snow_enabled = device_get_config_int("snow_enabled"); cga->vram = malloc(0x4000); @@ -513,6 +520,12 @@ static device_config_t cga_config[] = }, .default_int = COMPOSITE_OLD }, + { + .name = "snow_enabled", + .description = "Snow emulation", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .type = -1 } diff --git a/src/vid_et4000w32.c b/src/vid_et4000w32.c index a46a040dc..6af88a3a0 100644 --- a/src/vid_et4000w32.c +++ b/src/vid_et4000w32.c @@ -14,6 +14,7 @@ #include "video.h" #include "vid_svga.h" #include "vid_icd2061.h" +#include "vid_sdac_ramdac.h" #include "vid_stg_ramdac.h" #define FIFO_SIZE 65536 @@ -49,6 +50,7 @@ typedef struct et4000w32p_t svga_t svga; stg_ramdac_t ramdac; + sdac_ramdac_t sdac_ramdac; icd2061_t icd2061; int index; @@ -95,6 +97,7 @@ typedef struct et4000w32p_t { uint32_t base[3]; uint8_t ctrl; + uint8_t unk[2]; } mmu; fifo_entry_t fifo[FIFO_SIZE]; @@ -142,12 +145,19 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - stg_ramdac_out(addr, val, &et4000->ramdac, svga); + if (gfxcard == GFX_ET4000W32CS) + { + sdac_ramdac_out(addr, val, &et4000->sdac_ramdac, svga); + } + else + { + stg_ramdac_out(addr, val, &et4000->ramdac, svga); + } return; case 0x3CB: /*Banking extension*/ - svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); - svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x10) << 16); + svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 3) << 20); + svga->read_bank = (svga->read_bank & 0xfffff) | ((val & 0x30) << 16); et4000->banking2 = val; return; case 0x3CD: /*Banking*/ @@ -242,7 +252,14 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return stg_ramdac_in(addr, &et4000->ramdac, svga); + if (gfxcard == GFX_ET4000W32CS) + { + return sdac_ramdac_in(addr, &et4000->sdac_ramdac, svga); + } + else + { + return stg_ramdac_in(addr, &et4000->ramdac, svga); + } case 0x3CB: return et4000->banking2; @@ -304,10 +321,23 @@ void et4000w32p_recalctimings(svga_t *svga) case 2: case 3: svga->clock = cpuclock / icd2061_getfreq(&et4000->icd2061, 2); break; } } - else + else if (gfxcard == GFX_ET4000W32C) { svga->clock = cpuclock / stg_getclock((svga->miscout >> 2) & 3, &et4000->ramdac); } + else + { + svga->clock = cpuclock / sdac_getclock((svga->miscout >> 2) & 3, &et4000->sdac_ramdac); + switch (sdac_get_clock_divider(&et4000->sdac_ramdac)) + { + case 2: + svga->clock /= 2.0; + break; + case 3: + svga->clock /= 3.0; + break; + } + } switch (svga->bpp) { @@ -580,6 +610,7 @@ void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) if ((addr & 0x7fff) >= 0x7f80) { et4000w32p_queue(et4000, addr & 0x7fff, val, FIFO_WRITE_BYTE); + pclog("MMU queue: %04X: %02X\n", addr, val); } else switch (addr & 0x7fff) { @@ -596,6 +627,8 @@ void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) case 0x7f0a: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFF00FFFF) | (val << 16); break; case 0x7f0d: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00FFFFFF) | (val << 24); break; case 0x7f13: et4000->mmu.ctrl=val; break; + case 0x7f30: et4000->mmu.unk[0] = val; pclog("MMU Unknown 0 = %02X\n", et4000->mmu.unk[0]); break; + case 0x7f32: et4000->mmu.unk[1] = val; pclog("MMU Unknown 1 = %02X\n", et4000->mmu.unk[1]); break; } break; } @@ -651,6 +684,8 @@ uint8_t et4000w32p_mmu_read(uint32_t addr, void *p) case 0x7f0a: return et4000->mmu.base[2] >> 16; case 0x7f0b: return et4000->mmu.base[2] >> 24; case 0x7f13: return et4000->mmu.ctrl; + case 0x7f30: return et4000->mmu.unk[0]; + case 0x7f32: return et4000->mmu.unk[1]; case 0x7f36: temp = et4000->acl.status; @@ -1224,8 +1259,11 @@ void *et4000w32p_common_init(char *biosfile) } else { - pclog("No known BIOS detected or BIOS already set to 1 MB DRAM modules, maximum VRAM is 2 MB\n"); - vram_size == 2; + if (gfxcard != GFX_ET4000W32CS) + { + pclog("No known BIOS detected or BIOS already set to 1 MB DRAM modules, maximum VRAM is 2 MB\n"); + vram_size == 2; + } } } if (PCI) @@ -1261,6 +1299,11 @@ void *et4000w32pc_init() return et4000w32p_common_init("roms/cardex.vbi"); } +void *et4000w32pcs_init() +{ + return et4000w32p_common_init("roms/TSENG.BIN"); +} + int et4000w32p_available() { return rom_present("roms/et4000w32.bin"); @@ -1271,6 +1314,11 @@ int et4000w32pc_available() return rom_present("roms/cardex.vbi"); } +int et4000w32pcs_available() +{ + return rom_present("roms/TSENG.BIN"); +} + void et4000w32p_close(void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -1439,7 +1487,7 @@ device_t et4000w32p_device = device_t et4000w32pc_device = { - "Cardex Tseng Labs ET4000/w32p", + "Cardex 1703-DDC (ET4000/W32P)", 0, et4000w32pc_init, et4000w32p_close, @@ -1449,3 +1497,16 @@ device_t et4000w32pc_device = et4000w32p_add_status_info, et4000w32pc_config }; + +device_t et4000w32pcs_device = +{ + "Cardex ICS5341 (ET4000/W32P)", + 0, + et4000w32pcs_init, + et4000w32p_close, + et4000w32pcs_available, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + et4000w32p_add_status_info, + et4000w32pc_config +}; diff --git a/src/vid_et4000w32.h b/src/vid_et4000w32.h index 1b91ff09d..eff8b9847 100644 --- a/src/vid_et4000w32.h +++ b/src/vid_et4000w32.h @@ -1,2 +1,3 @@ extern device_t et4000w32p_device; extern device_t et4000w32pc_device; +extern device_t et4000w32pcs_device; diff --git a/src/vid_sdac_ramdac.c b/src/vid_sdac_ramdac.c index 2094f356d..82ae6ee24 100644 --- a/src/vid_sdac_ramdac.c +++ b/src/vid_sdac_ramdac.c @@ -6,6 +6,17 @@ #include "vid_svga.h" #include "vid_sdac_ramdac.h" +int sdac_get_clock_divider(sdac_ramdac_t *ramdac) +{ + switch (ramdac->command >> 4) + { + case 0x0: case 0x3: case 0x5: return 1; + case 0x1: case 0x2: case 0x6: case 0x7: case 0xa: case 0xc: return 2; + case 0x4: case 0xe: return 3; + default: return 1; + } +} + void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga) { // /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2); @@ -23,45 +34,16 @@ void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t * { ramdac->command = val; // pclog("RAMDAC command reg now %02X\n", val); - // 0, 1 = 15 bpp - if (gfxcard == GFX_ET4000W32C) - { - if (ramdac->command & 8) - { - switch (ramdac->regs[3]) - { - case 0: case 5: case 7: svga->bpp = 8; break; - case 1: case 2: case 8: svga->bpp = 15; break; - case 3: case 6: svga->bpp = 16; break; - case 4: case 9: svga->bpp = 24; break; - default: svga->bpp = 8; break; - } - } - else - { - switch (ramdac->command >> 5) - { - case 0: svga->bpp = 8; break; - case 5: svga->bpp = 15; break; - case 6: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - default: svga->bpp = 8; break; - } - } - } - else - { - switch (val >> 4) - { - case 0x2: case 0x3: case 0xa: svga->bpp = 15; break; - case 0x4: case 0xe: svga->bpp = 24; break; - case 0x5: case 0x6: case 0xc: svga->bpp = 16; break; - case 0x7: svga->bpp = 32; break; + switch (val >> 4) + { + case 0x2: case 0x3: case 0xa: svga->bpp = 15; break; + case 0x4: case 0xe: svga->bpp = 24; break; + case 0x5: case 0x6: case 0xc: svga->bpp = 16; break; + case 0x7: svga->bpp = 32; break; - case 0: case 1: default: svga->bpp = 8; break; - } - } - pclog("SDAC: Value %02X/%02X set to %i bpp\n", val >> 4, val, svga->bpp); + case 0: case 1: default: svga->bpp = 8; break; + } + svga_recalctimings(svga); } //ramdac->magic_count = 0; break; diff --git a/src/vid_stg_ramdac.c b/src/vid_stg_ramdac.c index 6e361d670..063e208bf 100644 --- a/src/vid_stg_ramdac.c +++ b/src/vid_stg_ramdac.c @@ -7,10 +7,39 @@ static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; static int stg_state_write[8] = {0,0,0,0,0,6,7,7}; +static int stg_state_indexed = 0; + +void stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac) +{ + int oldbpp = svga->bpp; + if (ramdac->command & 0x8) + { + switch (ramdac->regs[3]) + { + case 0: case 5: case 7: svga->bpp = 8; break; + case 1: case 2: case 8: svga->bpp = 15; break; + case 3: case 6: svga->bpp = 16; break; + case 4: case 9: svga->bpp = 24; break; + default: svga->bpp = 8; break; + } + } + else + { + switch (ramdac->command >> 5) + { + case 0: svga->bpp = 8; break; + case 5: svga->bpp = 15; break; + case 6: svga->bpp = 16; break; + case 7: svga->bpp = 24; break; + default: svga->bpp = 8; break; + } + } + svga_recalctimings(svga); +} void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga) { - int didwrite; + int didwrite, old; //if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc); switch (addr) { @@ -20,8 +49,20 @@ void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *sv case 0: case 1: case 2: case 3: break; case 4: + old = ramdac->command; ramdac->command = val; - /*pclog("Write RAMDAC command %02X\n",val);*/ + if ((old ^ val) & 8) + { + stg_ramdac_set_bpp(svga, ramdac); + } + else + { + if ((old ^ val) & 0xE0) + { + stg_ramdac_set_bpp(svga, ramdac); + } + } + // pclog("Write RAMDAC command %02X\n",val); break; case 5: ramdac->index = (ramdac->index & 0xff00) | val; @@ -30,38 +71,17 @@ void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *sv ramdac->index = (ramdac->index & 0xff) | (val << 8); break; case 7: -#ifndef RELEASE_BUILD - pclog("Write RAMDAC reg %02X %02X\n", ramdac->index, val); -#endif - if (ramdac->index < 0x100) + // pclog("Write RAMDAC reg %02X %02X\n", ramdac->index, val); + if (ramdac->index < 0x100) + { ramdac->regs[ramdac->index] = val; + } + if ((ramdac->index == 3) && (ramdac->command & 8)) stg_ramdac_set_bpp(svga, ramdac); ramdac->index++; break; } didwrite = (ramdac->magic_count >= 4); ramdac->magic_count = stg_state_write[ramdac->magic_count & 7]; - if (ramdac->command & 8) - { - switch (ramdac->regs[3]) - { - case 0: case 5: case 7: svga->bpp = 8; break; - case 1: case 2: case 8: svga->bpp = 15; break; - case 3: case 6: svga->bpp = 16; break; - case 4: case 9: svga->bpp = 24; break; - default: svga->bpp = 8; break; - } - } - else - { - switch (ramdac->command >> 5) - { - case 0: svga->bpp = 8; break; - case 5: svga->bpp = 15; break; - case 6: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - default: svga->bpp = 8; break; - } - } if (didwrite) return; break; case 0x3c7: case 0x3c8: case 0x3c9: @@ -93,15 +113,18 @@ uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga) temp = ramdac->index >> 8; break; case 7: -// pclog("Read RAMDAC index %04X\n",stg_ramdac.index); + // pclog("Read RAMDAC index %04X\n",ramdac->index); switch (ramdac->index) { case 0: temp = 0x44; break; case 1: - temp = 0x02; + temp = 0x03; break; + case 7: + temp = 0x88; + break; default: if (ramdac->index < 0x100) temp = ramdac->regs[ramdac->index]; else temp = 0xff; @@ -112,7 +135,7 @@ uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga) } ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7]; return temp; - case 0x3c8: case 0x3c9: + case 0x3c7: case 0x3c8: case 0x3c9: ramdac->magic_count=0; break; } @@ -124,14 +147,31 @@ float stg_getclock(int clock, void *p) stg_ramdac_t *ramdac = (stg_ramdac_t *)p; float t; int m, n1, n2; + float d; // pclog("STG_Getclock %i %04X\n", clock, ramdac->regs[clock]); if (clock == 0) return 25175000.0; if (clock == 1) return 28322000.0; clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ - m = (ramdac->regs[clock] & 0x7f) + 2; - n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; - n2 = ((ramdac->regs[clock] >> 13) & 0x07); - t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); + m = (ramdac->regs[clock] & 0x7f) + 2; /* B+2 */ + n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; /* N1+2 */ + n2 = ((ramdac->regs[clock] >> 13) & 0x07); /* D */ + switch (n2) + { + case 0: + d = 1.0; + break; + case 1: + d = 2.0; + break; + case 2: + d = 4.0; + break; + case 3: + d = 8.0; + break; + } + // t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); + t = (14318184.0 * ((float)m / d)) / (float)n1; // pclog("STG clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2); return t; } diff --git a/src/vid_unk_ramdac.c b/src/vid_unk_ramdac.c index 2b71647ae..c5c09da14 100644 --- a/src/vid_unk_ramdac.c +++ b/src/vid_unk_ramdac.c @@ -22,16 +22,21 @@ void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *sv case 0: case 1: case 2: case 3: svga->bpp = 8; break; + case 4: case 5: + svga->bpp = 32; /* Per the spec. */ + break; case 6: case 7: - svga->bpp = 15; - break; - case 8: case 9: case 0xA: case 0xB: - svga->bpp = 16; - break; - case 0xC: case 0xD: case 0xE: case 0xF: svga->bpp = 24; break; + case 8: case 9: case 0xA: case 0xB: + svga->bpp = 15; + break; + case 0xC: case 0xD: case 0xE: case 0xF: + svga->bpp = 16; + break; } + svga_recalctimings(svga); + pclog("unk_ramdac: set to %02X, %i bpp\n", (val&1)|((val&0xE0)>>4), svga->bpp); return; } ramdac->state = 0; diff --git a/src/video.c b/src/video.c index c592032f9..a9a340928 100644 --- a/src/video.c +++ b/src/video.c @@ -52,7 +52,8 @@ static VIDEO_CARD video_cards[] = {"ATI Graphics Pro Turbo (Mach64 GX)", &mach64gx_device, GFX_MACH64GX}, {"ATI VGA Charger (ATI-28800)", &ati28800_device, GFX_VGACHARGER}, {"ATI VGA Edge-16 (ATI-18800)", &ati18800_device, GFX_VGAEDGE16}, - {"Cardex Tseng ET4000/w32p", &et4000w32pc_device, GFX_ET4000W32C}, + {"Cardex 1703-DDC (ET4000/W32P)", &et4000w32pc_device, GFX_ET4000W32C}, + {"Cardex ICS5341 (ET4000/W32P)", &et4000w32pcs_device, GFX_ET4000W32CS}, {"CGA", &cga_device, GFX_CGA}, {"Cirrus Logic CL-GD5429", &gd5429_device, GFX_CL_GD5429}, {"Diamond Stealth 32 (Tseng ET4000/w32p)", &et4000w32p_device, GFX_ET4000W32}, @@ -388,6 +389,38 @@ static struct static void blit_thread(void *param); +int calc_15to32(int c) +{ + int b, g, r; + double db, dg, dr; + b = (c & 31); + g = ((c >> 5) & 31); + r = ((c >> 10) & 31); + db = (((double) b) / 31.0) * 255.0; + dg = (((double) g) / 31.0) * 255.0; + dr = (((double) r) / 31.0) * 255.0; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; + return (b | g | r); +} + +int calc_16to32(int c) +{ + int b, g, r; + double db, dg, dr; + b = (c & 31); + g = ((c >> 5) & 63); + r = ((c >> 11) & 31); + db = (((double) b) / 31.0) * 255.0; + dg = (((double) g) / 63.0) * 255.0; + dr = (((double) r) / 31.0) * 255.0; + b = (int) db; + g = ((int) dg) << 8; + r = ((int) dr) << 16; + return (b | g | r); +} + void initvideo() { int c, d, e; @@ -435,12 +468,20 @@ void initvideo() } video_15to32 = malloc(4 * 65536); +#if 0 for (c = 0; c < 65536; c++) video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); +#endif + for (c = 0; c < 65536; c++) + video_15to32[c] = calc_15to32(c); video_16to32 = malloc(4 * 65536); +#if 0 for (c = 0; c < 65536; c++) video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); +#endif + for (c = 0; c < 65536; c++) + video_16to32[c] = calc_16to32(c); blit_data.wake_blit_thread = thread_create_event(); blit_data.blit_complete = thread_create_event(); diff --git a/src/win-joystick.cc b/src/win-joystick.cc index 55e3206f2..5f77fd266 100644 --- a/src/win-joystick.cc +++ b/src/win-joystick.cc @@ -175,6 +175,30 @@ void joystick_close() } } +static int joystick_get_axis(int joystick_nr, int mapping) +{ + if (mapping & POV_X) + { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return sin((2*M_PI * (double)pov) / 36000.0) * 32767; + } + else if (mapping & POV_Y) + { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; + } + else + return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; +} + void joystick_poll() { int c, d; @@ -218,30 +242,26 @@ void joystick_poll() int joystick_nr = joystick_state[c].plat_joystick_nr - 1; for (d = 0; d < joystick_get_axis_count(joystick_type); d++) - { - if (joystick_state[c].axis_mapping[d] & POV_X) - { - int pov = plat_joystick_state[joystick_nr].p[joystick_state[c].axis_mapping[d] & 3]; - - if (LOWORD(pov) == 0xFFFF) - joystick_state[c].axis[d] = 0; - else - joystick_state[c].axis[d] = sin((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else if (joystick_state[c].axis_mapping[d] & POV_Y) - { - int pov = plat_joystick_state[joystick_nr].p[joystick_state[c].axis_mapping[d] & 3]; - - if (LOWORD(pov) == 0xFFFF) - joystick_state[c].axis[d] = 0; - else - joystick_state[c].axis[d] = -cos((2*M_PI * (double)pov) / 36000.0) * 32767; - } - else - joystick_state[c].axis[d] = plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[joystick_state[c].axis_mapping[d]].id]; - } + joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); for (d = 0; d < joystick_get_button_count(joystick_type); d++) joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + { + int x, y; + double angle, magnitude; + + x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); + y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + + angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); + magnitude = sqrt((double)x*(double)x + (double)y*(double)y); + + if (magnitude < 16384) + joystick_state[c].pov[d] = -1; + else + joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; + } } else { @@ -249,6 +269,8 @@ void joystick_poll() joystick_state[c].axis[d] = 0; for (d = 0; d < joystick_get_button_count(joystick_type); d++) joystick_state[c].button[d] = 0; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + joystick_state[c].pov[d] = -1; } } } diff --git a/src/win-joystickconfig.c b/src/win-joystickconfig.c index 4aff40248..a02f704e0 100644 --- a/src/win-joystickconfig.c +++ b/src/win-joystickconfig.c @@ -79,6 +79,38 @@ static void rebuild_axis_button_selections(HWND hdlg) id += 2; } + + for (c = 0; c < joystick_get_pov_count(joystick_config_type)*2; c++) + { + int sel = c; + + h = GetDlgItem(hdlg, id); + SendMessage(h, CB_RESETCONTENT, 0, 0); + + if (joystick) + { + for (d = 0; d < plat_joystick_state[joystick-1].nr_povs; d++) + { + char s[80]; + + sprintf(s, "%s (X axis)", plat_joystick_state[joystick-1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + } + for (d = 0; d < plat_joystick_state[joystick-1].nr_axes; d++) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick-1].axis[d].name); + } + SendMessage(h, CB_SETCURSEL, sel, 0); + EnableWindow(h, TRUE); + } + else + EnableWindow(h, FALSE); + + id += 2; + } + } static int get_axis(HWND hdlg, int id) @@ -97,6 +129,23 @@ static int get_axis(HWND hdlg, int id) return POV_X | (axis_sel >> 1); } +static int get_pov(HWND hdlg, int id) +{ + HWND h = GetDlgItem(hdlg, id); + int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_povs*2; + + if (axis_sel < nr_povs) + { + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); + } + + return axis_sel - nr_povs; +} + static BOOL CALLBACK joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) @@ -120,6 +169,7 @@ static BOOL CALLBACK joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wPar if (joystick_state[joystick_nr].plat_joystick_nr) { int nr_axes = plat_joystick_state[joystick-1].nr_axes; + int nr_povs = plat_joystick_state[joystick-1].nr_povs; for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) { int mapping = joystick_state[joystick_nr].axis_mapping[c]; @@ -139,6 +189,29 @@ static BOOL CALLBACK joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wPar SendMessage(h, CB_SETCURSEL, joystick_state[joystick_nr].button_mapping[c], 0); id += 2; } + for (c = 0; c < joystick_get_pov_count(joystick_config_type); c++) + { + int mapping; + + h = GetDlgItem(hdlg, id); + mapping = joystick_state[joystick_nr].pov_mapping[c][0]; + if (mapping & POV_X) + SendMessage(h, CB_SETCURSEL, (mapping & 3)*2, 0); + else if (mapping & POV_Y) + SendMessage(h, CB_SETCURSEL, (mapping & 3)*2 + 1, 0); + else + SendMessage(h, CB_SETCURSEL, mapping + nr_povs*2, 0); + id += 2; + h = GetDlgItem(hdlg, id); + mapping = joystick_state[joystick_nr].pov_mapping[c][1]; + if (mapping & POV_X) + SendMessage(h, CB_SETCURSEL, (mapping & 3)*2, 0); + else if (mapping & POV_Y) + SendMessage(h, CB_SETCURSEL, (mapping & 3)*2 + 1, 0); + else + SendMessage(h, CB_SETCURSEL, mapping + nr_povs*2, 0); + id += 2; + } } } return TRUE; @@ -174,6 +247,15 @@ static BOOL CALLBACK joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wPar joystick_state[joystick_nr].button_mapping[c] = SendMessage(h, CB_GETCURSEL, 0, 0); id += 2; } + for (c = 0; c < joystick_get_button_count(joystick_config_type); c++) + { + h = GetDlgItem(hdlg, id); + joystick_state[joystick_nr].pov_mapping[c][0] = get_pov(hdlg, id); + id += 2; + h = GetDlgItem(hdlg, id); + joystick_state[joystick_nr].pov_mapping[c][1] = get_pov(hdlg, id); + id += 2; + } } } case IDCANCEL: @@ -358,6 +440,59 @@ void joystickconfig_open(HWND hwnd, int joy_nr, int type) y += 20; } + + for (c = 0; c < joystick_get_pov_count(type)*2; c++) + { + char s[80]; + + /*Combo box*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 70; + item->y = y; + item->id = id++; + + item->cx = 140; + item->cy = 150; + + item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0085; // combo box class + + if (c & 1) + sprintf(s, "%s (Y axis)", joystick_get_pov_name(type, c/2)); + else + sprintf(s, "%s (X axis)", joystick_get_pov_name(type, c/2)); + data += MultiByteToWideChar(CP_ACP, 0, s, -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + /*Static text*/ + item = (DLGITEMTEMPLATE *)data; + item->x = 10; + item->y = y; + item->id = id++; + + item->cx = 60; + item->cy = 15; + + item->style = WS_CHILD | WS_VISIBLE; + + data = (uint16_t *)(item + 1); + *data++ = 0xFFFF; + *data++ = 0x0082; // static class + + data += MultiByteToWideChar(CP_ACP, 0, s, -1, data, 256); + *data++ = 0; // no creation data + + if (((unsigned long)data) & 2) + data++; + + y += 20; + } dlg->cdit = (id - IDC_CONFIG_BASE) + 2;