Video changes:

Improved the banking of the ATI 28800-5 cards (VGA Charger and VGA Wonder XL).
Improved the skew and horizontal display of some of the ET4000W32P cards as well as the cursor.
Made the Oak OTI 077 and PVGA WD90c30 cards use the Sierra 11487 (actually a clone is used in the real cards).
For the WD90c30, changed the way the hack is involved.
Reverted some changes of the S3 Vision/Trio that originally made glitches, now the glitches are gone and the accelerator renders fine.
Re-organized the Sierra 1148x RAMDAC's and added the 11486 (Mark 1).
MCA SVGA cards use the full 32-bit mapping.
This commit is contained in:
TC1995
2021-10-24 19:06:05 +02:00
parent f70963e1ba
commit 61273f5c1f
9 changed files with 551 additions and 317 deletions

View File

@@ -290,7 +290,7 @@ extern const device_t icd2061_device;
extern const device_t ics9161_device;
extern const device_t sc11483_ramdac_device;
extern const device_t sc11487_ramdac_device;
extern const device_t sc11484_ramdac_device;
extern const device_t sc11486_ramdac_device;
extern const device_t sc11484_nors2_ramdac_device;
extern const device_t sc1502x_ramdac_device;
extern const device_t sdac_ramdac_device;

View File

@@ -59,6 +59,7 @@
#endif
#define BIOS_ROM_PATH "roms/video/ati28800/bios.bin"
#define BIOS_VGAXL_ROM_PATH "roms/video/ati28800/ATI_VGAWonder_XL.bin"
typedef struct ati28800_t
@@ -82,6 +83,8 @@ typedef struct ati28800_t
int get_korean_font_index;
uint16_t get_korean_font_base;
int ksc5601_mode_enabled;
int type, type_korean;
} ati28800_t;
@@ -111,7 +114,6 @@ ati28800_log(const char *fmt, ...)
static void ati28800_recalctimings(svga_t *svga);
static void
ati28800_out(uint16_t addr, uint8_t val, void *p)
{
@@ -134,37 +136,36 @@ ati28800_out(uint16_t addr, uint8_t val, void *p)
ati28800_log("ATI 28800 write reg=0x%02X, val=0x%02X\n", ati28800->index, val);
switch (ati28800->index) {
case 0xa3:
ati28800->regs[0xa3] = val & 0x1f;
svga_recalctimings(svga);
if ((old ^ val) & 0x10)
svga_recalctimings(svga);
break;
case 0xa6:
ati28800->regs[0xa6] = val & 0xc9;
break;
case 0xab:
ati28800->regs[0xab] = val & 0xdf;
case 0xa7:
if ((old ^ val) & 0x80)
svga_recalctimings(svga);
break;
case 0xb0:
ati28800->regs[0xb0] = val & 0x7d;
svga_recalctimings(svga);
break;
case 0xb1:
ati28800->regs[0xb0] = val & 0x7f;
if ((old ^ val) & 0x60)
svga_recalctimings(svga);
break;
case 0xb2:
case 0xbe:
if (ati28800->regs[0xbe] & 0x08) { /* Read/write bank mode */
svga->read_bank = (((val & 0x01) << 3) | ((val & 0xe0) >> 5)) * 0x10000;
svga->write_bank = ((val & 0x1e) >> 1) * 0x10000;
svga->read_bank = (((ati28800->regs[0xb2] & 0x01) << 3) | ((ati28800->regs[0xb2] & 0xe0) >> 5)) * 0x10000;
svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000;
} else { /* Single bank mode */
svga->read_bank = ((val & 0x1e) >> 1) * 0x10000;
svga->write_bank = ((val & 0x1e) >> 1) * 0x10000;
svga->read_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000;
svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000;
}
if (ati28800->index == 0xbe) {
if ((old ^ val) & 0x10)
svga_recalctimings(svga);
}
break;
case 0xb3:
ati28800->regs[0xb3] = val & 0xef;
ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1);
break;
case 0xb6:
if ((old ^ val) & 0x10)
if ((old ^ val) & 0x11)
svga_recalctimings(svga);
break;
case 0xb8:
@@ -179,7 +180,10 @@ ati28800_out(uint16_t addr, uint8_t val, void *p)
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
if (ati28800->type == 1)
sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
case 0x3D4:
@@ -190,12 +194,6 @@ ati28800_out(uint16_t addr, uint8_t val, void *p)
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
if ((ati28800->regs[0xb4] & 0x10) && ((svga->crtcreg == 0x0a) || (svga->crtcreg == 0x0b)))
return;
if ((ati28800->regs[0xb4] & 0x20) && ((svga->crtc[0x08] & 0x7f) && (svga->crtc[0x14] & 0x1f)))
return;
if ((ati28800->regs[0xb4] & 0x40) && ((svga->crtcreg <= 0x06) && (svga->crtc[0x07] & 0x10) != 0x10))
return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
@@ -299,22 +297,23 @@ ati28800_in(uint16_t addr, void *p)
break;
case 0x1cf:
switch (ati28800->index) {
case 0xa0:
temp = 0x10;
break;
case 0xaa:
temp = ati28800->id;
break;
case 0xb0:
if (ati28800->memory == 1024)
temp = 0x08;
else if (ati28800->memory == 512)
temp = 0x10;
else
temp = 0x00;
temp = ati28800->regs[0xb0] | 0x80;
if (ati28800->memory == 1024) {
temp &= ~0x10;
temp |= 0x08;
} else if (ati28800->memory == 512) {
temp |= 0x10;
temp &= ~0x08;
} else {
temp &= ~0x18;
}
break;
case 0xb7:
temp = ati28800->regs[ati28800->index] & ~8;
temp = ati28800->regs[0xb7] & ~8;
if (ati_eeprom_read(&ati28800->eeprom))
temp |= 8;
break;
@@ -333,7 +332,9 @@ ati28800_in(uint16_t addr, void *p)
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
if (ati28800->type == 1)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3D4:
temp = svga->crtcreg;
@@ -401,8 +402,14 @@ ati28800_recalctimings(svga_t *svga)
{
ati28800_t *ati28800 = (ati28800_t *)svga->p;
switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) |
((svga->miscout & 0x0C) >> 2)) {
if (ati28800->regs[0xa3] & 0x10)
svga->ma_latch |= 0x10000;
if (ati28800->regs[0xb0] & 0x40)
svga->ma_latch |= 0x20000;
switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) |
((svga->miscout & 0x0C) >> 2)) {
case 0x00: svga->clock = (cpuclock * (double)(1ull << 32)) / 42954000.0; break;
case 0x01: svga->clock = (cpuclock * (double)(1ull << 32)) / 48771000.0; break;
case 0x02: ati28800_log ("clock 2\n"); break;
@@ -420,38 +427,69 @@ ati28800_recalctimings(svga_t *svga)
case 0x0E: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break;
case 0x0F: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break;
default: break;
}
}
if (ati28800->regs[0xb8] & 0x40)
if (ati28800->regs[0xb8] & 0x40)
svga->clock *= 2;
if (ati28800->regs[0xa3] & 0x10)
svga->ma |= 0x10000;
if (ati28800->regs[0xa7] & 0x80)
svga->clock *= 3;
if (ati28800->regs[0xb0] & 0x40)
svga->ma |= 0x20000;
if (ati28800->regs[0xb6] & 0x10) {
if (ati28800->regs[0xb6] & 0x10) {
svga->hdisp <<= 1;
svga->htotal <<= 1;
svga->rowoffset <<= 1;
}
if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) { /* Extended 256 colour modes */
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
svga->rowoffset <<= 1;
svga->ma <<= 1;
break;
case 15:
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
svga->rowoffset <<= 1;
svga->ma <<= 1;
break;
svga->gdcreg[5] &= ~0x40;
}
}
if (ati28800->regs[0xb0] & 0x20) {
svga->gdcreg[5] |= 0x40;
}
if (!svga->scrblank && svga->attr_palette_enable) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_4bpp_lowres;
else
svga->render = svga_render_4bpp_highres;
break;
case 0x20: /*4 colours*/
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_2bpp_lowres;
else
svga->render = svga_render_2bpp_highres;
break;
case 0x40: case 0x60: /*256+ colours*/
switch (svga->bpp) {
case 8:
svga->map8 = svga->pallook;
if (svga->lowres)
svga->render = svga_render_8bpp_lowres;
else {
svga->render = svga_render_8bpp_highres;
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
}
break;
case 15:
if (svga->lowres)
svga->render = svga_render_15bpp_lowres;
else {
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
}
break;
}
break;
}
}
}
svga->vram_display_mask = (ati28800->regs[0xb6] & 1) ? ((ati28800->memory << 10) - 1) : 0x3ffff;
}
@@ -466,14 +504,15 @@ ati28800k_recalctimings(svga_t *svga)
svga->render = svga_render_text_80_ksc5601;
}
void *
ati28800k_init(const device_t *info)
{
ati28800_t *ati28800 = (ati28800_t *) malloc(sizeof(ati28800_t));
memset(ati28800, 0, sizeof(ati28800_t));
if (info->local == 0) {
ati28800->type_korean = info->local;
if (ati28800->type_korean == 0) {
ati28800->memory = device_get_config_int("memory");
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800);
} else {
@@ -489,7 +528,7 @@ ati28800k_init(const device_t *info)
ati28800->in_get_korean_font_kind_set = 0;
ati28800->ksc5601_mode_enabled = 0;
switch(info->local) {
switch(ati28800->type_korean) {
case 0:
default:
rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
@@ -512,12 +551,12 @@ ati28800k_init(const device_t *info)
NULL,
NULL);
ati28800->svga.ramdac = device_add(&sc1502x_ramdac_device);
io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
ati28800->svga.miscout = 1;
ati28800->svga.bpp = 8;
ati28800->svga.packed_chain4 = 1;
ati28800->svga.ksc5601_sbyte_mask = 0;
ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9;
ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE;
@@ -541,14 +580,16 @@ ati28800_init(const device_t *info)
ati28800->memory = device_get_config_int("memory");
switch(info->local) {
ati28800->type = info->local;
switch(ati28800->type) {
case VGAWONDERXL:
ati28800->id = 6;
rom_init_interleaved(&ati28800->bios_rom,
BIOS_VGAXL_EVEN_PATH,
BIOS_VGAXL_ODD_PATH,
0xc0000, 0x10000, 0xffff,
0, MEM_MAPPING_EXTERNAL);
ati28800->id = 5;
rom_init(&ati28800->bios_rom,
BIOS_VGAXL_ROM_PATH,
0xc0000, 0x8000, 0x7fff,
0, MEM_MAPPING_EXTERNAL);
ati28800->svga.ramdac = device_add(&sc11486_ramdac_device);
break;
#if defined(DEV_BRANCH) && defined(USE_XL24)
@@ -576,8 +617,6 @@ ati28800_init(const device_t *info)
ati28800_in, ati28800_out,
NULL,
NULL);
ati28800->svga.ramdac = device_add(&sc1502x_ramdac_device);
io_sethandler(0x01ce, 2,
ati28800_in, NULL, NULL,
@@ -587,8 +626,10 @@ ati28800_init(const device_t *info)
ati28800_out, NULL, NULL, ati28800);
ati28800->svga.miscout = 1;
ati28800->svga.bpp = 8;
ati28800->svga.packed_chain4 = 1;
switch (info->local) {
switch (ati28800->type) {
case VGAWONDERXL:
ati_eeprom_load(&ati28800->eeprom, "ati28800xl.nvr", 0);
break;
@@ -616,7 +657,7 @@ ati28800_available(void)
static int
ati28800k_available()
ati28800k_available(void)
{
return ((rom_present(BIOS_ATIKOR_PATH) && rom_present(FONT_ATIKOR_PATH)));
}
@@ -625,7 +666,7 @@ ati28800k_available()
static int
compaq_ati28800_available(void)
{
return((rom_present(BIOS_VGAXL_EVEN_PATH) && rom_present(BIOS_VGAXL_ODD_PATH)));
return((rom_present(BIOS_VGAXL_ROM_PATH)));
}
@@ -719,7 +760,7 @@ static const device_config_t ati28800_wonderxl_config[] =
const device_t ati28800_device =
{
"ATI-28800",
"ATI 28800-5 (ATI VGA Charger)",
DEVICE_ISA,
0,
ati28800_init, ati28800_close, NULL,
@@ -765,7 +806,7 @@ const device_t ati28800k_spc6033p_device =
const device_t compaq_ati28800_device =
{
"Compaq ATI-28800",
"ATI 28800-5 (ATI VGA Wonder XL)",
DEVICE_ISA,
VGAWONDERXL,
ati28800_init, ati28800_close, NULL,

View File

@@ -97,11 +97,12 @@ typedef struct et4000w32p_t
uint32_t pattern_addr, source_addr, dest_addr, mix_addr;
} queued, internal;
uint8_t osr;
uint8_t status;
int pattern_x, source_x, pattern_x_back, source_x_back,
pattern_y, source_y, cpu_dat_pos, pix_pos,
cpu_input_num;
cpu_input_num, queue;
uint32_t pattern_addr, source_addr, dest_addr, mix_addr,
pattern_back, source_back, dest_back, mix_back,
@@ -119,9 +120,9 @@ typedef struct et4000w32p_t
static int et4000w32_vbus[4] = {1, 2, 4, 4};
static int et4000w32_max_x[8] = {0, 0, 4, 8, 16, 32, 64, 0x70000000};
static int et4000w32_wrap_x[8] = {0, 0, 3, 7, 15, 31, 63, 0xffffffff};
static int et4000w32_wrap_y[8] = {1, 2, 4, 8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
static int et4000w32_max_x[8] = {0,0,4,8,0x10,0x20,0x40,0x70000000};
static int et4000w32_wrap_x[8] = {0,0,3,7,0x0F,0x1F,0x3F,~0};
static int et4000w32_wrap_y[8] = {1,2,4,8,~0,~0,~0,~0};
static video_timings_t timing_et4000w32_vlb = {VIDEO_BUS, 4, 4, 4, 10, 10, 10};
static video_timings_t timing_et4000w32_pci = {VIDEO_PCI, 4, 4, 4, 10, 10, 10};
@@ -271,14 +272,24 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p)
switch (svga->bpp) {
case 8:
svga->hwcursor.xoff += 32;
break;
break;
}
}
if (svga->hwcursor.xsize == 128) {
svga->hwcursor.xoff &= 0x7f;
svga->hwcursor.yoff &= 0x7f;
if (et4000->type > ET4000W32P_REVC) {
if (svga->bpp == 24) {
et4000->adjust_cursor = 2;
}
}
} else {
if (et4000->type > ET4000W32P_REVC) {
if (svga->bpp == 24 && et4000->adjust_cursor) {
et4000->adjust_cursor = 0;
}
}
svga->hwcursor.xoff &= 0x3f;
svga->hwcursor.yoff &= 0x3f;
}
@@ -331,10 +342,15 @@ et4000w32p_in(uint16_t addr, void *p)
case 0x214B: case 0x215B: case 0x216B: case 0x217B:
if (et4000->index == 0xec)
return (et4000->regs[0xec] & 0xf) | (et4000->rev << 4);
if (et4000->index == 0xee) { /* Preliminary implementation */
if (svga->bpp == 8)
return 3;
else if (svga->bpp == 16)
if (et4000->index == 0xee) {
if (svga->bpp == 8) {
if ((svga->gdcreg[5] & 0x60) >= 0x40)
return 3;
else if ((svga->gdcreg[5] & 0x60) == 0x20)
return 1;
else
return 2;
} else if (svga->bpp == 15 || svga->bpp == 16)
return 4;
else
break;
@@ -409,13 +425,21 @@ et4000w32p_recalctimings(svga_t *svga)
switch (svga->bpp) {
case 15: case 16:
svga->hdisp >>= 1;
if (et4000->type <= ET4000W32P_REVC)
et4000->adjust_cursor = 1;
if (et4000->type <= ET4000W32P_REVC) {
if (et4000->type == ET4000W32P_REVC) {
if (svga->hdisp != 1024)
et4000->adjust_cursor = 1;
} else
et4000->adjust_cursor = 1;
}
break;
case 24:
svga->hdisp /= 3;
if (et4000->type <= ET4000W32P_REVC)
et4000->adjust_cursor = 2;
if (et4000->type == ET4000W32P_DIAMOND && (svga->hdisp == 640/2 || svga->hdisp == 1232)) {
svga->hdisp = 640;
}
break;
}
@@ -569,45 +593,51 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
case 0x7f80: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFFFF00) | val; break;
case 0x7f81: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFF00FF) | (val << 8); break;
case 0x7f82: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFF00FFFF) | (val << 16); break;
case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); break;
case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break;
case 0x7f84: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFFFF00) | val; break;
case 0x7f85: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFF00FF) | (val << 8); break;
case 0x7f86: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFF00FFFF) | (val << 16); break;
case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); break;
case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break;
case 0x7f88: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0xFF00) | val; break;
case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); break;
case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7f8a: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0xFF00) | val; break;
case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); break;
case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); et4000->acl.queue++;break;
case 0x7f8c: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0xFF00) | val; break;
case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); break;
case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7f8e:
et4000->acl.queue++;
if (et4000->type >= ET4000W32P_REVC)
et4000->acl.queued.pixel_depth = val;
else
et4000->acl.queued.vbus = val;
break;
case 0x7f8f: et4000->acl.queued.xy_dir = val; break;
case 0x7f90: et4000->acl.queued.pattern_wrap = val; break;
case 0x7f92: et4000->acl.queued.source_wrap = val; break;
case 0x7f8f: et4000->acl.queued.xy_dir = val; et4000->acl.queue++; break;
case 0x7f90: et4000->acl.queued.pattern_wrap = val; et4000->acl.queue++; break;
case 0x7f92: et4000->acl.queued.source_wrap = val; et4000->acl.queue++; break;
case 0x7f98: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0xFF00) | val; break;
case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); break;
case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7f9a: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0xFF00) | val; break;
case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); break;
case 0x7f9c: et4000->acl.queued.ctrl_routing = val; break;
case 0x7f9d: et4000->acl.queued.ctrl_reload = val; break;
case 0x7f9e: et4000->acl.queued.rop_bg = val; break;
case 0x7f9f: et4000->acl.queued.rop_fg = val; break;
case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7f9c: et4000->acl.queued.ctrl_routing = val; et4000->acl.queue++; break;
case 0x7f9d: et4000->acl.queued.ctrl_reload = val; et4000->acl.queue++; break;
case 0x7f9e: et4000->acl.queued.rop_bg = val; et4000->acl.queue++; break;
case 0x7f9f: et4000->acl.queued.rop_fg = val; et4000->acl.queue++; break;
case 0x7fa0: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFFFF00) | val; break;
case 0x7fa1: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFF00FF) | (val << 8); break;
case 0x7fa2: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFF00FFFF) | (val << 16); break;
case 0x7fa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00FFFFFF) | (val << 24);
et4000->acl.queue++;
et4000->acl.internal = et4000->acl.queued;
if (et4000->type >= ET4000W32P_REVC) {
et4000w32p_blit_start(et4000);
if (!(et4000->acl.queued.ctrl_routing & 0x43))
et4000w32p_blit(0xffffff, ~0, 0, 0, et4000);
if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3))
et4000w32p_blit(4, ~0, 0, 0, et4000);
if (et4000->acl.osr & 0x10) {
et4000w32p_blit_start(et4000);
if (!(et4000->acl.queued.ctrl_routing & 0x43)) {
et4000w32p_blit(0xffffff, ~0, 0, 0, et4000);
}
if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) {
et4000w32p_blit(4, ~0, 0, 0, et4000);
}
}
} else {
et4000w32_blit_start(et4000);
et4000->acl.cpu_input_num = 0;
@@ -618,15 +648,15 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
case 0x7fa4: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; break;
case 0x7fa5: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); break;
case 0x7fa6: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); break;
case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); break;
case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break;
case 0x7fa8: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; break;
case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); break;
case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7faa: et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; break;
case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); break;
case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7fac: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; break;
case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); break;
case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); et4000->acl.queue++; break;
case 0x7fae: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; break;
case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); break;
case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); et4000->acl.queue++; break;
}
}
@@ -638,17 +668,17 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
if (!(et4000->acl.status & ACL_XYST))
return;
if (et4000->acl.internal.ctrl_routing & 3) {
et4000->acl.queue++;
if ((et4000->acl.internal.ctrl_routing & 3) == 2) {
if (et4000->acl.mix_addr & 7)
et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000);
else
et4000w32p_blit(8, val, 0, 1, et4000);
et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000);
}
else if ((et4000->acl.internal.ctrl_routing & 3) == 1)
else if ((et4000->acl.internal.ctrl_routing & 3) == 1) {
et4000w32p_blit(1, ~0, val, 2, et4000);
}
}
} else {
if (!(et4000->acl.status & ACL_XYST)) {
et4000->acl.queue++;
et4000->acl.queued.dest_addr = (addr & 0x1FFF) + et4000->mmu.base[et4000->bank];
et4000->acl.internal = et4000->acl.queued;
et4000w32_blit_start(et4000);
@@ -658,6 +688,7 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val)
}
if (et4000->acl.internal.ctrl_routing & 7) {
et4000->acl.queue++;
et4000->acl.cpu_input = (et4000->acl.cpu_input &~ (0xFF << (et4000->acl.cpu_input_num << 3))) |
(val << (et4000->acl.cpu_input_num << 3));
et4000->acl.cpu_input_num++;
@@ -716,6 +747,7 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p)
case 0x7f0a: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFF00FFFF) | (val << 16); break;
case 0x7f0b: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00FFFFFF) | (val << 24); break;
case 0x7f13: et4000->mmu.ctrl = val; break;
case 0x7f31: et4000->acl.osr = val; break;
}
break;
}
@@ -771,13 +803,23 @@ et4000w32p_mmu_read(uint32_t addr, void *p)
case 0x7f13: return et4000->mmu.ctrl;
case 0x7f36:
if (et4000->type >= ET4000W32P_REVC) {
if (et4000->type >= ET4000W32P_REVC) {
if (et4000->acl.queue) {
et4000->acl.status |= ACL_RDST;
et4000->acl.queue = 0;
} else
et4000->acl.status &= ~ACL_RDST;
temp = et4000->acl.status;
temp &= ~(ACL_RDST | ACL_WRST);
if (temp == ACL_XYST && (et4000->acl.internal.ctrl_routing == 1 || et4000->acl.internal.ctrl_routing == 2))
temp |= ACL_RDST;
} else {
et4000->acl.status &= ~(ACL_XYST | ACL_SSO);
if (et4000->acl.queue) {
et4000->acl.status |= ACL_RDST;
et4000->acl.queue = 0;
} else
et4000->acl.status &= ~ACL_RDST;
temp = et4000->acl.status;
}
return temp;
@@ -883,7 +925,7 @@ et4000w32p_blit_start(et4000w32p_t *et4000)
et4000->acl.status |= ACL_XYST;
et4000w32_log("ACL status XYST set\n");
if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40))
et4000->acl.status |= ACL_SSO;
et4000->acl.status |= ACL_SSO;
if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) {
et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7];
@@ -997,7 +1039,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32
if (!(et4000->acl.status & ACL_XYST) && (et4000->type >= ET4000W32P_REVC))
return;
if (et4000->acl.internal.xy_dir & 0x80){ /* Line draw */
if (et4000->acl.internal.xy_dir & 0x80) { /* Line draw */
while (count--) {
et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y);
pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask];

View File

@@ -28,6 +28,7 @@
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#define BIOS_037C_PATH "roms/video/oti/bios.bin"
#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/oti067.bin"
@@ -85,6 +86,14 @@ oti_out(uint16_t addr, uint8_t val, void *p)
return;
} else
break;
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
if (oti->chip_id == OTI_077)
sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
case 0x3D4:
if (oti->chip_id)
@@ -216,6 +225,11 @@ oti_in(uint16_t addr, void *p)
temp = oti->enable_register;
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
if (oti->chip_id == OTI_077)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3CF:
return svga->gdcreg[svga->gdcaddr & 0xf];
@@ -343,6 +357,14 @@ oti_recalctimings(svga_t *svga)
if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10)) svga->rowoffset <<= 1;
svga->interlace = oti->regs[0x14] & 0x80;
if (svga->bpp == 16) {
svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1;
} else if (svga->bpp == 15) {
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
}
}
@@ -406,6 +428,9 @@ oti_init(const device_t *info)
svga_init(info, &oti->svga, oti, oti->vram_size << 10,
oti_recalctimings, oti_in, oti_out, NULL, NULL);
if (oti->chip_id == OTI_077)
oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/
io_sethandler(0x03c0, 32,
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);

View File

@@ -54,6 +54,7 @@ typedef struct paradise_t
uint32_t read_bank[4], write_bank[4];
int interlace;
int check;
struct {
uint8_t reg_block_ptr;
@@ -105,6 +106,13 @@ void paradise_out(uint16_t addr, uint8_t val, void *p)
}
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
if (paradise->type == WD90C30)
sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
case 0x3cf:
if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) {
if ((paradise->pr5 & 7) != 5)
@@ -215,7 +223,12 @@ uint8_t paradise_in(uint16_t addr, void *p)
return svga->seqregs[svga->seqaddr & 0x1f];
}
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
if (paradise->type == WD90C30)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3cf:
if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) {
if ((paradise->pr5 & 7) != 5)
@@ -232,8 +245,11 @@ uint8_t paradise_in(uint16_t addr, void *p)
paradise->pr1 &= ~0x40;
} else if (paradise->vram_mask == (1024 << 10) - 1) {
paradise->pr1 |= 0xc0;
if (svga->bpp >= 8 && !svga->lowres) /*Horrible tweak, but needed to get around black corruption in 1M mode*/
/*The following is a horrible tweak, but needed to get around black corruption in 1M mode*/
if (svga->bpp >= 8 && (svga->gdcreg[0x0e] & 0x01) && paradise->check)
paradise->pr1 &= ~0x40;
else if (!(svga->gdcreg[0x0e] & 0x01) && !(svga->crtc[0x14] & 0x40) && paradise->check)
paradise->check = 0;
}
return paradise->pr1;
case 6:
@@ -336,9 +352,25 @@ void paradise_recalctimings(svga_t *svga)
svga->interlace = 1;
}
}
if (svga->bpp >= 8 && !svga->lowres)
svga->render = svga_render_8bpp_highres;
if (paradise->type < WD90C30) {
if (svga->bpp >= 8 && !svga->lowres)
svga->render = svga_render_8bpp_highres;
} else {
if (svga->bpp >= 8 && !svga->lowres) {
if (svga->bpp == 16) {
svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1;
} else if (svga->bpp == 15) {
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
} else {
if ((svga->crtc[0x17] == 0xc2) && (svga->crtc[0x14] & 0x40))
paradise->check = 1;
svga->render = svga_render_8bpp_highres;
}
}
}
}
static void paradise_write(uint32_t addr, uint8_t val, void *p)
@@ -348,7 +380,7 @@ static void paradise_write(uint32_t addr, uint8_t val, void *p)
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
svga_write_linear(addr, val, svga);
}
static void paradise_writew(uint32_t addr, uint16_t val, void *p)
@@ -421,6 +453,7 @@ void *paradise_init(const device_t *info, uint32_t memsize)
NULL);
paradise->vram_mask = memsize - 1;
svga->decode_mask = memsize - 1;
svga->ramdac = device_add(&sc11487_ramdac_device); /*Actually a Winbond W82c487-80, probably a clone.*/
break;
}

View File

@@ -238,7 +238,7 @@ typedef struct s3_t
uint16_t multifunc[16];
uint8_t pix_trans[4];
int ssv_state;
int cx, cy;
int px, py;
int sx, sy;
@@ -347,6 +347,7 @@ typedef struct s3_t
int translate;
int enable_8514;
int color_16bit;
volatile int busy, force_busy;
uint8_t thread_run, serialport;
@@ -453,7 +454,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3);
temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \
#define READ_PIXTRANS_WORD \
if (s3->bpp == 0) { \
if (s3->bpp == 0 && !s3->color_16bit) { \
temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \
temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \
} else { \
@@ -461,7 +462,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3);
}
#define READ_PIXTRANS_LONG \
if (s3->bpp == 0) { \
if (s3->bpp == 0 && !s3->color_16bit) { \
temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \
temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \
temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 2)) & s3->vram_mask] << 16); \
@@ -520,7 +521,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
{
svga_t *svga = &s3->svga;
if (s3_cpu_src(s3)) {
if (s3->accel.cmd & 0x100) {
switch (s3->accel.cmd & 0x600) {
case 0x000:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
@@ -530,8 +531,12 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
s3_accel_start(8, 1, val | (val << 16), 0, s3);
} else
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
} else
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
} else {
if (s3->color_16bit)
s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
else
s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
}
break;
case 0x200:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
@@ -586,7 +591,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val)
static void
s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val)
{
if (s3_cpu_src(s3)) {
if (s3->accel.cmd & 0x100) {
switch (s3->accel.cmd & 0x600) {
case 0x000:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
@@ -700,12 +705,14 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x0f) << 8);
s3->accel.poly_cx2 = s3->accel.cur_x2 << 20;
break;
case 0xcae8:
case 0x8948: case 0x8ae8:
s3->accel.draw_fifo_slot++;
s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val;
s3->accel.point_1_updated = 1;
break;
case 0xcae9:
case 0x8949: case 0x8ae9:
s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8);
if (val & 0x20)
@@ -805,7 +812,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val;
break;
case 0x9d49: case 0x9ee9:
s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8);
s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8);
s3->accel.ssv_state = 1;
s3->accel.cx = s3->accel.cur_x;
@@ -1015,7 +1022,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3->accel.setup_fifo_slot++;
s3->accel.frgd_mix = val;
break;
case 0xbd48: case 0xbee8:
s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val;
break;
@@ -1138,8 +1145,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
else
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
} else
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
} else {
if (s3->color_16bit)
s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
else
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
}
}
}
break;
@@ -1156,8 +1167,9 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
else
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
} else
} else {
s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
}
break;
case 0x200:
/*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/
@@ -1313,6 +1325,7 @@ s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val)
} else {
s3->accel.b2e8_pix = 0;
}
s3_accel_out_pixtrans_l(s3, val);
}
@@ -1467,8 +1480,26 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
if (addr & 0x8000) {
s3_accel_out_fifo(s3, addr & 0xffff, val);
} else {
s3_accel_out_fifo(s3, 0xe2e8 + (addr & 3), val);
}
if (s3->accel.cmd & 0x100) {
if ((s3->accel.cmd & 0x600) == 0x200) {
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
else
s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
} else
s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
} else {
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
else
s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
} else
s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
}
}
}
}
}
@@ -2199,11 +2230,13 @@ s3_io_remove(s3_t *s3)
io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3);
io_removehandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_removehandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
s3_io_remove_alt(s3);
}
@@ -2316,13 +2349,15 @@ s3_io_set(s3_t *s3)
io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3);
if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) {
io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
}
}
io_sethandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
s3_io_set_alt(s3);
}
@@ -2360,13 +2395,10 @@ s3_out(uint16_t addr, uint8_t val, void *p)
}
if (svga->seqaddr == 4) /*Chain-4 - update banking*/
{
svga->chain4 = !!(val & 8);
if (svga->crtc[0x31] & 1) {
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
}
if (val & 0x08)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
} else if (svga->seqaddr == 9) {
svga->seqregs[svga->seqaddr] = val & 0x80;
s3_io_set(s3);
@@ -2430,7 +2462,9 @@ s3_out(uint16_t addr, uint8_t val, void *p)
return;
if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5))
return;
if ((s3->chip == S3_TRIO64V2) && svga->crtcreg >= 0x80)
if ((s3->chip == S3_TRIO64V2) && (svga->crtcreg >= 0x80))
return;
if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50))
return;
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
@@ -2486,12 +2520,10 @@ s3_out(uint16_t addr, uint8_t val, void *p)
case 0x35:
s3->bank = (s3->bank & 0x70) | (val & 0xf);
if (svga->crtc[0x31] & 1) {
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
}
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
break;
case 0x51:
@@ -2502,23 +2534,19 @@ s3_out(uint16_t addr, uint8_t val, void *p)
s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2);
s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2);
}
if (svga->crtc[0x31] & 1) {
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
}
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
break;
case 0x6a:
if (s3->chip >= S3_VISION964) {
s3->bank = val;
if (svga->crtc[0x31] & 1) {
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
}
if (svga->chain4)
svga->write_bank = svga->read_bank = s3->bank << 16;
else
svga->write_bank = svga->read_bank = s3->bank << 14;
}
break;
@@ -2771,6 +2799,7 @@ static void s3_recalctimings(svga_t *svga)
}
}
}
svga->ma_latch |= (s3->ma_ext << 16);
if (s3->chip >= S3_86C928) {
svga->hdisp = svga->hdisp_old;
@@ -2830,8 +2859,18 @@ static void s3_recalctimings(svga_t *svga)
}
}
if ((svga->crtc[0x43] & 0x08) && (s3->bpp == 0))
if ((svga->crtc[0x43] & 0x08) && (s3->color_16bit == 0) && (s3->chip <= S3_86C805)) {
s3->color_16bit = 1;
s3->width = 1024;
} else if (!(svga->crtc[0x43] & 0x08) && (s3->color_16bit == 1) && (s3->chip <= S3_86C805)) {
s3->color_16bit = 0;
if (s3->chip <= S3_86C924) {
if (s3->accel.advfunc_cntl & 4)
s3->width = 1024;
else
s3->width = 640;
}
}
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
svga->fb_only = 1;
@@ -3002,35 +3041,17 @@ static void s3_recalctimings(svga_t *svga)
}
} else {
svga->fb_only = 0;
if (!svga->scrblank && svga->attr_palette_enable) {
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
if (svga->seqregs[1] & 8) /*40 column*/ {
svga->render = svga_render_text_40;
} else {
svga->render = svga_render_text_80;
}
} else {
if ((svga->crtc[0x31] & 0x08) && ((svga->gdcreg[5] & 0x60) == 0x00)) {
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
if ((svga->crtc[0x31] & 0x08) && ((svga->gdcreg[5] & 0x60) == 0x00)) {
if (svga->bpp == 8) {
svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/
if (svga->hdisp <= 1024)
s3->width = 1024;
} else {
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_4bpp_lowres;
else
svga->render = svga_render_4bpp_highres;
break;
case 0x20: /*4 colours*/
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_2bpp_lowres;
else
svga->render = svga_render_2bpp_highres;
break;
}
}
}
} else {
if (s3->chip <= S3_86C924)
s3->width = 1024;
}
}
}
@@ -3069,7 +3090,9 @@ static void s3_trio64v_recalctimings(svga_t *svga)
if (!svga->rowoffset) svga->rowoffset = 256;
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
svga->fb_only = 1;
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
@@ -3090,10 +3113,13 @@ static void s3_trio64v_recalctimings(svga_t *svga)
svga->render = svga_render_32bpp_highres;
break;
}
}
} else
svga->fb_only = 0;
}
else /*Streams mode*/
{
svga->fb_only = 1;
if (s3->streams.buffer_ctrl & 1)
svga->ma_latch = s3->streams.pri_fb1 >> 2;
else
@@ -3179,7 +3205,7 @@ s3_updatemapping(s3_t *s3)
svga->banked_mask = 0x7fff;
break;
}
if (s3->chip >= S3_86C928) {
s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
@@ -3236,12 +3262,8 @@ s3_updatemapping(s3_t *s3)
mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size);
}
if (s3->chip >= S3_TRIO64V)
svga->fb_only = 1;
} else {
mem_mapping_disable(&s3->linear_mapping);
if (s3->chip >= S3_TRIO64V)
svga->fb_only = 0;
}
/* Memory mapped I/O. */
@@ -3255,9 +3277,10 @@ s3_updatemapping(s3_t *s3)
} else {
mem_mapping_enable(&s3->mmio_mapping);
}
} else
} else {
mem_mapping_disable(&s3->mmio_mapping);
}
/* New MMIO. */
if (svga->crtc[0x53] & 0x08)
mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000);
@@ -3288,12 +3311,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *p)
s3_t *s3 = (s3_t *)p;
svga_t *svga = &s3->svga;
if (!s3->enable_8514)
return;
if (port >= 0x8000) {
if (!s3->enable_8514)
return;
if (port >= 0x8000)
s3_accel_out_fifo(s3, port, val);
else {
} else {
switch (port)
{
case 0x4148: case 0x42e8:
@@ -3313,8 +3336,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *p)
s3->width = (val & 4) ? 1600 : 800;
svga->fullchange = changeframecount;
svga_recalctimings(svga);
} else if (s3->chip <= S3_86C805) {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
s3_updatemapping(s3);
if (s3->chip > S3_86C924)
s3_updatemapping(s3);
break;
}
}
@@ -3778,21 +3805,28 @@ s3_accel_in_w(uint16_t port, void *p)
if (s3->accel.cmd & 0x1000)
temp = (temp >> 8) | (temp << 8);
s3_accel_start(8, 1, temp | (temp << 16), 0, s3);
} else
} else {
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
} else
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
}
} else {
if (s3->color_16bit) {
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
} else {
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3);
}
}
break;
case 0x200:
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)
temp = (temp >> 8) | (temp << 8);
temp = (temp >> 8) | (temp << 8);
s3_accel_start(16, 1, temp | (temp << 16), 0, s3);
} else
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
} else
} else {
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3);
}
break;
}
}
@@ -3941,7 +3975,28 @@ s3_accel_read(uint32_t addr, void *p)
if (addr & 0x8000) {
temp = s3_accel_in(addr & 0xffff, p);
} else if (s3_cpu_dest(s3)) {
temp = s3_accel_in(0xe2e8 + (addr & 3), p);
READ_PIXTRANS_BYTE_MM
switch (s3->accel.cmd & 0x600) {
case 0x000:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3);
else
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
} else
s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
break;
case 0x200:
if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) {
if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))
s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3);
else
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
} else
s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3);
break;
}
}
}
@@ -4216,8 +4271,8 @@ polygon_setup(s3_t *s3)
}
}
#define READ(addr, dat) if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \
else if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \
#define READ(addr, dat) if (s3->bpp == 0 && !s3->color_16bit) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \
else if (s3->bpp == 1 || s3->color_16bit) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \
else if (s3->bpp == 2) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \
else dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)];
@@ -4522,12 +4577,12 @@ polygon_setup(s3_t *s3)
}
#define WRITE(addr, dat) if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) \
#define WRITE(addr, dat) if (s3->bpp == 0 && !s3->color_16bit) \
{ \
svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \
svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \
svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \
} \
else if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) \
else if (s3->bpp == 1 || s3->color_16bit) \
{ \
vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \
svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
@@ -5038,33 +5093,33 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
cmd |= 8;
}
// SRC-BASE/DST-BASE
if ((s3->accel.multifunc[0xd] >> 4) & 7) {
srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3);
} else {
srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3);
}
if ((s3->accel.multifunc[0xd] >> 0) & 7) {
dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3);
} else {
dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3);
}
if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) {
srcbase >>= 1;
dstbase >>= 1;
} else if (s3->bpp == 3) {
srcbase >>= 2;
dstbase >>= 2;
}
// SRC-BASE/DST-BASE
if ((s3->accel.multifunc[0xd] >> 4) & 7) {
srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3);
} else {
srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3);
}
if ((s3->accel.multifunc[0xd] >> 0) & 7) {
dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3);
} else {
dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3);
}
if (s3->bpp == 1) {
srcbase >>= 1;
dstbase >>= 1;
} else if (s3->bpp == 3) {
srcbase >>= 2;
dstbase >>= 2;
}
if ((s3->accel.cmd & 0x100) && ((s3_cpu_src(s3) || (s3_cpu_dest(s3))) && !cpu_input)) {
if ((s3->accel.cmd & 0x100) && ((s3_cpu_src(s3) || (s3_cpu_dest(s3)))) && (!cpu_input || (s3_enable_fifo(s3) == 0))) {
s3->force_busy = 1;
}
if (!cpu_input)
s3->accel.dat_count = 0;
if (cpu_input && (count <= 4)) {
if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) {
if ((s3->bpp == 3) && count == 2) {
if (s3->accel.dat_count) {
cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf;
@@ -5075,19 +5130,19 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
s3->accel.dat_count = 1;
}
}
if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08))
if (s3->bpp == 1 || s3->color_16bit)
count >>= 1;
if (s3->bpp == 3)
count >>= 2;
}
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08))
if (s3->bpp == 0 && !s3->color_16bit)
rd_mask &= 0xff;
else if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08))
else if (s3->bpp == 1 || s3->color_16bit)
rd_mask &= 0xffff;
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) compare &= 0xff;
if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) compare &= 0xffff;
if (s3->bpp == 0 && !s3->color_16bit) compare &= 0xff;
if (s3->bpp == 1 || s3->color_16bit) compare &= 0xffff;
switch (s3->accel.cmd & 0x600)
{
@@ -5100,6 +5155,7 @@ 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)*/
@@ -5140,7 +5196,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
mix_dat <<= 1;
mix_dat |= 1;
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8;
if (s3->bpp == 0) cpu_dat >>= 8;
else cpu_dat >>= 16;
if (!s3->accel.ssv_len)
break;
@@ -5173,14 +5229,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff;
s3->accel.sy = s3->accel.maj_axis_pcnt;
s3_fifo_slots(s3);
if (s3_cpu_src(s3)) {
return; /*Wait for data from CPU*/
}
}
frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
@@ -5199,24 +5254,26 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 3: src_dat = 0; break;
}
if (((compare_mode == 2 && src_dat != compare) ||
if ((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
compare_mode < 2))
compare_mode < 2)
{
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
MIX
if (s3->accel.cmd & 0x10) {
WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
}
WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
}
}
mix_dat <<= 1;
mix_dat |= 1;
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8;
else cpu_dat >>= 16;
if (s3->bpp == 0 && !s3->color_16bit)
cpu_dat >>= 8;
else {
cpu_dat >>= 16;
}
if (!s3->accel.sy) {
break;
}
@@ -5232,7 +5289,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 0xc0: s3->accel.cy++; break;
case 0xe0: s3->accel.cx++; s3->accel.cy++; break;
}
s3->accel.sy--;
}
s3->accel.cur_x = s3->accel.cx;
@@ -5263,17 +5319,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 3: src_dat = 0; break;
}
if (((compare_mode == 2 && src_dat != compare) ||
if ((compare_mode == 2 && src_dat != compare) ||
(compare_mode == 3 && src_dat == compare) ||
compare_mode < 2))
compare_mode < 2)
{
READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
MIX
if (s3->accel.cmd & 0x10) {
WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
}
WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
}
}
@@ -5287,13 +5341,16 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
mix_dat <<= 1;
mix_dat |= 1;
}
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8;
else cpu_dat >>= 16;
if (s3->bpp == 0 && !s3->color_16bit)
cpu_dat >>= 8;
else {
cpu_dat >>= 16;
}
if (!s3->accel.sy) {
break;
}
if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) {
s3->accel.err_term += s3->accel.destx_distp;
/*Step minor axis*/
@@ -5324,7 +5381,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
case 0xc0: s3->accel.cy++; break;
case 0xe0: s3->accel.cy++; break;
}
s3->accel.sy--;
}
s3->accel.cur_x = s3->accel.cx;
@@ -5432,10 +5488,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
mix_dat |= 1;
}
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08))
if (s3->bpp == 0 && !s3->color_16bit)
cpu_dat >>= 8;
else
else {
cpu_dat >>= 16;
}
if (s3->accel.cmd & 0x20)
s3->accel.cx++;
@@ -5462,7 +5519,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
if (cpu_input) {
if (s3->accel.b2e8_pix) {
s3->accel.cur_x = s3->accel.cx;
s3->accel.cur_y = s3->accel.cy;
s3->accel.cur_y = s3->accel.cy;
}
return;
}
@@ -5694,8 +5751,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_
mix_dat <<= 1;
mix_dat |= 1;
if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8;
else cpu_dat >>= 16;
if (s3->bpp == 0 && !s3->color_16bit)
cpu_dat >>= 8;
else {
cpu_dat >>= 16;
}
if (s3->accel.cmd & 0x20)
{
@@ -6384,7 +6444,6 @@ static int vram_sizes[] =
3 /*8 MB*/
};
static void s3_reset(void *priv)
{
s3_t *s3 = (s3_t *) priv;
@@ -6403,14 +6462,14 @@ static void s3_reset(void *priv)
svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4);
else
svga->crtc[0x36] = 3 | (1 << 4);
if (s3->chip >= S3_86C928)
svga->crtc[0x36] |= (vram_sizes[s3->vram] << 5);
else
svga->crtc[0x36] |= ((s3->vram == 1) ? 0x00 : 0x20) | 0x80;
svga->crtc[0x37] = 1 | (7 << 5);
if (s3->chip >= S3_86C928)
svga->crtc[0x37] |= 0x04;
@@ -6440,11 +6499,11 @@ static void s3_reset(void *priv)
case S3_PHOENIX_86C805:
svga->crtc[0x5a] = 0x0a;
break;
case S3_METHEUS_86C928:
svga->crtc[0x5a] = 0x0a;
break;
case S3_PARADISE_BAHAMAS64:
case S3_PHOENIX_VISION864:
case S3_MIROCRYSTAL20SD_864:
@@ -6857,8 +6916,10 @@ static void *s3_init(const device_t *info)
if (chip >= S3_86C928)
svga->crtc[0x36] |= (vram_sizes[vram] << 5);
else
svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x80;
else {
svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x98;
svga->crtc[0x41] = (vram == 1) ? 0x10 : 0x00;
}
svga->crtc[0x37] = 1 | (7 << 5);

View File

@@ -6,7 +6,7 @@
*
* This file is part of the 86Box distribution.
*
* Emulation of Sierra SC11483 and SC11487 RAMDACs.
* Emulation of Sierra SC1148x RAMDACs and clones (e.g.: Winbond).
*
* Used by the S3 911 and 924 chips.
*
@@ -43,24 +43,45 @@ sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga)
{
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) p;
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
rs |= ((!!rs2) << 2);
int oldbpp = 0;
switch (addr) {
case 0x3c6:
if (ramdac->state == 4) {
ramdac->state = 0;
ramdac->ctrl = val;
if (ramdac->ctrl & 0xa0) {
if ((ramdac->ctrl & 0x40) && (ramdac->type == 1))
svga->bpp = 16;
else
svga->bpp = 15;
} else
svga->bpp = 8;
svga_recalctimings(svga);
return;
switch (ramdac->state) {
case 4:
ramdac->state = 0;
if (val == 0xff)
break;
ramdac->ctrl = val;
ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5);
oldbpp = svga->bpp;
switch (ramdac->type) {
case 0: /* Sierra Mark 2 (11483)*/
case 2: /* Sierra Mark 2 (11484)*/
case 3: /* Sierra Mark 1 (11486)*/
if (val & 0xa0) {
svga->bpp = 15;
} else if (val == 0x00)
svga->bpp = 8;
break;
case 1: /* Sierra Mark 3 (11487)*/
if (val & 0xa0) {
if (val & 0x40)
svga->bpp = 16;
else
svga->bpp = 15;
} else if (val == 0x00)
svga->bpp = 8;
break;
}
if (oldbpp != svga->bpp)
svga_recalctimings(svga);
return;
default:
svga_out(addr, val, svga);
break;
}
ramdac->state = 0;
break;
case 0x3c7: case 0x3c8:
@@ -82,18 +103,21 @@ sc1148x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga)
switch (addr) {
case 0x3c6:
if (ramdac->state == 4) {
ramdac->state = 0;
ret = ramdac->ctrl;
if (ramdac->type == 1) {
if (((ramdac->ctrl >> 5) == 1) || ((ramdac->ctrl >> 5) == 3))
ret |= 1;
else
ret &= ~1;
}
return ret;
switch (ramdac->state) {
case 1:
case 2: case 3:
ret = 0x00;
ramdac->state++;
break;
case 4:
ret = ramdac->ctrl;
ret = (ret & ~0x18) | (svga->dac_mask & 0x18);
break;
default:
ret = svga_in(addr, svga);
ramdac->state++;
break;
}
ramdac->state++;
break;
case 0x3c7: case 0x3c8:
@@ -150,4 +174,12 @@ const device_t sc11484_nors2_ramdac_device =
0, 2,
sc1148x_ramdac_init, sc1148x_ramdac_close,
NULL, { NULL }, NULL, NULL
};
const device_t sc11486_ramdac_device =
{
"Sierra SC11486 RAMDAC",
0, 3,
sc1148x_ramdac_init, sc1148x_ramdac_close,
NULL, { NULL }, NULL, NULL
};

View File

@@ -953,7 +953,7 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize,
svga->translate_address = NULL;
svga->ksc5601_english_font_type = 0;
if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB)) {
if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) {
mem_mapping_add(&svga->mapping, 0xa0000, 0x20000,
svga_read, svga_readw, svga_readl,
svga_write, svga_writew, svga_writel,

View File

@@ -58,12 +58,13 @@ video_cards[] = {
{ "ati28800k", &ati28800k_device },
{ "ati18800v", &ati18800_vga88_device },
{ "ati28800", &ati28800_device },
{ "compaq_ati28800", &compaq_ati28800_device },
#if defined(DEV_BRANCH) && defined(USE_XL24)
{ "ati28800w", &ati28800_wonderxl24_device },
#endif
{ "ati18800", &ati18800_device },
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
{ "ati18800w", &ati18800_wonder_device },
#endif
#if defined(DEV_BRANCH) && defined(USE_XL24)
{ "ati28800w", &ati28800_wonderxl24_device },
#endif
{ "cga", &cga_device },
{ "superega", &sega_device },
@@ -74,7 +75,6 @@ video_cards[] = {
{ "cl_gd5428_isa", &gd5428_isa_device },
{ "cl_gd5429_isa", &gd5429_isa_device },
{ "cl_gd5434_isa", &gd5434_isa_device },
{ "compaq_ati28800", &compaq_ati28800_device },
{ "compaq_cga", &compaq_cga_device },
{ "compaq_cga_2", &compaq_cga_2_device },
{ "compaq_ega", &cpqega_device },