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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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, ¶ms);
|
||||
if (s3->eeprom == NULL) {
|
||||
free(s3);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
s3->accel.multifunc[0xd] = 0xd000;
|
||||
s3->accel.multifunc[0xe] = 0xe000;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user