From 79ace6997c89db6b80eefb41b6eac9a58a52fd1c Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 14 Apr 2024 16:10:57 +0300 Subject: [PATCH] Merlin/ET4000 updates. --- expansion.cpp | 18 ++++++ gfxboard.cpp | 121 ++++++++++++++++++++++++++++++++++---- include/rommgr.h | 1 + pcem/vid_bt482_ramdac.cpp | 29 +++++++++ pcem/vid_et4000.cpp | 2 + pcem/vid_et4000w32.cpp | 39 +++++++++++- pcem/vid_svga_render.cpp | 19 +++--- 7 files changed, 206 insertions(+), 23 deletions(-) diff --git a/expansion.cpp b/expansion.cpp index 8f8f714a..9ddaf8ad 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -4271,6 +4271,16 @@ static const struct expansionsubromtype a2090_sub[] = { }; #endif +static const struct expansionboardsettings merlin_settings[] = { + { + _T("Serial number\0"), + _T("serial\0"), + 2, false, 0 + }, + { + NULL + } +}; static const struct expansionboardsettings voodoo_settings[] = { { _T("Direct VRAM access in little endian modes"), _T("directvram") @@ -6047,6 +6057,14 @@ const struct expansionromtype expansionroms[] = { NULL, 0, false, EXPANSIONTYPE_RTG }, + { + _T("merlin"), _T("Merlin"), _T("X-Pert Computer Services"), + NULL, NULL, NULL, NULL, ROMTYPE_MERLIN | ROMTYPE_NOT, 0, 0, BOARD_IGNORE, true, + NULL, 0, + false, EXPANSIONTYPE_RTG, + 0, 0, 0, false, NULL, + false, 0, merlin_settings + }, { _T("vooodoo3_3k"), _T("Voodoo 3 3000"), _T("3dfx"), NULL, NULL, NULL, NULL, ROMTYPE_VOODOO3 | ROMTYPE_NONE, 0, 0, BOARD_IGNORE, false, diff --git a/gfxboard.cpp b/gfxboard.cpp index 26214fd0..d18c4399 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -273,14 +273,16 @@ static const struct gfxboard boards[] = _T("Merlin [Zorro II]"), _T("X-Pert Computer Services"), _T("MerlinZ2"), 2117, 3, 4, 0, 0x00000000, 0x00200000, 0x00200000, 0x00200000, 0, 2, 6, false, true, - 0, 0, NULL, &et4000w32_merlin_z2_device + ROMTYPE_MERLIN, + 0, NULL, &et4000w32_merlin_z2_device }, { GFXBOARD_ID_MERLIN_Z3, _T("Merlin [Zorro III]"), _T("X-Pert Computer Services"), _T("MerlinZ3"), 2117, 3, 4, 0, 0x00000000, 0x00200000, 0x00400000, 0x02000000, 0, 3, 6, false, true, - 0, 0, NULL, &et4000w32_merlin_z3_device + ROMTYPE_MERLIN, + 0, NULL, &et4000w32_merlin_z3_device }, { GFXBOARD_ID_GRAFFITY_Z2, @@ -465,7 +467,7 @@ struct rtggfxboard int vga_width, vga_height, vga_width_mult, vga_height_mult; bool vga_refresh_active; int device_settings; - uae_u8 extradata[16]; + uae_u32 extradata[16]; uae_u32 vgaioregionptr, vgavramregionptr, vgabank0regionptr, vgabank1regionptr; @@ -1079,6 +1081,18 @@ static void init_board (struct rtggfxboard *gb) device_add_rethink(gfxboard_rethink); } +static void merlin_init(struct rtggfxboard *gb) +{ + struct boardromconfig *brc = get_device_rom(&currprefs, ROMTYPE_MERLIN, 0, NULL); + if (brc) { + const TCHAR *ser = brc->roms[0].configtext; + gb->extradata[0] = _tstol(ser); + } else { + gb->extradata[0] = 1; + } + gb->extradata[0] ^= 0x5554452A; +} + static int GetBytesPerPixel(RGBFTYPE RGBfmt) { switch (RGBfmt) @@ -2914,6 +2928,7 @@ static void REGPARAM2 gfxboard_wput_mem_autoconfig (uaecptr addr, uae_u32 b) map_banks_z3(&gb->gfxboard_bank_special_pcem, (start + 0x1000000) >> 16, 0x1000000 >> 16); gb->configured_regs = gb->gfxmem_bank->start >> 16; gb->gfxboard_intena = 1; + merlin_init(gb); } else if (boardnum == GFXBOARD_ID_GRAFFITY_Z3) { @@ -3148,6 +3163,7 @@ static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b) gb->pcem_mmio_mask = 0x1fffff; gb->pcem_io_mask = 0xffff; gb->gfxboard_intena = 1; + merlin_init(gb); } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000W32) { @@ -4925,7 +4941,11 @@ bool gfxboard_init_memory (struct autoconfig_info *aci) if (gb->rbc->rtgmem_type == GFXBOARD_ID_VOODOO3_PCI || gb->rbc->rtgmem_type == GFXBOARD_ID_VOODOO5_PCI) { gb->pcibs = pci_board_add(b, &voodoo3_pci_board, -1, -1, aci, gb); } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_PERMEDIA2_PCI) { - gb->pcibs = pci_board_add(b, &permedia2_pci_board, -1, -1, aci, gb); + if (is_device_rom(p, ROMTYPE_GREX, 0) >= 0) { + gb->pcibs = pci_board_add(b, &permedia2_pci_board, 0, -1, aci, gb); + } else { + gb->pcibs = pci_board_add(b, &permedia2_pci_board, -1, -1, aci, gb); + } } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_GD5446_PCI) { gb->pcibs = pci_board_add(b, &gd5446_pci_board, -1, -1, aci, gb); } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_S3TRIO64_PCI) { @@ -5899,6 +5919,80 @@ static void REGPARAM2 gfxboard_lput_mmio_lbs_pcem(uaecptr addr, uae_u32 l) put_mem_pcem(addr, l, 2); } +static uae_u8 get_io_merlin(struct rtggfxboard *gb, uae_u32 addr) +{ + uae_u8 v = 0; + + if (addr < 0x5000) { + v = get_io_pcem(addr, 0); + } + + // 2M vs 4M config bits + if (addr == 0x3ca) { + v &= ~0x0c; + if (gb->gfxboard_bank_vram_pcem.allocated_size >= 0x400000) { + v |= 4; + } + } else if (addr == 0x3c2) { + v |= 0x20; + } + // serial eeprom? + if (addr == 0x81 || addr == 0x01) { + gb->extradata[2] >>= 1; + gb->extradata[1]++; + if (gb->extradata[1] <= 10) { + if (addr == 0x81) { + gb->extradata[2] |= 0x200; + } + if (gb->extradata[1] == 10) { + v = 0; + uae_u16 a = gb->extradata[2]; + uae_u8 aa = a >> 3; + uae_u8 d = 0xff; + if ((a & 7) == 3) { + uae_u8 ser[4] = { gb->extradata[0] >> 24, (uae_u8)(gb->extradata[0] >> 16), (uae_u8)(gb->extradata[0] >> 8), (uae_u8)(gb->extradata[0] >> 0) }; + if (aa == 0x7c) { + d = ser[0]; + } else if (aa == 0x7d) { + d = ser[1]; + } else if (aa == 0x7b) { + d = ser[2]; + } else if (aa == 0x7e) { + d = ser[3]; + } else if (aa == 0x7f) { + // checksum + d = 0; + for (int i = 0; i < 0x7f; i++) { + if (i == 0x7c) { + d += ser[0]; + } else if (i == 0x7d) { + d += ser[1]; + } else if (i == 0x7b) { + d += ser[2]; + } else if (i == 0x7e) { + d += ser[3]; + } else { + d += 0xff; + } + } + d = 0x100 - d; + } + } + gb->extradata[3] = d; + write_log("Merlin serial eeprom read address %04x (%02x) = %02x\n", a, aa, d); + } + } else { + v = ((gb->extradata[3] >> 7) & 1) ? 2 : 0; + gb->extradata[3] <<= 1; + } + } + if (addr == 0x0401) { + gb->extradata[2] = 0; + gb->extradata[1] = 0; + } + + return v; +} static void special_pcem_put(uaecptr addr, uae_u32 v, int size) { @@ -6278,12 +6372,15 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) if (addr == 0x401) { set_monswitch(gb, (v & 0x01) != 0); + gb->extradata[2] = 0; } - if (size) { - put_io_pcem(addr + 0, (v >> 8) & 0xff, 0); - put_io_pcem(addr + 1, (v >> 0) & 0xff, 0); - } else if (size == 0) { - put_io_pcem(addr, v & 0xff, 0); + if (addr < 0x5000) { + if (size) { + put_io_pcem(addr + 0, (v >> 8) & 0xff, 0); + put_io_pcem(addr + 1, (v >> 0) & 0xff, 0); + } else if (size == 0) { + put_io_pcem(addr, v & 0xff, 0); + } } } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000W32) { @@ -6676,10 +6773,10 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) addr &= 0xffff; if (size) { - v = get_io_pcem(addr + 0, 0) << 8; - v |= get_io_pcem(addr + 1, 0) << 0; + v = get_io_merlin(gb, addr + 0) << 8; + v |= get_io_merlin(gb, addr + 1) << 0; } else if (size == 0) { - v = get_io_pcem(addr, 0); + v = get_io_merlin(gb, addr); } } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000W32) { diff --git a/include/rommgr.h b/include/rommgr.h index 5600195b..2b33fc4a 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -213,6 +213,7 @@ extern int decode_cloanto_rom_do(uae_u8 *mem, int size, int real_size); #define ROMTYPE_ALTAIS 0x00100090 #define ROMTYPE_PROMETHEUSFS 0x00100091 #define ROMTYPE_RAINBOWII 0x00100092 +#define ROMTYPE_MERLIN 0x00100093 #define ROMTYPE_NOT 0x00800000 #define ROMTYPE_QUAD 0x01000000 diff --git a/pcem/vid_bt482_ramdac.cpp b/pcem/vid_bt482_ramdac.cpp index 38066ce5..cffa63f9 100644 --- a/pcem/vid_bt482_ramdac.cpp +++ b/pcem/vid_bt482_ramdac.cpp @@ -23,6 +23,7 @@ bt482_set_bpp(bt482_ramdac_t *ramdac, svga_t *svga) svga->swaprb = (ramdac->cmd_r0 & 2) == 0; break; case 0x09: + case 0x0b: svga->bpp = 32; svga->swaprb = (ramdac->cmd_r0 & 2) == 0; break; @@ -67,6 +68,7 @@ bt482_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga) { case 2: // command B svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT; + ramdac->cmd_r1 = val; break; case 3: // cursor ramdac->cursor_r = val; @@ -136,6 +138,31 @@ bt482_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga) case 0x00: /* Palette Write Index Register (RS value = 0000) */ temp = svga_in(addr, svga); break; + case 0x02: + if (ramdac->cmd_r0 & 1) { + switch (svga->dac_addr) + { + case 2: // command B + temp = ramdac->cmd_r1; + break; + case 3: // cursor + temp = ramdac->cursor_r ; + break; + case 4: // cursor x low + temp = ramdac->hwc_x & 0xff; + break; + case 5: // cursor x high + temp = (ramdac->hwc_x >> 8) & 0xff; + break; + case 6: // cursor y low + temp = ramdac->hwc_y & 0xff; + break; + case 7: // cursor y high + temp = (ramdac->hwc_y >> 8) & 0xff; + break; + } + } + break; case 0x03: /* Palette Read Index Register (RS value = 0011) */ temp = svga->dac_addr & 0xff; break; @@ -177,6 +204,8 @@ bt482_hwcursor_draw(svga_t *svga, int displine) clr2 = ramdac->extpallook[2]; clr3 = ramdac->extpallook[3]; + offset <<= svga->horizontal_linedbl; + /* The planes come in two parts, and each plane is 1bpp, 32x32 cursor has 4 bytes per line */ pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */ diff --git a/pcem/vid_et4000.cpp b/pcem/vid_et4000.cpp index 2ada2211..10f1b9f4 100644 --- a/pcem/vid_et4000.cpp +++ b/pcem/vid_et4000.cpp @@ -713,6 +713,8 @@ et4000_recalctimings(svga_t *svga) break; } + svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + #if 0 if (dev->type == ET4000_TYPE_KOREAN || dev->type == ET4000_TYPE_TRIGEM || dev->type == ET4000_TYPE_KASAN) { if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { diff --git a/pcem/vid_et4000w32.cpp b/pcem/vid_et4000w32.cpp index f87e489b..9b49625e 100644 --- a/pcem/vid_et4000w32.cpp +++ b/pcem/vid_et4000w32.cpp @@ -132,8 +132,9 @@ typedef struct et4000w32p_t { static int et4000w32_vbus[4] = { 1, 2, 4, 4 }; -static int et4000w32_max_x[8] = { 0, 0, 4, 8, 0x10, 0x20, 0x40, 0x70000000 }; -static int et4000w32_wrap_x[8] = { 0, 0, 3, 7, 0x0f, 0x1f, 0x3f, ~0 }; +// TW: At least W32 horizontal wrap 0 equals 1 (documentation says "reserved"). Fixes Amiga ProBench 2.x glitches. +static int et4000w32_max_x[8] = { 1, 1, 4, 8, 0x10, 0x20, 0x40, 0x70000000 }; +static int et4000w32_wrap_x[8] = { 1, 1, 3, 7, 0x0f, 0x1f, 0x3f, ~0 }; static int et4000w32_wrap_y[8] = { 1, 2, 4, 8, ~0, ~0, ~0, ~0 }; //static video_timings_t timing_et4000w32_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 4, .read_b = 10, .read_w = 10, .read_l = 10 }; @@ -424,7 +425,17 @@ et4000w32p_in(uint16_t addr, void *priv) svga->cgastat &= ~0x32; else svga->cgastat ^= 0x32; - return svga->cgastat; + + ret = svga->cgastat; + + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; + + if (ret & 0x08) + ret &= 0x7f; + else + ret |= 0x80; + return ret; case 0x210a: case 0x211a: @@ -506,6 +517,15 @@ et4000w32p_recalctimings(svga_t *svga) bt482_recalctimings(et4000->ramdac_bt, svga); } + svga->interlace = svga->crtc[0x35] & 0x80; + if (svga->interlace) { + int shift = (svga->crtc[0x17] & 4) ? 2 : 1; + svga->vtotal >>= shift; + svga->vsyncstart >>= shift; + svga->vblankstart >>= shift; + svga->dispend >>= shift; + } + //svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); if (et4000->type != ET4000W32P_DIAMOND) { @@ -522,6 +542,9 @@ et4000w32p_recalctimings(svga_t *svga) case 24: svga->clock /= 4; break; + case 32: + svga->clock /= 4; + break; default: break; @@ -573,11 +596,17 @@ et4000w32p_recalctimings(svga_t *svga) svga->hdisp = 640; } break; + case 32: + svga->hdisp /= 4; + svga->dots_per_clock /= 4; + break; default: break; } + svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + svga->render = svga_render_blank; if (!svga->scrblank && svga->attr_palette_enable) { if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ @@ -2792,6 +2821,7 @@ et4000w32p_hwcursor_draw(svga_t *svga, int displine) uint8_t dat; offset = svga->hwcursor_latch.xoff; + offset <<= svga->horizontal_linedbl; if ((et4000->type == ET4000W32) && (pitch == 32)) { switch (svga->bpp) { @@ -3030,6 +3060,9 @@ static void et4000w32_adjust_panning(svga_t *svga) case 24: src += ar11 & 3; break; + case 32: + src += ar11 & 3; + break; default: return; } diff --git a/pcem/vid_svga_render.cpp b/pcem/vid_svga_render.cpp index 05213ec1..06d41df0 100644 --- a/pcem/vid_svga_render.cpp +++ b/pcem/vid_svga_render.cpp @@ -994,6 +994,7 @@ void svga_render_32bpp_lowres(svga_t *svga) { int x; int offset = svga->scrollcache_dst; + int shift = svga->scrollcache_src; uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; if (svga->firstline_draw == 4000) @@ -1004,7 +1005,7 @@ void svga_render_32bpp_lowres(svga_t *svga) { for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + shift + (x << 2)) & svga->vram_display_mask]); *p++ = dat & 0xffffff; *p++ = dat & 0xffffff; } @@ -1014,7 +1015,7 @@ void svga_render_32bpp_lowres(svga_t *svga) { for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) { - uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t addr = svga->remap_func(svga, svga->ma + shift); uint32_t dat = *(uint32_t *)(&svga->vram[addr]); *p++ = dat & 0xffffff; *p++ = dat & 0xffffff; @@ -1033,6 +1034,7 @@ void svga_render_32bpp_lowres_swaprb(svga_t *svga) { int x; int offset = svga->scrollcache_dst; + int shift = svga->scrollcache_src; uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; if (svga->firstline_draw == 4000) @@ -1043,7 +1045,7 @@ void svga_render_32bpp_lowres_swaprb(svga_t *svga) { for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + shift + (x << 2)) & svga->vram_display_mask]); dat = ((dat & 0xff0000) >> 16) | ((dat & 0x0000ff) << 16) | ((dat & 0x00ff00)); *p++ = dat & 0xffffff; *p++ = dat & 0xffffff; @@ -1054,7 +1056,7 @@ void svga_render_32bpp_lowres_swaprb(svga_t *svga) { for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) { - uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t addr = svga->remap_func(svga, svga->ma + shift); uint32_t dat = *(uint32_t *)(&svga->vram[addr]); dat = ((dat & 0xff0000) >> 16) | ((dat & 0x0000ff) << 16) | ((dat & 0x00ff00)); *p++ = dat & 0xffffff; @@ -1075,6 +1077,7 @@ void svga_render_32bpp_highres(svga_t *svga) { int x; int offset = svga->scrollcache_dst; + int shift = svga->scrollcache_src; uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; if (svga->firstline_draw == 4000) @@ -1085,7 +1088,7 @@ void svga_render_32bpp_highres(svga_t *svga) { for (x = 0; x <= svga->hdisp; x++) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + shift + (x << 2)) & svga->vram_display_mask]); *p++ = dat & 0xffffff; } svga->ma += x * 4; @@ -1094,7 +1097,7 @@ void svga_render_32bpp_highres(svga_t *svga) { for (x = 0; x <= svga->hdisp; x++) { - uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t addr = svga->remap_func(svga, svga->ma + shift); uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); *p++ = dat & 0xffffff; svga->ma += 4; @@ -1124,7 +1127,7 @@ void svga_render_32bpp_highres_swaprb(svga_t *svga) { for (x = 0; x <= svga->hdisp; x++) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + shift + (x << 2)) & svga->vram_display_mask]); dat = ((dat & 0xff0000) >> 16) | ((dat & 0x0000ff) << 16) | ((dat & 0x00ff00)); *p++ = dat & 0xffffff; } @@ -1134,7 +1137,7 @@ void svga_render_32bpp_highres_swaprb(svga_t *svga) { for (x = 0; x <= svga->hdisp; x++) { - uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t addr = svga->remap_func(svga, svga->ma + shift); uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); dat = ((dat & 0xff0000) >> 16) | ((dat & 0x0000ff) << 16) | ((dat & 0x00ff00)); *p++ = dat & 0xffffff; -- 2.47.3