From 28d678476def25550a28f5b7f470007758a59d62 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 31 Aug 2025 19:35:04 +0200 Subject: [PATCH] Implement the ELSA S3 EEPROM, the RGB528 RAMDAC clock selection, and fix split calculation on all the S3 cards (ViRGE included). --- src/include/86box/net_eeprom_nmc93cxx.h | 10 +- src/include/86box/vid_svga.h | 1 + src/network/net_eeprom_nmc93cxx.c | 41 +++--- src/video/ramdac/vid_ramdac_ibm_rgb528.c | 119 +++++++++++++++- src/video/vid_s3.c | 170 ++++++++++++++++++----- src/video/vid_s3_virge.c | 7 +- 6 files changed, 285 insertions(+), 63 deletions(-) diff --git a/src/include/86box/net_eeprom_nmc93cxx.h b/src/include/86box/net_eeprom_nmc93cxx.h index f5260d1ed..7573a6116 100644 --- a/src/include/86box/net_eeprom_nmc93cxx.h +++ b/src/include/86box/net_eeprom_nmc93cxx.h @@ -1,5 +1,11 @@ -struct nmc93cxx_eeprom_t; -typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t; +#include <86box/vid_ati_eeprom.h> + +typedef struct nmc93cxx_eeprom_t { + ati_eeprom_t dev; + uint8_t addrbits; + uint16_t size; + char filename[1024]; +} nmc93cxx_eeprom_t; typedef struct nmc93cxx_eeprom_params_t { uint16_t nwords; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index ffe4f5808..0a327d02b 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -444,6 +444,7 @@ extern void ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void * extern uint8_t ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga); extern void ibm_rgb528_recalctimings(void *priv, svga_t *svga); extern void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine); +extern float ibm_rgb528_getclock(int clock, void *priv); extern void icd2061_write(void *priv, int val); extern float icd2061_getclock(int clock, void *priv); diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index b4fdce1e6..05fd43ed0 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -28,19 +28,9 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/nvr.h> -#include <86box/vid_ati_eeprom.h> #include <86box/net_eeprom_nmc93cxx.h> #include <86box/plat_unused.h> -struct nmc93cxx_eeprom_t { - ati_eeprom_t dev; - uint8_t addrbits; - uint16_t size; - char filename[1024]; -}; - -typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t; - #ifdef ENABLE_NMC93CXX_EEPROM_LOG int nmc93cxx_eeprom_do_log = ENABLE_NMC93CXX_EEPROM_LOG; @@ -110,6 +100,16 @@ nmc93cxx_eeprom_init(const device_t *info) return eeprom; } +static void +nmc93cxx_eeprom_save(nmc93cxx_eeprom_t *eeprom) +{ + FILE *fp = nvr_fopen(eeprom->filename, "wb"); + if (!fp) + return; + fwrite(eeprom->dev.data, 2, eeprom->size, fp); + fclose(fp); +} + void nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi) { @@ -133,21 +133,25 @@ nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi) uint8_t subcommand = address >> (eeprom->addrbits - 2); if (command == 0 && subcommand == 2) { /* Erase all. */ - for (address = 0; address < eeprom->size; address++) { + for (address = 0; address < eeprom->size; address++) eeprom->dev.data[address] = 0xffff; - } + + nmc93cxx_eeprom_save(eeprom); } else if (command == 3) { /* Erase word. */ eeprom->dev.data[address] = 0xffff; - } else if (tick >= 2 + 2 + eeprom->addrbits + 16) { + nmc93cxx_eeprom_save(eeprom); + } else if (tick >= (2 + 2 + eeprom->addrbits + 16)) { if (command == 1) { /* Write word. */ eeprom->dev.data[address] &= eeprom->dev.dat; + nmc93cxx_eeprom_save(eeprom); } else if (command == 0 && subcommand == 1) { /* Write all. */ - for (address = 0; address < eeprom->size; address++) { + for (address = 0; address < eeprom->size; address++) eeprom->dev.data[address] &= eeprom->dev.dat; - } + + nmc93cxx_eeprom_save(eeprom); } } } @@ -252,12 +256,7 @@ static void nmc93cxx_eeprom_close(void *priv) { nmc93cxx_eeprom_t *eeprom = (nmc93cxx_eeprom_t *) priv; - FILE *fp = nvr_fopen(eeprom->filename, "wb"); - if (fp) { - fwrite(eeprom->dev.data, 2, eeprom->size, fp); - fclose(fp); - } - free(priv); + free(eeprom); } uint16_t * diff --git a/src/video/ramdac/vid_ramdac_ibm_rgb528.c b/src/video/ramdac/vid_ramdac_ibm_rgb528.c index cd7d5c1b6..3b59aed70 100644 --- a/src/video/ramdac/vid_ramdac_ibm_rgb528.c +++ b/src/video/ramdac/vid_ramdac_ibm_rgb528.c @@ -83,6 +83,11 @@ typedef struct ibm_rgb528_ramdac_t { uint8_t cursor_array; uint8_t cursor_hotspot_x; uint8_t cursor_hotspot_y; + uint8_t misc_clock; + uint8_t pix_f_ref_div; + uint8_t pix_f[16]; + uint8_t pix_n[8]; + uint8_t pix_m[8]; } ibm_rgb528_ramdac_t; void @@ -606,11 +611,72 @@ ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *s case 0x06: if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) ramdac->indexed_data[ramdac->index] = val; + + switch (ramdac->index) { case 0x00a: case 0x00c: ibm_rgb528_set_bpp(ramdac, svga); break; + case 0x014: + if (ramdac->indexed_data[0x0002] & 0x01) { + switch (ramdac->indexed_data[0x0010]) { + case 0x00: + case 0x02: + ramdac->pix_f_ref_div = val; + break; + default: + break; + } + } + break; + case 0x020: + case 0x022: + case 0x024: + case 0x026: + case 0x028: + case 0x02a: + case 0x02c: + case 0x02e: + if (ramdac->indexed_data[0x0002] & 0x01) { + switch (ramdac->indexed_data[0x0010] & 0x07) { + case 0x00: + case 0x02: + ramdac->pix_f[ramdac->index - 0x0020] = val; + break; + case 0x01: + case 0x03: + ramdac->pix_m[(ramdac->index - 0x0020) >> 1] = val; + break; + default: + break; + } + } + break; + case 0x021: + case 0x023: + case 0x025: + case 0x027: + case 0x029: + case 0x02b: + case 0x02d: + case 0x02f: + if (ramdac->indexed_data[0x0002] & 0x01) { + switch (ramdac->indexed_data[0x010] & 0x07) { + case 0x00: + case 0x02: + ramdac->pix_f[ramdac->index - 0x0020] = val; + break; + case 0x01: + case 0x03: + ramdac->pix_n[(ramdac->index - 0x0020) >> 1] = val; + break; + default: + break; + } + } + break; + case 0x030: switch (val & 0xc0) { case 0x00: @@ -722,7 +788,7 @@ ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *s if (ramdac->indx_cntl) { if (ramdac->index == 0x00ff) ramdac->cursor_array = 0; - ramdac->index = (ramdac->index + 1) & 0x07ff; + ramdac->index++; } break; case 0x07: @@ -794,7 +860,7 @@ ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) if (ramdac->indx_cntl) { if (ramdac->index == 0x00ff) ramdac->cursor_array = 0; - ramdac->index = (ramdac->index + 1) & 0x07ff; + ramdac->index++; } break; case 0x07: @@ -846,6 +912,55 @@ ibm_rgb528_recalctimings(void *priv, svga_t *svga) } } +float +ibm_rgb528_getclock(int clock, void *priv) +{ + const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; + int pll_vco_div_cnt; + int pll_df; + int pll_ref_div_cnt; + int ddot_divs[8] = { 1, 2, 4, 8, 16, 1, 1, 1 }; + int ddot_div = ddot_divs[(ramdac->indexed_data[0x0002] >> 1) & 0x07]; + float f_pll; + + clock &= 0x03; + + if (ramdac->indexed_data[0x0002] & 0x01) { + switch (ramdac->indexed_data[0x0010] & 0x07) { + case 0x00: + default: + pll_vco_div_cnt = ramdac->pix_f[clock] & 0x3f; + pll_df = 8 >> (ramdac->pix_f[clock] >> 6); + pll_ref_div_cnt = ramdac->pix_f_ref_div & 0x1f; + break; + case 0x01: + pll_vco_div_cnt = ramdac->pix_m[clock] & 0x3f; + pll_df = 8 >> (ramdac->pix_m[clock] >> 6); + pll_ref_div_cnt = ramdac->pix_n[clock] & 0x1f; + break; + case 0x02: + pll_vco_div_cnt = ramdac->pix_f[ramdac->indexed_data[0x0011] & 0x0f] & 0x3f; + pll_df = 8 >> (ramdac->pix_f[ramdac->indexed_data[0x0011] & 0x0f] >> 6); + pll_ref_div_cnt = ramdac->pix_f_ref_div & 0x1f; + break; + case 0x03: + pll_vco_div_cnt = ramdac->pix_m[ramdac->indexed_data[0x0011] & 0x07] & 0x3f; + pll_df = 8 >> (ramdac->pix_m[ramdac->indexed_data[0x0011] & 0x07] >> 6); + pll_ref_div_cnt = ramdac->pix_n[ramdac->indexed_data[0x0011] & 0x07] & 0x1f; + break; + } + } else { + pll_vco_div_cnt = ramdac->indexed_data[0x0016] & 0x3f; + pll_df = 8 >> (ramdac->indexed_data[0x0016] >> 6); + pll_ref_div_cnt = ramdac->indexed_data[0x0015] & 0x1f; + } + + f_pll = 28322000.0f * (float) (pll_vco_div_cnt + 65) / (float) (pll_ref_div_cnt * pll_df); + f_pll /= (float) ddot_div; + + return f_pll; +} + void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine) { diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 91b7b097e..d0a098517 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -33,6 +33,8 @@ #include <86box/mem.h> #include <86box/pci.h> #include <86box/rom.h> +#include <86box/net_eeprom_nmc93cxx.h> +#include <86box/nvr.h> #include <86box/plat.h> #include <86box/thread.h> #include <86box/video.h> @@ -196,10 +198,12 @@ typedef struct } fifo_entry_t; typedef struct s3_t { + char nvr_path[128]; mem_mapping_t linear_mapping; mem_mapping_t mmio_mapping; mem_mapping_t new_mmio_mapping; + int elsa_eeprom; uint8_t has_bios; rom_t bios_rom; @@ -393,8 +397,12 @@ typedef struct s3_t { bool color_key_enabled; uint8_t thread_run, serialport; + uint8_t eeprom_inst; + uint16_t eeprom_data[128]; void *i2c, *ddc; + nmc93cxx_eeprom_t *eeprom; + int vram; void (*accel_start)(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv); @@ -2639,7 +2647,7 @@ s3_trio64v_colorkey(s3_t* s3, uint32_t x, uint32_t y) if (!(s3->streams.chroma_ctrl & (1 << 28))) { return true; } - + comp_r = (s3->streams.chroma_ctrl >> 16) & 0xFF; comp_g = (s3->streams.chroma_ctrl >> 8) & 0xFF; comp_b = (s3->streams.chroma_ctrl) & 0xFF; @@ -2648,7 +2656,7 @@ s3_trio64v_colorkey(s3_t* s3, uint32_t x, uint32_t y) if (svga->render == svga_render_24bpp_highres) bytes_per_pel = 3; if (svga->render == svga_render_16bpp_highres) bytes_per_pel = 2; if (svga->render == svga_render_15bpp_highres) { bytes_per_pel = 2; is15bpp = true; } - + switch (bytes_per_pel) { case 1: { uint8_t index = svga->vram[(base_addr + (stride * y) + x * bytes_per_pel) & svga->vram_mask]; @@ -2695,7 +2703,7 @@ s3_trio64v_colorkey(s3_t* s3, uint32_t x, uint32_t y) return !!(r == comp_r && g == comp_g && b == comp_b); } - + static void s3_trio64v_overlay_draw(svga_t *svga, int displine) { @@ -2945,8 +2953,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) switch (addr) { case 0x3c2: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968)) { - if ((s3->card_type != S3_SPEA_MERCURY_P64V) && (s3->card_type != S3_MIROVIDEO40SV_ERGO_968)) { + if (s3->chip == S3_VISION964) { + if (s3->card_type != S3_ELSAWIN2KPROX_964) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); } @@ -3008,7 +3016,11 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x3C9: case 0x3CA: /*0x3c6 alias*/ case 0x3CB: /*0x3c7 alias*/ - rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); + if ((svga->crtc[0x55] & 0x03) == 0x00) + rs2 = !!(svga->crtc[0x43] & 2); + else + rs2 = (svga->crtc[0x55] & 0x01); + // rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); if (s3->chip >= S3_TRIO32) svga_out(addr, val, svga); else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { @@ -3072,8 +3084,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) break; case 0x5c: - if ((val & 0xa0) == 0x80) - i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + if (s3->elsa_eeprom) + nmc93cxx_eeprom_write(s3->eeprom, !!(val & 0x80), !!(val & 0x40), !!(val & 0x10)); if (s3->card_type == S3_PHOENIX_VISION868 || s3->card_type == S3_PHOENIX_VISION968) { if ((val & 0x20) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) svga->dac_addr |= 0x20; @@ -3155,6 +3167,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.x /= 3; else if ((s3->chip <= S3_86C805) && s3->color_16bit) svga->hwcursor.x >>= 1; + else if ((s3->chip == S3_TRIO32) && ((svga->bpp == 15) || (svga->bpp == 16))) + svga->hwcursor.x >>= 1; break; case 0x4a: @@ -3217,9 +3231,11 @@ s3_out(uint16_t addr, uint8_t val, void *priv) if (((svga->miscout >> 2) & 3) == 3) s3_log("[%04X:%08X]: Write CRTC%02x=%02x.\n", CS, cpu_state.pc, svga->crtcreg, svga->crtc[svga->crtcreg]); - if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968)) { - if (((svga->miscout >> 2) & 3) == 3) - icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); + if (s3->chip == S3_VISION964) { + if (s3->card_type != S3_ELSAWIN2KPROX_964) { + if (((svga->miscout >> 2) & 3) == 3) + icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); + } } break; @@ -3304,6 +3320,10 @@ s3_in(uint16_t addr, void *priv) break; case 0x3c2: + if (s3->elsa_eeprom) { + temp = nmc93cxx_eeprom_read(s3->eeprom) ? 0x10 : 0x00; + return (svga_in(addr, svga) & 0xef) | temp; + } if (s3->chip <= S3_86C924) return svga_in(addr, svga) | 0x10; break; @@ -3389,17 +3409,11 @@ s3_in(uint16_t addr, void *priv) case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); case 0x5c: /* General Output Port Register */ - temp = svga->crtc[0x5c] & 0xa0; + temp = svga->crtc[0x5c] & 0xf0; if (((svga->miscout >> 2) & 3) == 3) temp |= svga->crtc[0x42] & 0x0f; else temp |= ((svga->miscout >> 2) & 3); - if ((temp & 0xa0) == 0xa0) { - if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(s3->i2c)) - temp |= 0x40; - if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(s3->i2c)) - temp |= 0x10; - } return temp; case 0x69: return s3->ma_ext; @@ -3613,8 +3627,13 @@ s3_recalctimings(svga_t *svga) svga->vblankstart = svga->dispend; /*Applies only to Enhanced modes*/ if (svga->crtc[0x5e] & 0x10) svga->vsyncstart |= 0x400; + if (svga->crtc[7] & 0x10) + svga->split |= 0x100; + if (svga->crtc[9] & 0x40) + svga->split |= 0x200; if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; + svga->split++; if (s3->accel.advfunc_cntl & 0x01) svga->split = 0x7fff; if (svga->crtc[0x51] & 0x30) @@ -3629,7 +3648,6 @@ s3_recalctimings(svga_t *svga) if ((((svga->miscout >> 2) & 3) == 3) && (s3->chip < S3_TRIO32)) clk_sel = svga->crtc[0x42] & 0x0f; - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { @@ -3809,7 +3827,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -3841,7 +3858,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -3964,7 +3980,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -4000,7 +4015,6 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MERCURY_P64V: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4012,7 +4026,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -4148,7 +4161,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -4171,7 +4183,6 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MERCURY_P64V: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4183,7 +4194,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -4267,7 +4277,6 @@ s3_recalctimings(svga_t *svga) case S3_MIROVIDEO40SV_ERGO_968: svga->hdisp = (svga->hdisp / 3) << 2; svga->dots_per_clock = (svga->hdisp / 3) << 2; - svga->clock /= (2.0 / 3.0); break; default: break; @@ -4324,7 +4333,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -4346,7 +4354,6 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MERCURY_P64V: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4358,7 +4365,6 @@ s3_recalctimings(svga_t *svga) case 1600: svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - svga->clock /= 2.0; break; default: break; @@ -4440,8 +4446,13 @@ s3_trio64v_recalctimings(svga_t *svga) svga->vblankstart |= 0x400; if (svga->crtc[0x5e] & 0x10) svga->vsyncstart |= 0x400; + if (svga->crtc[7] & 0x10) + svga->split |= 0x100; + if (svga->crtc[9] & 0x40) + svga->split |= 0x200; if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; + svga->split++; svga->interlace = svga->crtc[0x42] & 0x20; svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); @@ -6114,9 +6125,10 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *priv) s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_WORD); } else { switch (addr & (addr_mask - 1)) { + case 0x83c8: case 0x83d4: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write(addr, val, s3); + s3_accel_write(addr + 1, val >> 8, s3); break; case 0xff20: s3_accel_write_fifo(s3, addr, val); @@ -9935,6 +9947,27 @@ s3_reset(void *priv) } } +static uint16_t +s3_calc_crc16(int ndata, uint16_t *data) +{ + int i; + int j; + int s; + uint16_t crc16; + uint16_t d; + + crc16 = 0; + for (i = 1; i < ndata; i++) { + d = data[i]; + for (j = 0; j < 16; j++) { + s = (crc16 >> 1) + (crc16 >> 14) + (crc16 >> 15) + d + 1; + crc16 = (crc16 << 1) | (s & 1); + d >>= 1; + } + } + return crc16; +} + static void * s3_init(const device_t *info) { @@ -9946,6 +9979,10 @@ s3_init(const device_t *info) svga_t *svga = &s3->svga; int vram; uint32_t vram_size; + nmc93cxx_eeprom_params_t params; + char eeprom_filename[1024] = { 0 }; + char filename[1024] = { 0 }; + uint16_t checksum; switch (info->local) { case S3_ORCHID_86C911: @@ -10381,6 +10418,8 @@ s3_init(const device_t *info) s3->accel_start = s3_accel_start; + s3->elsa_eeprom = 0; + switch (s3->card_type) { case S3_ORCHID_86C911: case S3_DIAMOND_STEALTH_VRAM: @@ -10444,6 +10483,10 @@ s3_init(const device_t *info) svga->ramdac = device_add(&att491_ramdac_device); svga->clock_gen = device_add(&av9194_device); svga->getclock = av9194_getclock; + if (info->local == S3_WINNER1000_805) { + s3->elsa_eeprom = 1; + sprintf(s3->nvr_path, "s3_elsa_1k_805_%i.nvr", device_get_instance()); + } break; case S3_86C805_ONBOARD: @@ -10532,8 +10575,9 @@ s3_init(const device_t *info) switch (info->local) { case S3_ELSAWIN2KPROX_964: svga->ramdac = device_add(&ibm_rgb528_ramdac_device); - svga->clock_gen = device_add(&icd2061_device); - svga->getclock = icd2061_getclock; + svga->clock_gen = svga->ramdac; + svga->getclock = ibm_rgb528_getclock; + s3->elsa_eeprom = 1; break; default: svga->ramdac = device_add(&bt485_ramdac_device); @@ -10572,8 +10616,11 @@ s3_init(const device_t *info) case S3_PHOENIX_VISION968: case S3_NUMBER9_9FX_771: svga->ramdac = device_add(&ibm_rgb528_ramdac_device); - svga->clock_gen = device_add(&icd2061_device); - svga->getclock = icd2061_getclock; + svga->clock_gen = svga->ramdac; + svga->getclock = ibm_rgb528_getclock; + if (info->local == S3_ELSAWIN2KPROX) { + s3->elsa_eeprom = 1; + } break; default: svga->ramdac = device_add(&tvp3026_ramdac_device); @@ -10682,6 +10729,55 @@ s3_init(const device_t *info) s3->i2c = i2c_gpio_init("ddc_s3"); s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); + + if (s3->elsa_eeprom) { + s3->eeprom_inst = device_get_instance(); + + s3->eeprom_data[0x01] = 0x3353; + + switch (s3->card_type) { + case S3_WINNER1000_805: + s3->eeprom_data[0x02] = 0x091a; + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_s3_winner_1k_805_%d.nvr", s3->eeprom_inst); + break; + case S3_ELSAWIN2KPROX: + s3->eeprom_data[0x02] = 0x094a; + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_s3_winner_2k_pro_x8_968_%d.nvr", s3->eeprom_inst); + break; + case S3_ELSAWIN2KPROX_964: + s3->eeprom_data[0x02] = 0x094a; + snprintf(eeprom_filename, sizeof(eeprom_filename), "eeprom_s3_winner_2k_pro_x8_964_%d.nvr", s3->eeprom_inst); + break; + default: + break; + } + + s3->eeprom_data[0x05] = 0x0040; + s3->eeprom_data[0x07] = 0xf424; + s3->eeprom_data[0x08] = 0xf424; + // s3->eeprom_data[0x09] = 0x0500; + // s3->eeprom_data[0x0b] = 0x0640; + // s3->eeprom_data[0x0c] = 0x04b0; + s3->eeprom_data[0x0b] = 0x0c80; + s3->eeprom_data[0x0c] = 0x0a00; + s3->eeprom_data[0x0d] = 0x0001; + for (uint8_t i = 0; i < 0x32; i++) + s3->eeprom_data[0x0e + i] = 0xffff; + + checksum = s3_calc_crc16(64, s3->eeprom_data); + + s3->eeprom_data[0x00] = checksum; + params.nwords = 64; + params.default_content = s3->eeprom_data; + params.filename = filename; + snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, s3->eeprom_inst); + s3->eeprom = device_add_inst_params(&nmc93cxx_device, s3->eeprom_inst, ¶ms); + if (s3->eeprom == NULL) { + free(s3); + return NULL; + } + } + s3->accel.multifunc[0xd] = 0xd000; s3->accel.multifunc[0xe] = 0xe000; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 13a88a0c5..e0ebfcb6f 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -852,9 +852,14 @@ s3_virge_recalctimings(svga_t *svga) if (svga->crtc[0x5e] & 0x04) svga->vblankstart |= 0x400; if (svga->crtc[0x5e] & 0x10) - svga->vsyncstart |= 0x400; + svga->vsyncstart |= 0x400; + if (svga->crtc[7] & 0x10) + svga->split |= 0x100; + if (svga->crtc[9] & 0x40) + svga->split |= 0x200; if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; + svga->split++; svga->interlace = svga->crtc[0x42] & 0x20; if (((svga->miscout >> 2) & 3) == 3) {