Added TVP3026 clock emulation and hooked up to the corresponding S3 cards needing it.
Added the SPEA Mercury Lite 928PCI-based card and its corresponding accel changes. Restored the S3 ViRGE threaded-FIFO but with small changes.
This commit is contained in:
@@ -274,6 +274,7 @@ extern void tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, voi
|
||||
extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga);
|
||||
extern void tvp3026_recalctimings(void *p, svga_t *svga);
|
||||
extern void tvp3026_hwcursor_draw(svga_t *svga, int displine);
|
||||
extern float tvp3026_getclock(int clock, void *p);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t ati68860_ramdac_device;
|
||||
|
||||
@@ -348,6 +348,7 @@ extern const device_t s3_diamond_stealth_vram_isa_device;
|
||||
extern const device_t s3_ami_86c924_isa_device;
|
||||
extern const device_t s3_metheus_86c928_isa_device;
|
||||
extern const device_t s3_metheus_86c928_vlb_device;
|
||||
extern const device_t s3_spea_mercury_lite_86c928_pci_device;
|
||||
extern const device_t s3_spea_mirage_86c801_isa_device;
|
||||
extern const device_t s3_spea_mirage_86c805_vlb_device;
|
||||
extern const device_t s3_mirocrystal_8s_805_vlb_device;
|
||||
@@ -394,6 +395,7 @@ extern const device_t s3_trio64v2_dx_onboard_pci_device;
|
||||
extern const device_t s3_virge_325_pci_device;
|
||||
extern const device_t s3_diamond_stealth_2000_pci_device;
|
||||
extern const device_t s3_diamond_stealth_3000_pci_device;
|
||||
extern const device_t s3_stb_velocity_3d_pci_device;
|
||||
extern const device_t s3_virge_375_pci_device;
|
||||
extern const device_t s3_diamond_stealth_2000pro_pci_device;
|
||||
extern const device_t s3_virge_385_pci_device;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define ROM_DIAMOND_STEALTH_VRAM "roms/video/s3/Diamond Stealth VRAM BIOS v2.31 U14.BIN"
|
||||
#define ROM_AMI_86C924 "roms/video/s3/S3924AMI.BIN"
|
||||
#define ROM_METHEUS_86C928 "roms/video/s3/928.VBI"
|
||||
#define ROM_SPEA_MERCURY_LITE_PCI "roms/video/s3/SPEAVGA.VBI"
|
||||
#define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI"
|
||||
#define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN"
|
||||
#define ROM_MIROCRYSTAL8S_805 "roms/video/s3/S3_805VL_ATT20C491_miroCRYSTAL_8s_ver1.4.BIN"
|
||||
@@ -104,7 +105,8 @@ enum
|
||||
S3_PHOENIX_VISION968,
|
||||
S3_MIROCRYSTAL8S_805,
|
||||
S3_NUMBER9_9FX_531,
|
||||
S3_NUMBER9_9FX_771
|
||||
S3_NUMBER9_9FX_771,
|
||||
S3_SPEA_MERCURY_LITE_PCI
|
||||
};
|
||||
|
||||
|
||||
@@ -113,22 +115,24 @@ enum
|
||||
S3_86C911 = 0x00,
|
||||
S3_86C924 = 0x02,
|
||||
S3_86C928 = 0x04,
|
||||
S3_86C801 = 0x06,
|
||||
S3_86C805 = 0x07,
|
||||
S3_VISION964 = 0x08,
|
||||
S3_VISION968 = 0x10,
|
||||
S3_VISION864 = 0x18,
|
||||
S3_VISION868 = 0x20,
|
||||
S3_TRIO32 = 0x28,
|
||||
S3_TRIO64 = 0x30,
|
||||
S3_TRIO64V = 0x38,
|
||||
S3_TRIO64V2 = 0x40
|
||||
S3_86C928PCI = 0x06,
|
||||
S3_86C801 = 0x07,
|
||||
S3_86C805 = 0x08,
|
||||
S3_VISION964 = 0x18,
|
||||
S3_VISION968 = 0x20,
|
||||
S3_VISION864 = 0x28,
|
||||
S3_VISION868 = 0x30,
|
||||
S3_TRIO32 = 0x38,
|
||||
S3_TRIO64 = 0x40,
|
||||
S3_TRIO64V = 0x48,
|
||||
S3_TRIO64V2 = 0x50
|
||||
};
|
||||
|
||||
|
||||
static video_timings_t timing_s3_86c911 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35};
|
||||
static video_timings_t timing_s3_86c801 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35};
|
||||
static video_timings_t timing_s3_86c805 = {VIDEO_BUS, 4, 4, 5, 20, 20, 35};
|
||||
static video_timings_t timing_s3_86c928pci = {VIDEO_PCI, 2, 2, 4, 26, 26, 42};
|
||||
static video_timings_t timing_s3_stealth64_vlb = {VIDEO_BUS, 2, 2, 4, 26, 26, 42};
|
||||
static video_timings_t timing_s3_stealth64_pci = {VIDEO_PCI, 2, 2, 4, 26, 26, 42};
|
||||
static video_timings_t timing_s3_vision864_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, 35};
|
||||
@@ -563,7 +567,7 @@ static void
|
||||
s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
|
||||
{
|
||||
svga_t *svga = &s3->svga;
|
||||
|
||||
|
||||
if (s3->accel.cmd & 0x100) {
|
||||
switch (s3->accel.cmd & 0x600) {
|
||||
case 0x000:
|
||||
@@ -1173,7 +1177,8 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
if (s3->chip != S3_86C928PCI)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1197,7 +1202,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
}
|
||||
break;
|
||||
case 0x200:
|
||||
/*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/
|
||||
/*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928 ISA/VLB*/
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
@@ -1205,7 +1210,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
else
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
|
||||
} else {
|
||||
if (s3->chip == S3_86C928)
|
||||
if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
@@ -1214,6 +1219,15 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8));
|
||||
else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x400:
|
||||
@@ -1261,7 +1275,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
break;
|
||||
case 0x200:
|
||||
/*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/
|
||||
/*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928 ISA/VLB card*/
|
||||
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
|
||||
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
@@ -1269,7 +1283,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
else
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
|
||||
} else {
|
||||
if (s3->chip == S3_86C928)
|
||||
if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
|
||||
else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
@@ -1278,6 +1292,15 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s3->chip == S3_86C928 || s3->chip == S3_86C928PCI)
|
||||
s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8));
|
||||
else {
|
||||
if (s3->accel.cmd & 0x1000)
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x400:
|
||||
@@ -1360,7 +1383,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
|
||||
if ((addr >= 0x08000) && (addr <= 0x0803f))
|
||||
s3_pci_write(0, addr & 0xff, val, s3);
|
||||
}
|
||||
|
||||
|
||||
switch (addr & 0x1fffe) {
|
||||
case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/
|
||||
case 0x8102: addr = 0x86e8; break;
|
||||
@@ -2405,8 +2428,10 @@ s3_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
case 0x3c2:
|
||||
if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) {
|
||||
if (((val >> 2) & 3) != 3)
|
||||
icd2061_write(svga->clock_gen, (val >> 2) & 3);
|
||||
if ((s3->card_type != S3_SPEA_MERCURY_P64V) && (s3->card_type != S3_MIROVIDEO40SV_ERGO_968)) {
|
||||
if (((val >> 2) & 3) != 3)
|
||||
icd2061_write(svga->clock_gen, (val >> 2) & 3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2472,6 +2497,8 @@ s3_out(uint16_t addr, uint8_t val, void *p)
|
||||
sc1148x_ramdac_out(addr, rs2, val, svga->ramdac, svga);
|
||||
} else if (s3->card_type == S3_NUMBER9_9FX_531)
|
||||
att498_ramdac_out(addr, rs2, val, svga->ramdac, svga);
|
||||
else if ((s3->chip == S3_86C928PCI) && (s3->card_type == S3_SPEA_MERCURY_LITE_PCI))
|
||||
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
|
||||
else
|
||||
sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga);
|
||||
return;
|
||||
@@ -2760,6 +2787,8 @@ s3_in(uint16_t addr, void *p)
|
||||
return sc1148x_ramdac_in(addr, rs2, svga->ramdac, svga);
|
||||
else if (s3->card_type == S3_NUMBER9_9FX_531)
|
||||
return att498_ramdac_in(addr, rs2, svga->ramdac, svga);
|
||||
else if ((s3->chip == S3_86C928PCI) && (s3->card_type == S3_SPEA_MERCURY_LITE_PCI))
|
||||
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
|
||||
else
|
||||
return sdac_ramdac_in(addr, rs2, svga->ramdac, svga);
|
||||
break;
|
||||
@@ -2880,7 +2909,7 @@ static void s3_recalctimings(svga_t *svga)
|
||||
if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 ||
|
||||
s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 ||
|
||||
s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 ||
|
||||
s3->card_type == S3_NUMBER9_9FX_531) {
|
||||
s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) {
|
||||
if (!(svga->crtc[0x5e] & 0x04))
|
||||
svga->vblankstart = svga->dispend;
|
||||
if (svga->bpp != 32) {
|
||||
@@ -3006,7 +3035,8 @@ static void s3_recalctimings(svga_t *svga)
|
||||
svga->hdisp = s3->width;
|
||||
}
|
||||
|
||||
if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805)
|
||||
if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 ||
|
||||
s3->card_type == S3_SPEA_MERCURY_LITE_PCI)
|
||||
svga->hdisp = s3->width;
|
||||
break;
|
||||
case 16:
|
||||
@@ -3034,7 +3064,8 @@ static void s3_recalctimings(svga_t *svga)
|
||||
svga->hdisp = s3->width;
|
||||
}
|
||||
|
||||
if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805)
|
||||
if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 ||
|
||||
s3->card_type == S3_SPEA_MERCURY_LITE_PCI)
|
||||
svga->hdisp = s3->width;
|
||||
break;
|
||||
case 24:
|
||||
@@ -3044,6 +3075,15 @@ static void s3_recalctimings(svga_t *svga)
|
||||
svga->hdisp /= 3;
|
||||
else
|
||||
svga->hdisp = (svga->hdisp * 2) / 3;
|
||||
|
||||
if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) {
|
||||
if (s3->width == 2048)
|
||||
switch (svga->dispend) {
|
||||
case 480:
|
||||
svga->hdisp = 640;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 ||
|
||||
s3->card_type == S3_SPEA_MERCURY_P64V)
|
||||
@@ -3085,7 +3125,7 @@ static void s3_recalctimings(svga_t *svga)
|
||||
s3->width = 800;
|
||||
svga->hdisp = 800;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3292,6 +3332,7 @@ s3_updatemapping(s3_t *s3)
|
||||
case S3_TRIO64V:
|
||||
case S3_TRIO64V2:
|
||||
case S3_86C928:
|
||||
case S3_86C928PCI:
|
||||
s3->linear_size = 0x400000;
|
||||
break;
|
||||
default:
|
||||
@@ -3842,8 +3883,9 @@ s3_accel_in(uint16_t port, void *p)
|
||||
s3_accel_start(16, 1, s3->accel.pix_trans[0], 0, s3);
|
||||
else
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
|
||||
} else
|
||||
} else {
|
||||
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5235,7 +5277,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
|
||||
/*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
|
||||
When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
|
||||
the NOP command)*/
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case 0: /*NOP (Short Stroke Vectors)*/
|
||||
@@ -6129,8 +6170,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
|
||||
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
|
||||
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
|
||||
|
||||
|
||||
|
||||
while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2))
|
||||
{
|
||||
int y = s3->accel.poly_cy;
|
||||
@@ -6278,7 +6317,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
|
||||
|
||||
ROPMIX
|
||||
|
||||
if (s3->accel.cmd & 0x10) {
|
||||
if (s3->accel.cmd & 0x10) {
|
||||
WRITE(s3->accel.dest + s3->accel.dx, out);
|
||||
}
|
||||
}
|
||||
@@ -6615,6 +6654,7 @@ static void s3_reset(void *priv)
|
||||
break;
|
||||
|
||||
case S3_METHEUS_86C928:
|
||||
case S3_SPEA_MERCURY_LITE_PCI:
|
||||
svga->crtc[0x5a] = 0x0a;
|
||||
break;
|
||||
|
||||
@@ -6763,6 +6803,11 @@ static void *s3_init(const device_t *info)
|
||||
else
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801);
|
||||
break;
|
||||
case S3_SPEA_MERCURY_LITE_PCI:
|
||||
bios_fn = ROM_SPEA_MERCURY_LITE_PCI;
|
||||
chip = S3_86C928PCI;
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c928pci);
|
||||
break;
|
||||
case S3_MIROCRYSTAL20SD_864:
|
||||
bios_fn = ROM_MIROCRYSTAL20SD_864_VLB;
|
||||
chip = S3_VISION864;
|
||||
@@ -7159,7 +7204,20 @@ static void *s3_init(const device_t *info)
|
||||
svga->ramdac = device_add(&bt485_ramdac_device);
|
||||
svga->clock_gen = device_add(&icd2061_device);
|
||||
svga->getclock = icd2061_getclock;
|
||||
break;
|
||||
break;
|
||||
|
||||
case S3_SPEA_MERCURY_LITE_PCI:
|
||||
svga->decode_mask = (4 << 20) - 1;
|
||||
stepping = 0xb0; /*86C928PCI*/
|
||||
s3->id = stepping;
|
||||
s3->id_ext = stepping;
|
||||
s3->id_ext_pci = stepping;
|
||||
s3->packed_mmio = 0;
|
||||
svga->crtc[0x5a] = 0x0a;
|
||||
svga->ramdac = device_add(&sc1502x_ramdac_device);
|
||||
svga->clock_gen = device_add(&av9194_device);
|
||||
svga->getclock = av9194_getclock;
|
||||
break;
|
||||
|
||||
case S3_PARADISE_BAHAMAS64:
|
||||
case S3_PHOENIX_VISION864:
|
||||
@@ -7219,13 +7277,15 @@ static void *s3_init(const device_t *info)
|
||||
}
|
||||
|
||||
if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968 ||
|
||||
info->local == S3_NUMBER9_9FX_771)
|
||||
info->local == S3_NUMBER9_9FX_771) {
|
||||
svga->ramdac = device_add(&ibm_rgb528_ramdac_device);
|
||||
else
|
||||
svga->clock_gen = device_add(&icd2061_device);
|
||||
svga->getclock = icd2061_getclock;
|
||||
} else {
|
||||
svga->ramdac = device_add(&tvp3026_ramdac_device);
|
||||
|
||||
svga->clock_gen = device_add(&icd2061_device);
|
||||
svga->getclock = icd2061_getclock;
|
||||
svga->clock_gen = svga->ramdac;
|
||||
svga->getclock = tvp3026_getclock;
|
||||
}
|
||||
break;
|
||||
|
||||
case S3_NUMBER9_9FX_531:
|
||||
@@ -7380,6 +7440,11 @@ static int s3_metheus_86c928_available(void)
|
||||
return rom_present(ROM_METHEUS_86C928);
|
||||
}
|
||||
|
||||
static int s3_spea_mercury_lite_pci_available(void)
|
||||
{
|
||||
return rom_present(ROM_SPEA_MERCURY_LITE_PCI);
|
||||
}
|
||||
|
||||
static int s3_bahamas64_available(void)
|
||||
{
|
||||
return rom_present(ROM_PARADISE_BAHAMAS64);
|
||||
@@ -7796,6 +7861,20 @@ const device_t s3_metheus_86c928_vlb_device =
|
||||
s3_standard_config
|
||||
};
|
||||
|
||||
const device_t s3_spea_mercury_lite_86c928_pci_device =
|
||||
{
|
||||
"S3 86c928 PCI (SPEA Mercury Lite)",
|
||||
DEVICE_PCI,
|
||||
S3_SPEA_MERCURY_LITE_PCI,
|
||||
s3_init,
|
||||
s3_close,
|
||||
s3_reset,
|
||||
{ s3_spea_mercury_lite_pci_available },
|
||||
s3_speed_changed,
|
||||
s3_force_redraw,
|
||||
s3_standard_config
|
||||
};
|
||||
|
||||
const device_t s3_mirocrystal_20sd_864_vlb_device =
|
||||
{
|
||||
"S3 Vision864 VLB (MiroCRYSTAL 20SD)",
|
||||
|
||||
@@ -61,7 +61,7 @@ static int dither[4][4] =
|
||||
#define FIFO_ENTRY_SIZE (1 << 31)
|
||||
|
||||
#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx)
|
||||
#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= FIFO_SIZE)
|
||||
#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= (FIFO_SIZE - 4))
|
||||
#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx)
|
||||
|
||||
#define FIFO_TYPE 0xff000000
|
||||
@@ -70,6 +70,7 @@ static int dither[4][4] =
|
||||
#define ROM_VIRGE_325 "roms/video/s3virge/86c325.bin"
|
||||
#define ROM_DIAMOND_STEALTH3D_2000 "roms/video/s3virge/s3virge.bin"
|
||||
#define ROM_DIAMOND_STEALTH3D_3000 "roms/video/s3virge/diamondstealth3000.vbi"
|
||||
#define ROM_STB_VELOCITY_3D "roms/video/s3virge/stb_velocity3d_110.BIN"
|
||||
#define ROM_VIRGE_DX "roms/video/s3virge/86c375_1.bin"
|
||||
#define ROM_DIAMOND_STEALTH3D_2000PRO "roms/video/s3virge/virgedxdiamond.vbi"
|
||||
#define ROM_VIRGE_GX "roms/video/s3virge/86c375_4.bin"
|
||||
@@ -82,6 +83,7 @@ enum
|
||||
S3_VIRGE_325,
|
||||
S3_DIAMOND_STEALTH3D_2000,
|
||||
S3_DIAMOND_STEALTH3D_3000,
|
||||
S3_STB_VELOCITY_3D,
|
||||
S3_VIRGE_DX,
|
||||
S3_DIAMOND_STEALTH3D_2000PRO,
|
||||
S3_VIRGE_GX,
|
||||
@@ -288,7 +290,6 @@ typedef struct virge_t
|
||||
int sec_x, sec_y, sec_w, sec_h;
|
||||
} streams;
|
||||
|
||||
int fifo_slot;
|
||||
uint8_t cmd_dma;
|
||||
uint8_t dma_bs;
|
||||
uint32_t cmd_dma_base;
|
||||
@@ -302,6 +303,10 @@ typedef struct virge_t
|
||||
fifo_entry_t fifo[FIFO_SIZE];
|
||||
volatile int fifo_read_idx, fifo_write_idx;
|
||||
|
||||
thread_t *fifo_thread;
|
||||
event_t *wake_fifo_thread;
|
||||
event_t *fifo_not_full_event;
|
||||
|
||||
int virge_busy, local;
|
||||
|
||||
uint8_t subsys_stat, subsys_cntl, advfunc_cntl;
|
||||
@@ -417,6 +422,11 @@ s3_virge_tri_timer(void *p)
|
||||
thread_set_event(virge->wake_render_thread); /*Wake up FIFO thread if moving from idle*/
|
||||
}
|
||||
|
||||
static __inline void
|
||||
wake_fifo_thread(virge_t *virge)
|
||||
{
|
||||
thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
|
||||
}
|
||||
|
||||
static void
|
||||
queue_triangle(virge_t *virge)
|
||||
@@ -970,7 +980,8 @@ static void s3_virge_updatemapping(virge_t *virge)
|
||||
mem_mapping_disable(&virge->new_mmio_mapping);
|
||||
}
|
||||
|
||||
static void s3_virge_vblank_start(svga_t *svga)
|
||||
static void
|
||||
s3_virge_vblank_start(svga_t *svga)
|
||||
{
|
||||
virge_t *virge = (virge_t *)svga->p;
|
||||
|
||||
@@ -978,6 +989,16 @@ static void s3_virge_vblank_start(svga_t *svga)
|
||||
s3_virge_update_irqs(virge);
|
||||
}
|
||||
|
||||
static void
|
||||
s3_virge_wait_fifo_idle(virge_t *virge)
|
||||
{
|
||||
while (!FIFO_EMPTY)
|
||||
{
|
||||
wake_fifo_thread(virge);
|
||||
thread_wait_event(virge->fifo_not_full_event, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
s3_virge_mmio_read(uint32_t addr, void *p)
|
||||
{
|
||||
@@ -989,14 +1010,12 @@ s3_virge_mmio_read(uint32_t addr, void *p)
|
||||
switch (addr & 0xffff)
|
||||
{
|
||||
case 0x8505:
|
||||
ret = 0;
|
||||
if (virge->s3d_busy || virge->fifo_slot) {
|
||||
ret = 0x10;
|
||||
} else {
|
||||
ret = 0x30;
|
||||
}
|
||||
if (virge->fifo_slot)
|
||||
virge->fifo_slot--;
|
||||
if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY)
|
||||
ret = 0x10;
|
||||
else
|
||||
ret = 0x10 | (1 << 5);
|
||||
if (!virge->virge_busy)
|
||||
wake_fifo_thread(virge);
|
||||
return ret;
|
||||
|
||||
case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3:
|
||||
@@ -1014,6 +1033,7 @@ s3_virge_mmio_read(uint32_t addr, void *p)
|
||||
return s3_virge_in(addr & 0x3ff, virge);
|
||||
|
||||
case 0x859c:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
return virge->cmd_dma;
|
||||
|
||||
case 0xff20: case 0xff21:
|
||||
@@ -1030,22 +1050,21 @@ static uint16_t
|
||||
s3_virge_mmio_read_w(uint32_t addr, void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
uint32_t ret = 0xffff;
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
s3_virge_log("[%04X:%08X]: MMIO ReadW addr = %04x\n", CS, cpu_state.pc, addr & 0xfffe);
|
||||
|
||||
switch (addr & 0xfffe) {
|
||||
case 0x8504:
|
||||
if (!virge->fifo_slot)
|
||||
if (FIFO_EMPTY)
|
||||
virge->subsys_stat |= INT_FIFO_EMP;
|
||||
ret |= virge->subsys_stat;
|
||||
if (virge->fifo_slot)
|
||||
virge->fifo_slot--;
|
||||
ret |= 0x30; /*A bit of a workaround at the moment.*/
|
||||
s3_virge_update_irqs(virge);
|
||||
return ret;
|
||||
return ret;
|
||||
|
||||
case 0x859c:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
return virge->cmd_dma;
|
||||
|
||||
default:
|
||||
@@ -1134,78 +1153,91 @@ s3_virge_mmio_read_l(uint32_t addr, void *p)
|
||||
break;
|
||||
|
||||
case 0x8504:
|
||||
if (virge->s3d_busy || virge->fifo_slot) {
|
||||
if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY)
|
||||
ret = (0x10 << 8);
|
||||
} else {
|
||||
else
|
||||
ret = (0x10 << 8) | (1 << 13);
|
||||
if (!virge->s3d_busy)
|
||||
virge->subsys_stat |= INT_3DF_EMP;
|
||||
if (!virge->fifo_slot)
|
||||
virge->subsys_stat |= INT_FIFO_EMP;
|
||||
}
|
||||
ret |= virge->subsys_stat;
|
||||
if (virge->fifo_slot)
|
||||
virge->fifo_slot--;
|
||||
s3_virge_update_irqs(virge);
|
||||
if (!virge->virge_busy)
|
||||
wake_fifo_thread(virge);
|
||||
dmahdr->dblword_read = 0;
|
||||
dmahdr->dblword_write = 0;
|
||||
break;
|
||||
|
||||
case 0x8590:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->cmd_dma_base;
|
||||
break;
|
||||
case 0x8594:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
break;
|
||||
case 0x8598:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->dma_ptr;
|
||||
break;
|
||||
case 0x859c:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->cmd_dma;
|
||||
break;
|
||||
|
||||
case 0xa4d4:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.src_base;
|
||||
break;
|
||||
case 0xa4d8:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.dest_base;
|
||||
break;
|
||||
case 0xa4dc:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r;
|
||||
break;
|
||||
case 0xa4e0:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b;
|
||||
break;
|
||||
case 0xa4e4:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str;
|
||||
break;
|
||||
case 0xa4e8: case 0xace8:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.mono_pat_0;
|
||||
break;
|
||||
case 0xa4ec: case 0xacec:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.mono_pat_1;
|
||||
break;
|
||||
case 0xa4f0:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.pat_bg_clr;
|
||||
break;
|
||||
case 0xa4f4:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.pat_fg_clr;
|
||||
break;
|
||||
case 0xa4f8:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.src_bg_clr;
|
||||
break;
|
||||
case 0xa4fc:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.src_fg_clr;
|
||||
break;
|
||||
case 0xa500:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = virge->s3d.cmd_set;
|
||||
break;
|
||||
case 0xa504:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = (virge->s3d.r_width << 16) | virge->s3d.r_height;
|
||||
break;
|
||||
case 0xa508:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y;
|
||||
break;
|
||||
case 0xa50c:
|
||||
s3_virge_wait_fifo_idle(virge);
|
||||
ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y;
|
||||
break;
|
||||
|
||||
@@ -1242,14 +1274,96 @@ s3_virge_mmio_read_l(uint32_t addr, void *p)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
fifo_thread(void *param)
|
||||
{
|
||||
virge_t *virge = (virge_t *)param;
|
||||
|
||||
static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
while (virge->fifo_thread_run)
|
||||
{
|
||||
thread_set_event(virge->fifo_not_full_event);
|
||||
thread_wait_event(virge->wake_fifo_thread, -1);
|
||||
thread_reset_event(virge->wake_fifo_thread);
|
||||
virge->virge_busy = 1;
|
||||
while (!FIFO_EMPTY)
|
||||
{
|
||||
uint64_t start_time = plat_timer_read();
|
||||
uint64_t end_time;
|
||||
uint32_t addr, val;
|
||||
fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK];
|
||||
addr = fifo->addr_type & FIFO_ADDR;
|
||||
val = fifo->val;
|
||||
|
||||
switch (fifo->addr_type & FIFO_TYPE)
|
||||
{
|
||||
case FIFO_WRITE_BYTE:
|
||||
if ((addr & 0xfffc) < 0x8000)
|
||||
s3_virge_bitblt(virge, 8, val);
|
||||
break;
|
||||
case FIFO_WRITE_WORD:
|
||||
if ((addr & 0xfffc) < 0x8000)
|
||||
{
|
||||
if (virge->s3d.cmd_set & CMD_SET_MS)
|
||||
s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16);
|
||||
else
|
||||
s3_virge_bitblt(virge, 16, val);
|
||||
}
|
||||
break;
|
||||
case FIFO_WRITE_DWORD:
|
||||
if ((addr & 0xfffc) < 0x8000)
|
||||
{
|
||||
if (virge->s3d.cmd_set & CMD_SET_MS)
|
||||
s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
|
||||
else
|
||||
s3_virge_bitblt(virge, 32, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
virge->fifo_read_idx++;
|
||||
fifo->addr_type = FIFO_INVALID;
|
||||
|
||||
if (FIFO_ENTRIES > 0xe000)
|
||||
thread_set_event(virge->fifo_not_full_event);
|
||||
|
||||
end_time = plat_timer_read();
|
||||
virge_time += end_time - start_time;
|
||||
}
|
||||
virge->virge_busy = 0;
|
||||
virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP;
|
||||
s3_virge_update_irqs(virge);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)
|
||||
{
|
||||
fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK];
|
||||
|
||||
if (FIFO_FULL)
|
||||
{
|
||||
thread_reset_event(virge->fifo_not_full_event);
|
||||
if (FIFO_FULL)
|
||||
thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
|
||||
}
|
||||
|
||||
fifo->val = val;
|
||||
fifo->addr_type = (addr & FIFO_ADDR) | type;
|
||||
|
||||
virge->fifo_write_idx++;
|
||||
|
||||
if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8)
|
||||
wake_fifo_thread(virge);
|
||||
}
|
||||
|
||||
static void
|
||||
s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
s3_virge_log("MMIO WriteB addr = %04x, val = %02x\n", addr & 0xffff, val);
|
||||
|
||||
if ((addr & 0xffff) < 0x8000) {
|
||||
s3_virge_bitblt(virge, 8, val);
|
||||
s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE);
|
||||
} else {
|
||||
switch (addr & 0xffff) {
|
||||
case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3:
|
||||
@@ -1286,10 +1400,7 @@ s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p)
|
||||
s3_virge_log("[%04X:%08X]: MMIO WriteW addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffe, val);
|
||||
|
||||
if ((addr & 0xfffe) < 0x8000) {
|
||||
if (virge->s3d.cmd_set & CMD_SET_MS)
|
||||
s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16);
|
||||
else
|
||||
s3_virge_bitblt(virge, 16, val);
|
||||
s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD);
|
||||
} else {
|
||||
if ((addr & 0xfffe) == 0x83d4) {
|
||||
s3_virge_mmio_write(addr, val, virge);
|
||||
@@ -1310,17 +1421,19 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
||||
|
||||
s3_virge_log("MMIO WriteL addr = %04x, val = %08x\n", addr & 0xfffc, val);
|
||||
if ((addr & 0xfffc) < 0x8000) {
|
||||
if ((addr & 0xe000) == 0) {
|
||||
if (virge->s3d.cmd_set & CMD_SET_MS)
|
||||
s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
|
||||
else
|
||||
s3_virge_bitblt(virge, 32, val);
|
||||
s3_virge_bitblt(virge, 32, val);
|
||||
} else {
|
||||
s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD);
|
||||
}
|
||||
|
||||
if (virge->cmd_dma) {
|
||||
dmahdr->datatype = 1;
|
||||
}
|
||||
} else {
|
||||
if ((addr & 0xfffc) >= 0xa000)
|
||||
virge->fifo_slot++;
|
||||
if (virge->cmd_dma) {
|
||||
dmahdr->datatype = 0;
|
||||
}
|
||||
@@ -3875,6 +3988,7 @@ static void s3_virge_reset(void *priv)
|
||||
virge->svga.crtc[0x59] = 0x70;
|
||||
break;
|
||||
case S3_DIAMOND_STEALTH3D_3000:
|
||||
case S3_STB_VELOCITY_3D:
|
||||
virge->svga.crtc[0x59] = 0x70;
|
||||
break;
|
||||
case S3_VIRGE_GX2:
|
||||
@@ -3950,6 +4064,9 @@ static void *s3_virge_init(const device_t *info)
|
||||
case S3_DIAMOND_STEALTH3D_3000:
|
||||
bios_fn = ROM_DIAMOND_STEALTH3D_3000;
|
||||
break;
|
||||
case S3_STB_VELOCITY_3D:
|
||||
bios_fn = ROM_STB_VELOCITY_3D;
|
||||
break;
|
||||
case S3_VIRGE_DX:
|
||||
bios_fn = ROM_VIRGE_DX;
|
||||
break;
|
||||
@@ -4041,6 +4158,7 @@ static void *s3_virge_init(const device_t *info)
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_diamond_stealth3d_2000_pci);
|
||||
break;
|
||||
case S3_DIAMOND_STEALTH3D_3000:
|
||||
case S3_STB_VELOCITY_3D:
|
||||
virge->svga.decode_mask = (8 << 20) - 1;
|
||||
virge->virge_id_high = 0x88;
|
||||
virge->virge_id_low = 0x3d;
|
||||
@@ -4135,6 +4253,11 @@ static void *s3_virge_init(const device_t *info)
|
||||
virge->render_thread_run = 1;
|
||||
virge->render_thread = thread_create(render_thread, virge);
|
||||
|
||||
virge->wake_fifo_thread = thread_create_event();
|
||||
virge->fifo_not_full_event = thread_create_event();
|
||||
virge->fifo_thread_run = 1;
|
||||
virge->fifo_thread = thread_create(fifo_thread, virge);
|
||||
|
||||
timer_add(&virge->tri_timer, s3_virge_tri_timer, virge, 0);
|
||||
|
||||
virge->local = info->local;
|
||||
@@ -4153,6 +4276,12 @@ static void s3_virge_close(void *p)
|
||||
thread_destroy_event(virge->wake_main_thread);
|
||||
thread_destroy_event(virge->wake_render_thread);
|
||||
|
||||
virge->fifo_thread_run = 0;
|
||||
thread_set_event(virge->wake_fifo_thread);
|
||||
thread_wait(virge->fifo_thread);
|
||||
thread_destroy_event(virge->wake_fifo_thread);
|
||||
thread_destroy_event(virge->fifo_not_full_event);
|
||||
|
||||
svga_close(&virge->svga);
|
||||
|
||||
ddc_close(virge->ddc);
|
||||
@@ -4176,6 +4305,11 @@ static int s3_virge_988_diamond_available(void)
|
||||
return rom_present(ROM_DIAMOND_STEALTH3D_3000);
|
||||
}
|
||||
|
||||
static int s3_virge_988_stb_available(void)
|
||||
{
|
||||
return rom_present(ROM_STB_VELOCITY_3D);
|
||||
}
|
||||
|
||||
static int s3_virge_375_available(void)
|
||||
{
|
||||
return rom_present(ROM_VIRGE_DX);
|
||||
@@ -4302,6 +4436,20 @@ const device_t s3_diamond_stealth_3000_pci_device =
|
||||
s3_virge_config
|
||||
};
|
||||
|
||||
const device_t s3_stb_velocity_3d_pci_device =
|
||||
{
|
||||
"S3 ViRGE/VX (STB Velocity 3D) PCI",
|
||||
DEVICE_PCI,
|
||||
S3_STB_VELOCITY_3D,
|
||||
s3_virge_init,
|
||||
s3_virge_close,
|
||||
s3_virge_reset,
|
||||
{ s3_virge_988_stb_available },
|
||||
s3_virge_speed_changed,
|
||||
s3_virge_force_redraw,
|
||||
s3_virge_config
|
||||
};
|
||||
|
||||
const device_t s3_virge_375_pci_device =
|
||||
{
|
||||
"S3 ViRGE/DX (375) PCI",
|
||||
|
||||
@@ -138,6 +138,7 @@ video_cards[] = {
|
||||
{ "cl_gd5480_pci", &gd5480_pci_device },
|
||||
{ "ctl3d_banshee_pci", &creative_voodoo_banshee_device },
|
||||
{ "stealth32_pci", &et4000w32p_pci_device },
|
||||
{ "spea_mercurylite_pci", &s3_spea_mercury_lite_86c928_pci_device },
|
||||
{ "stealth64v_pci", &s3_diamond_stealth64_964_pci_device },
|
||||
{ "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device },
|
||||
{ "mirocrystal20sv_pci", &s3_mirocrystal_20sv_964_pci_device },
|
||||
@@ -160,6 +161,7 @@ video_cards[] = {
|
||||
{ "virge325_pci", &s3_virge_325_pci_device },
|
||||
{ "stealth3d_2000_pci", &s3_diamond_stealth_2000_pci_device },
|
||||
{ "stealth3d_3000_pci", &s3_diamond_stealth_3000_pci_device },
|
||||
{ "stb_velocity3d_pci", &s3_stb_velocity_3d_pci_device },
|
||||
{ "virge375_pci", &s3_virge_375_pci_device },
|
||||
{ "stealth3d_2000pro_pci", &s3_diamond_stealth_2000pro_pci_device },
|
||||
{ "virge385_pci", &s3_virge_385_pci_device },
|
||||
|
||||
@@ -47,6 +47,12 @@ typedef struct
|
||||
uint8_t misc;
|
||||
uint8_t type;
|
||||
uint8_t mode;
|
||||
uint8_t pll_addr;
|
||||
uint8_t clock_sel;
|
||||
struct
|
||||
{
|
||||
uint8_t m, n, p;
|
||||
} pix, mem, loop;
|
||||
} tvp3026_ramdac_t;
|
||||
|
||||
static void
|
||||
@@ -96,7 +102,6 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
ramdac->ind_idx = val;
|
||||
@@ -152,7 +157,7 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
|
||||
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
|
||||
svga->dac_hwcursor.ena = ((val & 0x03) != 0);
|
||||
svga->dac_hwcursor.ena = !!(val & 0x03);
|
||||
ramdac->mode = val & 0x03;
|
||||
}
|
||||
break;
|
||||
@@ -163,7 +168,7 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
|
||||
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
|
||||
svga->dac_hwcursor.ena = ((val & 0x03) != 0);
|
||||
svga->dac_hwcursor.ena = !!(val & 0x03);
|
||||
ramdac->mode = val & 0x03;
|
||||
break;
|
||||
case 0x0f: /* Latch Control */
|
||||
@@ -177,6 +182,9 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
|
||||
ramdac->mcr = val;
|
||||
tvp3026_set_bpp(ramdac, svga);
|
||||
break;
|
||||
case 0x1a: /* Clock Selection */
|
||||
ramdac->clock_sel = val;
|
||||
break;
|
||||
case 0x1c: /* Palette-Page Register */
|
||||
ramdac->ppr = val;
|
||||
break;
|
||||
@@ -187,6 +195,51 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
|
||||
ramdac->misc = val;
|
||||
svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT;
|
||||
break;
|
||||
case 0x2c: /* PLL Address */
|
||||
ramdac->pll_addr = val;
|
||||
break;
|
||||
case 0x2d: /* Pixel clock PLL data */
|
||||
switch (ramdac->pll_addr & 3) {
|
||||
case 0:
|
||||
ramdac->pix.n = val;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->pix.m = val;
|
||||
break;
|
||||
case 2:
|
||||
ramdac->pix.p = val;
|
||||
break;
|
||||
}
|
||||
ramdac->pll_addr = ((ramdac->pll_addr + 1) & 3) | (ramdac->pll_addr & 0xfc);
|
||||
break;
|
||||
case 0x2e: /* Memory Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 2) & 3) {
|
||||
case 0:
|
||||
ramdac->mem.n = val;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->mem.m = val;
|
||||
break;
|
||||
case 2:
|
||||
ramdac->mem.p = val;
|
||||
break;
|
||||
}
|
||||
ramdac->pll_addr = ((ramdac->pll_addr + 4) & 0x0c) | (ramdac->pll_addr & 0xf3);
|
||||
break;
|
||||
case 0x2f: /* Loop Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 4) & 3) {
|
||||
case 0:
|
||||
ramdac->loop.n = val;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->loop.m = val;
|
||||
break;
|
||||
case 2:
|
||||
ramdac->loop.p = val;
|
||||
break;
|
||||
}
|
||||
ramdac->pll_addr = ((ramdac->pll_addr + 0x10) & 0x30) | (ramdac->pll_addr & 0xcf);
|
||||
break;
|
||||
case 0x39: /* MCLK/Loop Clock Control */
|
||||
ramdac->mclk = val;
|
||||
break;
|
||||
@@ -292,6 +345,9 @@ tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga)
|
||||
case 0x19: /* Multiplex Control */
|
||||
temp = ramdac->mcr;
|
||||
break;
|
||||
case 0x1a: /* Clock Selection */
|
||||
temp = ramdac->clock_sel;
|
||||
break;
|
||||
case 0x1c: /* Palette-Page Register */
|
||||
temp = ramdac->ppr;
|
||||
break;
|
||||
@@ -301,6 +357,54 @@ tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga)
|
||||
case 0x1e: /* Miscellaneous Control */
|
||||
temp = ramdac->misc;
|
||||
break;
|
||||
case 0x2c: /* PLL Address */
|
||||
temp = ramdac->pll_addr;
|
||||
break;
|
||||
case 0x2d: /* Pixel clock PLL data */
|
||||
switch (ramdac->pll_addr & 3) {
|
||||
case 0:
|
||||
temp = ramdac->pix.n;
|
||||
break;
|
||||
case 1:
|
||||
temp = ramdac->pix.m;
|
||||
break;
|
||||
case 2:
|
||||
temp = ramdac->pix.p;
|
||||
break;
|
||||
case 3:
|
||||
temp = 0x40; /*PLL locked to frequency*/
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2e: /* Memory Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 2) & 3) {
|
||||
case 0:
|
||||
temp = ramdac->mem.n;
|
||||
break;
|
||||
case 1:
|
||||
temp = ramdac->mem.m;
|
||||
break;
|
||||
case 2:
|
||||
temp = ramdac->mem.p;
|
||||
break;
|
||||
case 3:
|
||||
temp = 0x40; /*PLL locked to frequency*/
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2f: /* Loop Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 4) & 3) {
|
||||
case 0:
|
||||
temp = ramdac->loop.n;
|
||||
break;
|
||||
case 1:
|
||||
temp = ramdac->loop.m;
|
||||
break;
|
||||
case 2:
|
||||
temp = ramdac->loop.p;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x39: /* MCLK/Loop Clock Control */
|
||||
temp = ramdac->mclk;
|
||||
break;
|
||||
@@ -436,6 +540,29 @@ tvp3026_hwcursor_draw(svga_t *svga, int displine)
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
tvp3026_getclock(int clock, void *p)
|
||||
{
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) p;
|
||||
int n, m, pl;
|
||||
float f_vco, f_pll;
|
||||
|
||||
if (clock == 0)
|
||||
return 25175000.0;
|
||||
if (clock == 1)
|
||||
return 28322000.0;
|
||||
|
||||
/*Fvco = 8 x Fref x (65 - M) / (65 - N)*/
|
||||
/*Fpll = Fvco / 2^P*/
|
||||
n = ramdac->pix.n & 0x3f;
|
||||
m = ramdac->pix.m & 0x3f;
|
||||
pl = ramdac->pix.p & 0x03;
|
||||
f_vco = 8.0 * 14318184 * (float)(65 - m) / (float)(65 - n);
|
||||
f_pll = f_vco / (float)(1 << pl);
|
||||
|
||||
return f_pll;
|
||||
}
|
||||
|
||||
void *
|
||||
tvp3026_ramdac_init(const device_t *info)
|
||||
{
|
||||
@@ -447,6 +574,7 @@ tvp3026_ramdac_init(const device_t *info)
|
||||
ramdac->latch_cntl = 0x06;
|
||||
ramdac->true_color = 0x80;
|
||||
ramdac->mcr = 0x98;
|
||||
ramdac->clock_sel = 0x07;
|
||||
ramdac->mclk = 0x18;
|
||||
|
||||
return ramdac;
|
||||
|
||||
Reference in New Issue
Block a user