ATI Mach64 improvements and ATI 28800-6 (VGA Wonder XL24) emulation.
This commit is contained in:
@@ -396,6 +396,7 @@ enum
|
||||
GFX_WD90C11, /*Paradise WD90C11 Standalone*/
|
||||
GFX_OTI077, /*Oak OTI-077*/
|
||||
GFX_ET4000W32CS, /*Tseng ET4000/W32p (Cardex) (ICS RAMDAC) */
|
||||
GFX_VGAWONDERXL24, /*Compaq ATI VGA Wonder XL24 (28800-6)*/
|
||||
GFX_MAX
|
||||
};
|
||||
|
||||
|
@@ -22,6 +22,8 @@ typedef struct ati28800_t
|
||||
int index;
|
||||
} ati28800_t;
|
||||
|
||||
void ati28800_svga_recalctimings(svga_t *svga);
|
||||
|
||||
void ati28800_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
@@ -42,6 +44,14 @@ void ati28800_out(uint16_t addr, uint8_t val, void *p)
|
||||
ati28800->regs[ati28800->index] = val;
|
||||
switch (ati28800->index)
|
||||
{
|
||||
case 0xad:
|
||||
if (gfxcard == GFX_VGAWONDERXL24)
|
||||
{
|
||||
svga->charseta = (svga->charseta & 0x3ffff) | ((((uint32_t) val) >> 4) << 18);
|
||||
svga->charsetb = (svga->charsetb & 0x3ffff) | ((((uint32_t) val) >> 4) << 18);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb2:
|
||||
case 0xbe:
|
||||
if (ati28800->regs[0xbe] & 8) /*Read/write bank mode*/
|
||||
@@ -75,7 +85,7 @@ void ati28800_out(uint16_t addr, uint8_t val, void *p)
|
||||
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
|
||||
{
|
||||
svga->fullchange = changeframecount;
|
||||
svga_recalctimings(svga);
|
||||
ati28800_svga_recalctimings(svga);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -101,6 +111,10 @@ uint8_t ati28800_in(uint16_t addr, void *p)
|
||||
case 0x1cf:
|
||||
switch (ati28800->index)
|
||||
{
|
||||
case 0xaa:
|
||||
temp = (gfxcard == GFX_VGAWONDERXL24) ? 6 : 5;
|
||||
break;
|
||||
|
||||
case 0xb7:
|
||||
temp = ati28800->regs[ati28800->index] & ~8;
|
||||
if (ati_eeprom_read(&ati28800->eeprom))
|
||||
@@ -135,6 +149,161 @@ uint8_t ati28800_in(uint16_t addr, void *p)
|
||||
return temp;
|
||||
}
|
||||
|
||||
void ati28800_svga_recalctimings(svga_t *svga)
|
||||
{
|
||||
double crtcconst;
|
||||
double _dispontime, _dispofftime, disptime;
|
||||
int hdisp_old;
|
||||
|
||||
svga->vtotal = svga->crtc[6];
|
||||
svga->dispend = svga->crtc[0x12];
|
||||
svga->vsyncstart = svga->crtc[0x10];
|
||||
svga->split = svga->crtc[0x18];
|
||||
svga->vblankstart = svga->crtc[0x15];
|
||||
|
||||
if (svga->crtc[7] & 1) svga->vtotal |= 0x100;
|
||||
if (svga->crtc[7] & 32) svga->vtotal |= 0x200;
|
||||
svga->vtotal += 2;
|
||||
|
||||
if (svga->crtc[7] & 2) svga->dispend |= 0x100;
|
||||
if (svga->crtc[7] & 64) svga->dispend |= 0x200;
|
||||
svga->dispend++;
|
||||
|
||||
if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100;
|
||||
if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200;
|
||||
svga->vsyncstart++;
|
||||
|
||||
if (svga->crtc[7] & 0x10) svga->split|=0x100;
|
||||
if (svga->crtc[9] & 0x40) svga->split|=0x200;
|
||||
svga->split++;
|
||||
|
||||
if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100;
|
||||
if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200;
|
||||
svga->vblankstart++;
|
||||
|
||||
svga->hdisp = svga->crtc[1];
|
||||
svga->hdisp++;
|
||||
|
||||
svga->htotal = svga->crtc[0];
|
||||
if ((ati28800->regs[0xad] & 8) && (gfxcard == GFX_VGAWONDERXL24)) svga->htotal |= (ati28800->regs[0xad] & 1) ? 0x100 | 0;
|
||||
svga->htotal += 6; /*+6 is required for Tyrian*/
|
||||
|
||||
svga->rowoffset = svga->crtc[0x13];
|
||||
|
||||
svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1;
|
||||
|
||||
svga->lowres = svga->attrregs[0x10] & 0x40;
|
||||
|
||||
svga->interlace = 0;
|
||||
|
||||
svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd];
|
||||
|
||||
svga->hdisp_time = svga->hdisp;
|
||||
svga->render = svga_render_blank;
|
||||
if (!svga->scrblank && svga->attr_palette_enable)
|
||||
{
|
||||
if (!(svga->gdcreg[6] & 1)) /*Text mode*/
|
||||
{
|
||||
if (svga->seqregs[1] & 8) /*40 column*/
|
||||
{
|
||||
svga->render = svga_render_text_40;
|
||||
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
svga->render = svga_render_text_80;
|
||||
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
|
||||
}
|
||||
svga->hdisp_old = svga->hdisp;
|
||||
}
|
||||
else
|
||||
{
|
||||
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
|
||||
svga->hdisp_old = svga->hdisp;
|
||||
|
||||
switch (svga->gdcreg[5] & 0x60)
|
||||
{
|
||||
case 0x00: /*16 colours*/
|
||||
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:
|
||||
if (svga->lowres)
|
||||
svga->render = svga_render_8bpp_lowres;
|
||||
else
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
break;
|
||||
case 15:
|
||||
if (svga->lowres)
|
||||
svga->render = svga_render_15bpp_lowres;
|
||||
else
|
||||
svga->render = svga_render_15bpp_highres;
|
||||
break;
|
||||
case 16:
|
||||
if (svga->lowres)
|
||||
svga->render = svga_render_16bpp_lowres;
|
||||
else
|
||||
svga->render = svga_render_16bpp_highres;
|
||||
break;
|
||||
case 24:
|
||||
if (svga->lowres)
|
||||
svga->render = svga_render_24bpp_lowres;
|
||||
else
|
||||
svga->render = svga_render_24bpp_highres;
|
||||
break;
|
||||
case 32:
|
||||
if (svga->lowres)
|
||||
svga->render = svga_render_32bpp_lowres;
|
||||
else
|
||||
svga->render = svga_render_32bpp_highres;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pclog("svga_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", svga_render, svga_render_text_40, svga_render_text_80, svga_render_8bpp_lowres, svga_render_8bpp_highres, svga_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8);
|
||||
|
||||
svga->linedbl = svga->crtc[9] & 0x80;
|
||||
svga->rowcount = svga->crtc[9] & 31;
|
||||
if (svga->recalctimings_ex)
|
||||
svga->recalctimings_ex(svga);
|
||||
|
||||
if (svga->vblankstart < svga->dispend)
|
||||
svga->dispend = svga->vblankstart;
|
||||
|
||||
crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0);
|
||||
|
||||
disptime = svga->htotal;
|
||||
_dispontime = svga->hdisp_time;
|
||||
|
||||
// printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
|
||||
if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; }
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= crtcconst;
|
||||
_dispofftime *= crtcconst;
|
||||
|
||||
svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT));
|
||||
svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT));
|
||||
/* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock);
|
||||
printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart);
|
||||
printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]);
|
||||
|
||||
pclog("svga->render %08X\n", svga->render);*/
|
||||
}
|
||||
|
||||
void ati28800_recalctimings(svga_t *svga)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)svga->p;
|
||||
@@ -168,6 +337,13 @@ void *ati28800_init()
|
||||
"roms/XLODD.BIN",
|
||||
0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
}
|
||||
else if (gfxcard == GFX_VGAWONDERXL24)
|
||||
{
|
||||
rom_init_interleaved(&ati28800->bios_rom,
|
||||
"roms/112-14318-102.bin",
|
||||
"roms/112-14319-102.bin",
|
||||
0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
|
||||
}
|
||||
else
|
||||
rom_init(&ati28800->bios_rom, "roms/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
@@ -197,6 +373,11 @@ static int compaq_ati28800_available()
|
||||
return (rom_present("roms/XLEVEN.bin") && rom_present("roms/XLODD.bin"));
|
||||
}
|
||||
|
||||
static int ati28800_wonderxl24_available()
|
||||
{
|
||||
return (rom_present("roms/112-14318-102.bin") && rom_present("roms/112-14319-102.bin"));
|
||||
}
|
||||
|
||||
void ati28800_close(void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
@@ -210,7 +391,7 @@ void ati28800_speed_changed(void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
|
||||
svga_recalctimings(&ati28800->svga);
|
||||
ati28800_svga_recalctimings(&ati28800->svga);
|
||||
}
|
||||
|
||||
void ati28800_force_redraw(void *p)
|
||||
@@ -283,3 +464,16 @@ device_t compaq_ati28800_device =
|
||||
ati28800_add_status_info,
|
||||
ati28800_config
|
||||
};
|
||||
|
||||
device_t ati28800_wonderxl24_device =
|
||||
{
|
||||
"ATI-28800 (VGA Wonder XL24)",
|
||||
0,
|
||||
ati28800_init,
|
||||
ati28800_close,
|
||||
ati28800_wonderxl24_available,
|
||||
ati28800_speed_changed,
|
||||
ati28800_force_redraw,
|
||||
ati28800_add_status_info,
|
||||
ati28800_config
|
||||
};
|
||||
|
@@ -1,2 +1,3 @@
|
||||
extern device_t ati28800_device;
|
||||
extern device_t compaq_ati28800_device;
|
||||
extern device_t ati28800_wonderxl24_device;
|
||||
|
@@ -274,6 +274,12 @@ void mach64_out(uint16_t addr, uint8_t val, void *p)
|
||||
break;
|
||||
case 0x1cf:
|
||||
mach64->regs[mach64->index & 0x3f] = val;
|
||||
if ((mach64->index & 0x3f) == 0x2d)
|
||||
{
|
||||
svga->charseta = (svga->charseta & 0x3ffff) | ((((uint32_t) val) >> 4) << 18);
|
||||
svga->charsetb = (svga->charsetb & 0x3ffff) | ((((uint32_t) val) >> 4) << 18);
|
||||
break;
|
||||
}
|
||||
if ((mach64->index & 0x3f) == 0x36)
|
||||
mach64_recalctimings(svga);
|
||||
break;
|
||||
@@ -360,11 +366,18 @@ void mach64_recalctimings(svga_t *svga)
|
||||
svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1;
|
||||
svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1;
|
||||
svga->htotal = (mach64->crtc_h_total_disp & 255) + 1;
|
||||
if (mach64->regs[0x2d] & 8) svga->htotal |= (mach64->regs[0x2d] & 1) ? 0x100 : 0;
|
||||
svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1;
|
||||
svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1;
|
||||
svga->rowoffset = (mach64->crtc_off_pitch >> 22);
|
||||
svga->clock = cpuclock / mach64->ics2595.output_clock;
|
||||
svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2;
|
||||
if (mach64->regs[0x2d] & 8)
|
||||
{
|
||||
svga->ma_latch |= (((uint32_t) (mach64->regs[0x30] & 0x40)) >> 6) << 16;
|
||||
svga->ma_latch |= (((uint32_t) (mach64->regs[0x23] & 0x10)) >> 4) << 17;
|
||||
svga->ma_latch |= (((uint32_t) (mach64->regs[0x2d] & 0xc)) >> 2) << 18;
|
||||
}
|
||||
svga->linedbl = svga->rowcount = 0;
|
||||
svga->split = 0xffffff;
|
||||
svga->vblankstart = svga->dispend;
|
||||
|
@@ -50,7 +50,8 @@ typedef struct
|
||||
static VIDEO_CARD video_cards[] =
|
||||
{
|
||||
{"ATI Graphics Pro Turbo (Mach64 GX)", &mach64gx_device, GFX_MACH64GX},
|
||||
{"ATI VGA Charger (ATI-28800)", &ati28800_device, GFX_VGACHARGER},
|
||||
{"ATI VGA Charger (ATI-28800-5)", &ati28800_device, GFX_VGACHARGER},
|
||||
{"ATI VGA Wonder XL24 (ATI-28800-6)", &ati28800_wonderxl24_device, GFX_VGAWONDERXL24},
|
||||
{"ATI VGA Edge-16 (ATI-18800)", &ati18800_device, GFX_VGAEDGE16},
|
||||
{"Cardex 1703-DDC (ET4000/W32P)", &et4000w32pc_device, GFX_ET4000W32C},
|
||||
{"Cardex ICS5341 (ET4000/W32P)", &et4000w32pcs_device, GFX_ET4000W32CS},
|
||||
@@ -60,7 +61,7 @@ static VIDEO_CARD video_cards[] =
|
||||
{"Diamond Stealth 3D 2000 (S3 ViRGE)", &s3_virge_device, GFX_VIRGE},
|
||||
{"EGA", &ega_device, GFX_EGA},
|
||||
{"Chips & Technologies SuperEGA", &sega_device, GFX_SUPER_EGA},
|
||||
{"Compaq ATI VGA Wonder XL (ATI-28800)", &compaq_ati28800_device, GFX_VGAWONDERXL},
|
||||
{"Compaq ATI VGA Wonder XL (ATI-28800-5)", &compaq_ati28800_device, GFX_VGAWONDERXL},
|
||||
{"Compaq EGA", &cpqega_device, GFX_COMPAQ_EGA},
|
||||
{"Compaq/Paradise VGA", &cpqvga_device, GFX_COMPAQ_VGA},
|
||||
{"Hercules", &hercules_device, GFX_HERCULES},
|
||||
|
Reference in New Issue
Block a user