diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index fa4b22044..43925c733 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -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, * Miran Grca, @@ -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 +}; diff --git a/src/video/vid_ati18800.h b/src/video/vid_ati18800.h index b41facab3..725f5cc73 100644 --- a/src/video/vid_ati18800.h +++ b/src/video/vid_ati18800.h @@ -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; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 8a5aeca5a..6b3044aef 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -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, * Miran Grca, @@ -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); diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index be4db180e..d04a1bb99 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -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, * Miran Grca, @@ -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; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index b72a71e08..cec443f7d 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -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 },