Implement the ELSA S3 EEPROM, the RGB528 RAMDAC clock selection, and fix split calculation on all the S3 cards (ViRGE included).

This commit is contained in:
OBattler
2025-08-31 19:35:04 +02:00
parent 9ee4d3c701
commit 28d678476d
6 changed files with 285 additions and 63 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 *

View File

@@ -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)
{

View File

@@ -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);
@@ -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, &params);
if (s3->eeprom == NULL) {
free(s3);
return NULL;
}
}
s3->accel.multifunc[0xd] = 0xd000;
s3->accel.multifunc[0xe] = 0xe000;

View File

@@ -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) {