mirror of
https://github.com/86Box/86Box.git
synced 2025-01-22 17:22:25 -05:00
Merge pull request #563 from 86Box/feature/egawonder800
Added the ATI EGA Wonder 800+ from PCem + updated file versions.
This commit is contained in:
commit
7f0e0cb5bf
5 changed files with 144 additions and 8 deletions
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
* ATI 18800 emulation (VGA Edge-16)
|
||||
*
|
||||
* Version: @(#)vid_ati18800.c 1.0.14 2018/10/02
|
||||
* Version: @(#)vid_ati18800.c 1.0.15 2020/01/18
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
|
@ -39,15 +39,18 @@
|
|||
#endif
|
||||
#define BIOS_ROM_PATH_VGA88 L"roms/video/ati18800/vga88.bin"
|
||||
#define BIOS_ROM_PATH_EDGE16 L"roms/video/ati18800/vgaedge16.vbi"
|
||||
#define BIOS_ROM_PATH_EGAWONDER800P L"roms/video/ati18800/ATI EGA Wonder 800+ N1.00.BIN"
|
||||
|
||||
enum {
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
ATI18800_WONDER = 0,
|
||||
ATI18800_VGA88,
|
||||
ATI18800_EDGE16
|
||||
ATI18800_EDGE16,
|
||||
ATI18800_EGAWONDER800P
|
||||
#else
|
||||
ATI18800_VGA88 = 0,
|
||||
ATI18800_EDGE16
|
||||
ATI18800_EDGE16,
|
||||
ATI18800_EGAWONDER800P
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -61,6 +64,10 @@ typedef struct ati18800_t
|
|||
|
||||
uint8_t regs[256];
|
||||
int index;
|
||||
|
||||
int is_ega;
|
||||
int ega_switches;
|
||||
int ega_switch_read;
|
||||
} ati18800_t;
|
||||
|
||||
static video_timings_t timing_ati18800 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
|
||||
|
@ -71,6 +78,7 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p)
|
|||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
svga_t *svga = &ati18800->svga;
|
||||
uint8_t old;
|
||||
int c;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
@ -103,6 +111,41 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x3c2:
|
||||
if (ati18800->is_ega)
|
||||
{
|
||||
if ((val & 0x80) != (svga->miscout & 0x80))
|
||||
{
|
||||
if (val & 0x80)
|
||||
{
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
svga->pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
svga->pallook[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||
}
|
||||
svga->vertical_linedbl = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
if ((c & 0x17) == 6)
|
||||
svga->pallook[c] = makecol32(0xaa, 0x55, 0x00);
|
||||
else
|
||||
{
|
||||
svga->pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
svga->pallook[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55);
|
||||
}
|
||||
}
|
||||
svga->vertical_linedbl = 1;
|
||||
}
|
||||
|
||||
svga->fullchange = changeframecount;
|
||||
}
|
||||
ati18800->ega_switch_read = val & 0xc;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3D4:
|
||||
svga->crtcreg = val & 0x3f;
|
||||
return;
|
||||
|
@ -153,6 +196,19 @@ static uint8_t ati18800_in(uint16_t addr, void *p)
|
|||
}
|
||||
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:
|
||||
temp = svga->crtcreg;
|
||||
break;
|
||||
|
@ -188,13 +244,32 @@ static void ati18800_recalctimings(svga_t *svga)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *ati18800_init(const device_t *info)
|
||||
{
|
||||
int c;
|
||||
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
|
||||
memset(ati18800, 0, sizeof(ati18800_t));
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati18800);
|
||||
|
||||
ati18800->is_ega = (info->local == ATI18800_EGAWONDER800P);
|
||||
|
||||
switch (info->local) {
|
||||
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
|
||||
case ATI18800_WONDER:
|
||||
|
@ -210,20 +285,46 @@ static void *ati18800_init(const device_t *info)
|
|||
case ATI18800_EDGE16:
|
||||
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
case ATI18800_EGAWONDER800P:
|
||||
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EGAWONDER800P, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
break;
|
||||
};
|
||||
|
||||
if (info->local != ATI18800_EGAWONDER800P) {
|
||||
svga_init(&ati18800->svga, ati18800, 1 << 20, /*512kb*/
|
||||
ati18800_recalctimings,
|
||||
ati18800_in, ati18800_out,
|
||||
NULL,
|
||||
NULL);
|
||||
} else {
|
||||
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, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
if (info->local != ATI18800_EGAWONDER800P)
|
||||
io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
else {
|
||||
io_sethandler(0x03c6, 0x0006, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
io_sethandler(0x03ca, 0x0016, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
|
||||
|
||||
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.miscout = 1;
|
||||
|
||||
ati_eeprom_load(&ati18800->eeprom, L"ati18800.nvr", 0);
|
||||
if (info->local != ATI18800_EGAWONDER800P)
|
||||
ati_eeprom_load(&ati18800->eeprom, L"ati18800.nvr", 0);
|
||||
else {
|
||||
ati18800->ega_switches = 9;
|
||||
ati_eeprom_load(&ati18800->eeprom, L"egawonder800.nvr", 0);
|
||||
}
|
||||
|
||||
return ati18800;
|
||||
}
|
||||
|
@ -245,6 +346,11 @@ static int ati18800_available(void)
|
|||
return rom_present(BIOS_ROM_PATH_EDGE16);
|
||||
}
|
||||
|
||||
static int ega_wonder_800_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH_EGAWONDER800P);
|
||||
}
|
||||
|
||||
static void ati18800_close(void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
|
@ -308,3 +414,16 @@ const device_t ati18800_device =
|
|||
ati18800_force_redraw,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t ati_ega_wonder_800_device =
|
||||
{
|
||||
"ATI EGA Wonder 800+",
|
||||
DEVICE_ISA, ATI18800_EGAWONDER800P,
|
||||
ati18800_init,
|
||||
ati18800_close,
|
||||
NULL,
|
||||
ega_wonder_800_available,
|
||||
ati18800_speed_changed,
|
||||
ati18800_force_redraw,
|
||||
NULL
|
||||
};
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
extern const device_t ati18800_wonder_device;
|
||||
extern const device_t ati18800_vga88_device;
|
||||
extern const device_t ati18800_device;
|
||||
extern const device_t ati_ega_wonder_800_device;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* This is intended to be used by another SVGA driver,
|
||||
* and not as a card in it's own right.
|
||||
*
|
||||
* Version: @(#)vid_svga.c 1.0.40 2019/12/28
|
||||
* Version: @(#)vid_svga.c 1.0.41 2020/01/18
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
|
@ -700,6 +700,12 @@ svga_poll(void *p)
|
|||
svga->ma = svga->maback;
|
||||
}
|
||||
}
|
||||
|
||||
svga->hsync_divisor = !svga->hsync_divisor;
|
||||
|
||||
if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
|
||||
return;
|
||||
|
||||
svga->vc++;
|
||||
svga->vc &= 2047;
|
||||
|
||||
|
@ -1238,7 +1244,10 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
|
|||
} else
|
||||
suppress_overscan = 0;
|
||||
|
||||
set_screen_size(xsize + x_add, ysize + y_add);
|
||||
if (svga->vertical_linedbl)
|
||||
set_screen_size(xsize + x_add, (ysize + y_add) * 2);
|
||||
else
|
||||
set_screen_size(xsize + x_add, ysize + y_add);
|
||||
|
||||
if (video_force_resize_get())
|
||||
video_force_resize_set(0);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
* Generic SVGA handling.
|
||||
*
|
||||
* Version: @(#)vid_svga.h 1.0.15 2018/10/04
|
||||
* Version: @(#)vid_svga.h 1.0.16 2020/01/18
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
|
@ -131,6 +131,12 @@ typedef struct svga_t
|
|||
dac_mask, dac_status,
|
||||
ksc5601_sbyte_mask;
|
||||
|
||||
|
||||
int vertical_linedbl;
|
||||
|
||||
/*Used to implement CRTC[0x17] bit 2 hsync divisor*/
|
||||
int hsync_divisor;
|
||||
|
||||
void *ramdac, *clock_gen;
|
||||
} svga_t;
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ static const VIDEO_CARD
|
|||
video_cards[] = {
|
||||
{ "None", "none", NULL },
|
||||
{ "Internal", "internal", NULL },
|
||||
{ "[ISA] ATI EGA Wonder 800+", "egawonder800", &ati_ega_wonder_800_device },
|
||||
{ "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device },
|
||||
{ "[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device },
|
||||
{ "[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device },
|
||||
|
|
Loading…
Reference in a new issue