Add ATI EGA Wonder 800+ emulation.
This commit is contained in:
parent
2c6b130ec8
commit
2489fd9c6e
7 changed files with 140 additions and 3 deletions
|
|
@ -300,6 +300,7 @@ enum
|
||||||
GFX_SIGMA400, /*Sigma Designs Color 400 */
|
GFX_SIGMA400, /*Sigma Designs Color 400 */
|
||||||
GFX_PGC, /*Professional Graphics Controller */
|
GFX_PGC, /*Professional Graphics Controller */
|
||||||
GFX_IM1024, /*Vermont Microsystems IM1024 */
|
GFX_IM1024, /*Vermont Microsystems IM1024 */
|
||||||
|
GFX_EGAWONDER800, /*ATI EGA Wonder 800+*/
|
||||||
GFX_MAX
|
GFX_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ typedef struct ati18800_t
|
||||||
|
|
||||||
uint8_t regs[256];
|
uint8_t regs[256];
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
int is_ega;
|
||||||
|
int ega_switches;
|
||||||
|
int ega_switch_read;
|
||||||
} ati18800_t;
|
} ati18800_t;
|
||||||
|
|
||||||
void ati18800_out(uint16_t addr, uint8_t val, void *p)
|
void ati18800_out(uint16_t addr, uint8_t val, void *p)
|
||||||
|
|
@ -56,6 +60,43 @@ void ati18800_out(uint16_t addr, uint8_t val, void *p)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x3c2:
|
||||||
|
if (ati18800->is_ega)
|
||||||
|
{
|
||||||
|
if ((val & 0x80) != (svga->miscout & 0x80))
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (val & 0x80)
|
||||||
|
{
|
||||||
|
for (c = 0; c < 256; c++)
|
||||||
|
{
|
||||||
|
ati18800->svga.pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||||
|
ati18800->svga.pallook[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||||
|
}
|
||||||
|
ati18800->svga.vertical_linedbl = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (c = 0; c < 256; c++)
|
||||||
|
{
|
||||||
|
if ((c & 0x17) == 6)
|
||||||
|
ati18800->svga.pallook[c] = makecol32(0xaa, 0x55, 0x00);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ati18800->svga.pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||||
|
ati18800->svga.pallook[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ati18800->svga.vertical_linedbl = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svga->fullchange = changeframecount;
|
||||||
|
}
|
||||||
|
ati18800->ega_switch_read = val & 0xc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x3D4:
|
case 0x3D4:
|
||||||
svga->crtcreg = val & 0x3f;
|
svga->crtcreg = val & 0x3f;
|
||||||
return;
|
return;
|
||||||
|
|
@ -109,6 +150,20 @@ uint8_t ati18800_in(uint16_t addr, void *p)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x3c2:
|
||||||
|
if (ati18800->is_ega)
|
||||||
|
{
|
||||||
|
switch (ati18800->ega_switch_read)
|
||||||
|
{
|
||||||
|
case 0xc: return (ati18800->ega_switches & 1) ? 0x10 : 0;
|
||||||
|
case 0x8: return (ati18800->ega_switches & 2) ? 0x10 : 0;
|
||||||
|
case 0x4: return (ati18800->ega_switches & 4) ? 0x10 : 0;
|
||||||
|
case 0x0: return (ati18800->ega_switches & 8) ? 0x10 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 0x3D4:
|
case 0x3D4:
|
||||||
temp = svga->crtcreg;
|
temp = svga->crtcreg;
|
||||||
break;
|
break;
|
||||||
|
|
@ -119,10 +174,25 @@ uint8_t ati18800_in(uint16_t addr, void *p)
|
||||||
temp = svga_in(addr, svga);
|
temp = svga_in(addr, svga);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc);
|
// if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ega_wonder_800_recalctimings(svga_t *svga)
|
||||||
|
{
|
||||||
|
ati18800_t *ati18800 = (ati18800_t *)svga->p;
|
||||||
|
int clksel = ((svga->miscout & 0xc) >> 2) | ((ati18800->regs[0xbe] & 0x10) ? 4 : 0);
|
||||||
|
|
||||||
|
switch (clksel)
|
||||||
|
{
|
||||||
|
case 0: svga->clock = (cpuclock * (double)(1ull << 32)) / 25175000.0; break;
|
||||||
|
case 1: svga->clock = (cpuclock * (double)(1ull << 32)) / 28322000.0; break;
|
||||||
|
case 4: svga->clock = (cpuclock * (double)(1ull << 32)) / 14318181.0; break;
|
||||||
|
case 5: svga->clock = (cpuclock * (double)(1ull << 32)) / 16257000.0; break;
|
||||||
|
case 7: default: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void *ati18800_init()
|
void *ati18800_init()
|
||||||
{
|
{
|
||||||
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
|
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
|
||||||
|
|
@ -146,11 +216,51 @@ void *ati18800_init()
|
||||||
return ati18800;
|
return ati18800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *ega_wonder_800_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
|
||||||
|
memset(ati18800, 0, sizeof(ati18800_t));
|
||||||
|
|
||||||
|
rom_init(&ati18800->bios_rom, "ATI EGA Wonder 800+ N1.00.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||||
|
|
||||||
|
svga_init(&ati18800->svga, ati18800, 1 << 18, /*256kb*/
|
||||||
|
ega_wonder_800_recalctimings,
|
||||||
|
ati18800_in, ati18800_out,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||||
|
io_sethandler(0x03c0, 0x0006, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||||
|
io_sethandler(0x03ca, 0x0016, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||||
|
|
||||||
|
ati18800->svga.miscout = 1;
|
||||||
|
|
||||||
|
for (c = 0; c < 256; c++)
|
||||||
|
{
|
||||||
|
ati18800->svga.pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||||
|
ati18800->svga.pallook[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||||
|
}
|
||||||
|
|
||||||
|
ati_eeprom_load(&ati18800->eeprom, "egawonder800.nvr", 0);
|
||||||
|
|
||||||
|
ati18800->is_ega = 1;
|
||||||
|
ati18800->ega_switches = 9;
|
||||||
|
|
||||||
|
return ati18800;
|
||||||
|
}
|
||||||
|
|
||||||
static int ati18800_available()
|
static int ati18800_available()
|
||||||
{
|
{
|
||||||
return rom_present("vgaedge16.vbi");
|
return rom_present("vgaedge16.vbi");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ega_wonder_800_available()
|
||||||
|
{
|
||||||
|
return rom_present("ATI EGA Wonder 800+ N1.00.BIN");
|
||||||
|
}
|
||||||
|
|
||||||
void ati18800_close(void *p)
|
void ati18800_close(void *p)
|
||||||
{
|
{
|
||||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||||
|
|
@ -193,3 +303,14 @@ device_t ati18800_device =
|
||||||
ati18800_add_status_info
|
ati18800_add_status_info
|
||||||
};
|
};
|
||||||
|
|
||||||
|
device_t ati_ega_wonder_800_device =
|
||||||
|
{
|
||||||
|
"ATI EGA Wonder 800+",
|
||||||
|
0,
|
||||||
|
ega_wonder_800_init,
|
||||||
|
ati18800_close,
|
||||||
|
ega_wonder_800_available,
|
||||||
|
ati18800_speed_changed,
|
||||||
|
ati18800_force_redraw,
|
||||||
|
ati18800_add_status_info
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
extern device_t ati18800_device;
|
extern device_t ati18800_device;
|
||||||
|
extern device_t ati_ega_wonder_800_device;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
|
||||||
f = nvrfopen(eeprom->fn, "rb");
|
f = nvrfopen(eeprom->fn, "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
memset(eeprom->data, 0, eeprom->type ? 512 : 128);
|
memset(eeprom->data, 0xff, eeprom->type ? 512 : 128);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
|
fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
|
||||||
|
|
|
||||||
|
|
@ -582,6 +582,11 @@ void svga_poll(void *p)
|
||||||
svga->ma = svga->maback;
|
svga->ma = svga->maback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
svga->hsync_divisor = !svga->hsync_divisor;
|
||||||
|
|
||||||
|
if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
|
||||||
|
return;
|
||||||
|
|
||||||
svga->vc++;
|
svga->vc++;
|
||||||
svga->vc &= 2047;
|
svga->vc &= 2047;
|
||||||
|
|
||||||
|
|
@ -1296,7 +1301,10 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
|
||||||
if (xsize<64) xsize=656;
|
if (xsize<64) xsize=656;
|
||||||
if (ysize<32) ysize=200;
|
if (ysize<32) ysize=200;
|
||||||
|
|
||||||
updatewindowsize(xsize,ysize);
|
if (svga->vertical_linedbl)
|
||||||
|
updatewindowsize(xsize,ysize*2);
|
||||||
|
else
|
||||||
|
updatewindowsize(xsize,ysize);
|
||||||
}
|
}
|
||||||
if (vid_resize)
|
if (vid_resize)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@ typedef struct svga_t
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
uint8_t ksc5601_sbyte_mask;
|
uint8_t ksc5601_sbyte_mask;
|
||||||
|
|
||||||
|
int vertical_linedbl;
|
||||||
|
|
||||||
|
/*Used to implement CRTC[0x17] bit 2 hsync divisor*/
|
||||||
|
int hsync_divisor;
|
||||||
} svga_t;
|
} svga_t;
|
||||||
|
|
||||||
extern int svga_init(svga_t *svga, void *p, int memsize,
|
extern int svga_init(svga_t *svga, void *p, int memsize,
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ static VIDEO_CARD video_cards[] =
|
||||||
{
|
{
|
||||||
{"ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx", &mach64gx_device, GFX_MACH64GX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
{"ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx", &mach64gx_device, GFX_MACH64GX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
||||||
{"ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
{"ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
|
||||||
|
{"ATI EGA Wonder 800+ (ATI-18800)", "egawonder800", &ati_ega_wonder_800_device, GFX_EGAWONDER800, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||||
{"ATI Korean VGA (ATI-28800)", "ati28800k", &ati28800k_device, GFX_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
{"ATI Korean VGA (ATI-28800)", "ati28800k", &ati28800k_device, GFX_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||||
{"ATI VGA Charger (ATI-28800)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
{"ATI VGA Charger (ATI-28800)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
|
||||||
{"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
{"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue