diff --git a/src/ibm.h b/src/ibm.h index 4212fad..e59b322 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -300,6 +300,7 @@ enum GFX_SIGMA400, /*Sigma Designs Color 400 */ GFX_PGC, /*Professional Graphics Controller */ GFX_IM1024, /*Vermont Microsystems IM1024 */ + GFX_EGAWONDER800, /*ATI EGA Wonder 800+*/ GFX_MAX }; diff --git a/src/vid_ati18800.c b/src/vid_ati18800.c index 7e672a0..fd00caa 100644 --- a/src/vid_ati18800.c +++ b/src/vid_ati18800.c @@ -19,6 +19,10 @@ typedef struct ati18800_t uint8_t regs[256]; int index; + + int is_ega; + int ega_switches; + int ega_switch_read; } ati18800_t; 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; + 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: svga->crtcreg = val & 0x3f; return; @@ -109,6 +150,20 @@ 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; @@ -119,10 +174,25 @@ uint8_t ati18800_in(uint16_t addr, void *p) temp = svga_in(addr, svga); 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; } +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() { ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); @@ -146,11 +216,51 @@ void *ati18800_init() 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() { 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) { ati18800_t *ati18800 = (ati18800_t *)p; @@ -193,3 +303,14 @@ device_t ati18800_device = 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 +}; diff --git a/src/vid_ati18800.h b/src/vid_ati18800.h index 83fe2c0..0d667ab 100644 --- a/src/vid_ati18800.h +++ b/src/vid_ati18800.h @@ -1 +1,2 @@ extern device_t ati18800_device; +extern device_t ati_ega_wonder_800_device; diff --git a/src/vid_ati_eeprom.c b/src/vid_ati_eeprom.c index 3586894..ce13701 100644 --- a/src/vid_ati_eeprom.c +++ b/src/vid_ati_eeprom.c @@ -37,7 +37,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type) f = nvrfopen(eeprom->fn, "rb"); if (!f) { - memset(eeprom->data, 0, eeprom->type ? 512 : 128); + memset(eeprom->data, 0xff, eeprom->type ? 512 : 128); return; } fread(eeprom->data, 1, eeprom->type ? 512 : 128, f); diff --git a/src/vid_svga.c b/src/vid_svga.c index 538b131..3418ae1 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -582,6 +582,11 @@ void 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; @@ -1296,7 +1301,10 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) if (xsize<64) xsize=656; if (ysize<32) ysize=200; - updatewindowsize(xsize,ysize); + if (svga->vertical_linedbl) + updatewindowsize(xsize,ysize*2); + else + updatewindowsize(xsize,ysize); } if (vid_resize) { diff --git a/src/vid_svga.h b/src/vid_svga.h index 08f5111..5a7efa3 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -129,6 +129,11 @@ typedef struct svga_t void *p; uint8_t ksc5601_sbyte_mask; + + int vertical_linedbl; + + /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ + int hsync_divisor; } svga_t; extern int svga_init(svga_t *svga, void *p, int memsize, diff --git a/src/video.c b/src/video.c index 7eb151d..3b31973 100644 --- a/src/video.c +++ b/src/video.c @@ -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 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 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}},