From: Toni Wilen Date: Wed, 3 Apr 2024 16:01:44 +0000 (+0300) Subject: Merlin blitter fix, oMniBus, Graffity and Rainbow II RTG cards. X-Git-Tag: 5300~50 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=111c54828c48290fca808947c52a9eaa714e07ec;p=francis%2Fwinuae.git Merlin blitter fix, oMniBus, Graffity and Rainbow II RTG cards. --- diff --git a/expansion.cpp b/expansion.cpp index e311aeee..ec9fd196 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -4733,6 +4733,17 @@ static const struct expansionboardsettings harlequin_settings[] = { } }; +static const struct expansionboardsettings rainbow2_settings[] = { + { + _T("Mode\0") _T("NTSC\0") _T("PAL\0"), + _T("mode\0") _T("ntsc\0") _T("pal\0"), + true + }, + { + NULL + } +}; + static const struct expansionboardsettings cubo_settings[] = { { _T("DIP1 #1"), @@ -6082,6 +6093,14 @@ const struct expansionromtype expansionroms[] = { 0, 0, 0, false, NULL, false, 0, harlequin_settings }, + { + _T("rainbowii"), _T("Rainbow II"), _T("Ingenieurburo Helfrich"), + NULL, NULL, NULL, NULL, ROMTYPE_RAINBOWII | ROMTYPE_NOT, 0, 0, BOARD_IGNORE, false, + NULL, 0, + false, EXPANSIONTYPE_RTG, + 0, 0, 0, false, NULL, + false, 0, rainbow2_settings + }, /* Sound Cards */ { diff --git a/framebufferboards.cpp b/framebufferboards.cpp index 103d2cbe..68682ae1 100644 --- a/framebufferboards.cpp +++ b/framebufferboards.cpp @@ -82,6 +82,16 @@ static void fb_free_surface(struct fb_struct *data) data->surface = NULL; } +static void fb_irq(struct fb_struct *data) +{ + if (!data->irq) + return; + if (data->irq == 2) + INTREQ_0(0x8000 | 0x0008); + else if (data->irq == 6) + INTREQ_0(0x8000 | 0x2000); +} + static void harlequin_offset(struct fb_struct *data) { int offset = data->data[0] & 0x3f; @@ -258,6 +268,7 @@ static bool harlequin_init(struct autoconfig_info *aci) fb_boards++; return true; } + static void harlequin_free(void *userdata) { struct fb_struct *data = (struct fb_struct*)userdata; @@ -271,16 +282,6 @@ static void harlequin_free(void *userdata) xfree(data); } -static void fb_irq(struct fb_struct *data) -{ - if (!data->irq) - return; - if (data->irq == 2) - INTREQ_0(0x8000 | 0x0008); - else if (data->irq == 6) - INTREQ_0(0x8000 | 0x2000); -} - static void harlequin_reset(void *userdata) { struct fb_struct *data = (struct fb_struct*)userdata; @@ -407,6 +408,235 @@ static void harlequin_configured(void *userdata, uae_u32 address) data->io_end = data->io_start + 0x20000; } +static void harlequin_refresh(void *userdata) +{ +} + + + +static void rainbow2_setmode(struct fb_struct *data) +{ + int mode = data->ntsc; + if (data->data[0] & 4) { + mode = mode ? 0 : 1; + } + switch (mode) + { + case 0: + data->width = 768; + data->height = 576; + break; + case 1: + data->width = 768; + data->height = 476; + break; + } + data->lace = (data->data[0] & 1) != 0; +} + +static void REGPARAM2 rainbow2_wput(struct fb_struct *data, uaecptr addr, uae_u32 w) +{ + addr &= 0x1fffff; + if (addr < 0x1c0000) { + data->fb[addr + 0] = (uae_u8)(w >> 8); + data->fb[addr + 1] = (uae_u8)(w >> 0); + data->fb_modified = true; + } +} +static void REGPARAM2 rainbow2_bput(struct fb_struct *data, uaecptr addr, uae_u32 b) +{ + addr &= 0x1fffff; + if (addr == 0x1ffff8) { + // bit 0: interlace (only makes odd/even fields, does not increase resolution) + // bit 1: display enable + // bit 2: toggle PAL/NTSC (yes, toggle, not set!) + // bit 3: 0=read ROM, 1= read VRAM + data->data[0] = b; + rainbow2_setmode(data); + } + if (addr < 0x18000 && (data->data[0] & 8)) { + data->fb[addr] = (uae_u8)b; + data->fb_modified = true; + } +} +static uae_u32 REGPARAM2 rainbow2_wget(struct fb_struct *data, uaecptr addr) +{ + uae_u32 v = 0; + addr &= 0x1fffff; + if (addr < 0x1c0000 && (data->data[0] & 8)) { + v = data->fb[addr + 0] << 8; + v |= data->fb[addr + 1] << 0; + } + return v; +} +static uae_u32 REGPARAM2 rainbow2_bget(struct fb_struct *data, uaecptr addr) +{ + uae_u8 v = 0; + addr &= 0x1fffff; + if (addr == 0x1ffff8) { + v = data->data[0]; + } + if (addr < 0x1c0000 && (data->data[0] & 8)) { + v = data->fb[addr]; + } + return 0; +} + +static bool rainbow2_init(struct autoconfig_info *aci) +{ + int vram = 0x200000; + bool ntsc = true; + + aci->label = _T("Rainbow II"); + + struct boardromconfig *brc = get_device_rom(aci->prefs, ROMTYPE_RAINBOWII, gfxboard_get_devnum(aci->prefs, aci->devnum), NULL); + if (brc) { + ntsc = (brc->roms[0].device_settings & 1) == 0; + } + + if (!aci->doinit) { + return true; + } + struct fb_struct *data = xcalloc(struct fb_struct, 1); + data->devnum = aci->devnum; + fb_data[data->devnum] = data; + + data->bget = rainbow2_bget; + data->wget = rainbow2_wget; + data->bput = rainbow2_bput; + data->wput = rainbow2_wput; + + data->ntsc = ntsc; + data->fb_vram_size = vram; + data->fb_vram_mask = data->fb_vram_size - 1; + data->fb = xcalloc(uae_u8, data->fb_vram_size); + + data->rgbtype = RGBFB_A8R8G8B8; + + rainbow2_setmode(data); + + aci->addrbank = &generic_fb_bank; + aci->userdata = data; + + fb_boards++; + return true; +} +static void rainbow2_free(void *userdata) +{ + struct fb_struct *data = (struct fb_struct *)userdata; + + fb_free_surface(data); + + xfree(data->fb); + data->fb = NULL; + + fb_data[data->devnum] = NULL; + xfree(data); +} + +static void rainbow2_reset(void *userdata) +{ + struct fb_struct *data = (struct fb_struct *)userdata; + fb_boards = 0; + fb_last = NULL; +} + +static void rainbow2_hsync(void *userdata) +{ + struct fb_struct *data = (struct fb_struct *)userdata; + fb_irq(data); +} + +static void rainbow2_convert(struct fb_struct *data) +{ + struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[data->monitor_id]; + + int sy = 0; + int w = vidinfo->width < data->width ? vidinfo->width : data->width; + int h = vidinfo->height < data->height ? vidinfo->height : data->height; + for (int y = 0; y < h; y++) { + uae_u8 *s = data->fb + sy * data->width * 4; + if (!(data->data[0] & 2)) { + uae_u32 tmp[768]; + memset(tmp, 0, sizeof(tmp)); + fb_copyrow(data->monitor_id, (uae_u8*)tmp, data->surface, 0, 0, data->width, 4, y); + } else { + fb_copyrow(data->monitor_id, s, data->surface, 0, 0, data->width, 4, y); + } + sy++; + } +} + +static bool rainbow2_vsync(void *userdata, struct gfxboard_mode *mode) +{ + struct fb_struct *data = (struct fb_struct *)userdata; + bool rendered = false; + + if (data->visible) { + + mode->width = data->width; + mode->height = data->height; + mode->mode = data->rgbtype; + mode->hlinedbl = 1; + mode->vlinedbl = 1; + + if (fb_get_surface(data)) { + if (data->fb_modified || data->modechanged || mode->redraw_required) { + + data->fb_modified = false; + data->modechanged = false; + + rainbow2_convert(data); + } + fb_free_surface(data); + rendered = true; + } + + } + + return rendered; +} + +static bool rainbow2_toggle(void *userdata, int mode) +{ + struct fb_struct *data = (struct fb_struct *)userdata; + + if (!data->configured) + return false; + + if (!mode) { + if (!data->enabled) + return false; + data->enabled = false; + data->modechanged = false; + data->visible = false; + return true; + } else { + if (data->enabled) + return false; + data->enabled = true; + data->modechanged = true; + data->visible = true; + return true; + } + return false; +} + +static void rainbow2_configured(void *userdata, uae_u32 address) +{ + struct fb_struct *data = (struct fb_struct *)userdata; + + data->configured = address; + data->io_start = address; + data->io_end = data->io_start + 0x200000; +} + +static void rainbow2_refresh(void *userdata) +{ +} + + + static struct fb_struct *getfbboard(uaecptr addr) { if (fb_boards == 1) @@ -488,10 +718,6 @@ static addrbank generic_fb_bank ABFLAG_IO, S_READ, S_WRITE }; -static void harlequin_refresh(void *userdata) -{ -} - struct gfxboard_func harlequin_func { harlequin_init, @@ -503,3 +729,15 @@ struct gfxboard_func harlequin_func harlequin_toggle, harlequin_configured }; + +struct gfxboard_func rainbowii_func +{ + rainbow2_init, + rainbow2_free, + rainbow2_reset, + rainbow2_hsync, + rainbow2_vsync, + rainbow2_refresh, + rainbow2_toggle, + rainbow2_configured +}; diff --git a/gfxboard.cpp b/gfxboard.cpp index f60cdf48..26214fd0 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -210,6 +210,13 @@ static const struct gfxboard boards[] = 0x00000000, 0x00400000, 0x00400000, 0x10000000, 0, 3, 2, false, false, 0, 0, NULL, &s3_virge_device, 0x40 }, + { + GFXBOARD_ID_PERMEDIA2_PCI, + _T("BlizzardVision/CyberVision PPC (Permedia2) [PCI]"), _T("3DLabs"), _T("PERMEDIA2_PCI"), + 0, 0, 0, 0, + 0x00000000, 0x00800000, 0x00800000, 0x10000000, 0, 0, -1, false, false, + 0, 0, NULL, &permedia2_device, 0, GFXBOARD_BUSTYPE_PCI + }, { GFXBOARD_ID_PICASSO2, _T("Picasso II [Zorro II]"), _T("Village Tronic"), _T("PicassoII"), @@ -262,11 +269,32 @@ static const struct gfxboard boards[] = 0, 0, NULL, &ncr_retina_z3_device, 0, GFXBOARD_BUSTYPE_DRACO }, { - GFXBOARD_ID_PIXEL64, - _T("Pixel64 [AteoBus]"), _T("Atéo Concepts"), _T("Pixel64"), - 2026, 255, 254, 0, // 255: type=$c7 flags=$40, 254: type=$c2 flags=$40 128k, 252: type=$c2 flags=$40, 128k - 0x00000000, 0x00200000, 0x00200000, 0x00400000, CIRRUS_ID_CLGD5434, 2, 0, false, false, - 0, 0, NULL, &gd5434_vlb_device + GFXBOARD_ID_MERLIN_Z2, + _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 + }, + { + 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 + }, + { + GFXBOARD_ID_GRAFFITY_Z2, + _T("Graffity [Zorro II]"), _T("Atéo Concepts"), _T("GraffityZ2"), + 2092, 34, 33, 0, + 0x00000000, 0x00100000, 0x00200000, 0x00200000, CIRRUS_ID_CLGD5428, 2, 2, false, true, + 0, 0, NULL, &gd5428_device + }, + { + GFXBOARD_ID_GRAFFITY_Z3, + _T("Graffity [Zorro III]"), _T("Atéo Concepts"), _T("GraffityZ3"), + 2092, 33, 0, 0, + 0x00000000, 0x00100000, 0x00200000, 0x01000000, CIRRUS_ID_CLGD5428, 3, 2, false, true, + 0, 0, NULL, &gd5428_device }, { GFXBOARD_ID_EGS_110_24, @@ -297,18 +325,25 @@ static const struct gfxboard boards[] = 0, 0, NULL, &et4000_domino_device }, { - GFXBOARD_ID_MERLIN_Z2, - _T("Merlin [Zorro II]"), _T("X-Pert Computer Services"), _T("MerlinZ2"), - 2117, 3, 4, 0, - 0x00000000, 0x00200000, 0x00200000, 0x00200000, 0, 2, 0, false, false, - 0, 0, NULL, &et4000w32_merlin_z2_device + GFXBOARD_ID_PIXEL64, + _T("Pixel64 [AteoBus]"), _T("Atéo Concepts"), _T("Pixel64"), + 2026, 255, 254, 0, // 255: type=$c7 flags=$40, 254: type=$c2 flags=$40 128k, 252: type=$c2 flags=$40, 128k + 0x00000000, 0x00200000, 0x00200000, 0x00400000, CIRRUS_ID_CLGD5434, 2, 0, false, false, + 0, 0, NULL, &gd5434_vlb_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, 0, false, false, - 0, 0, NULL, &et4000w32_merlin_z3_device + GFXBOARD_ID_OMNIBUS_ET4000, + _T("oMniBus ET4000AX [Zorro II]"), _T("ArMax"), _T("OmnibusET4000"), + 2181, 0, 0x100, 0, + 0x00000000, 0x00100000, 0x00100000, 0x00100000, 0, 2, 0, false, false, + 0, 0, NULL, &et4000_omnibus_device + }, + { + GFXBOARD_ID_OMNIBUS_ET4000W32, + _T("oMniBus ET4000W32 [Zorro II]"), _T("ArMax"), _T("OmnibusET4000W32"), + 2181, 0, 0x100, 0, + 0x00000000, 0x00100000, 0x00100000, 0x00100000, 0, 2, 0, false, false, + 0, 0, NULL, &et4000w32_omnibus_device }, { GFXBOARD_ID_HARLEQUIN, @@ -317,6 +352,13 @@ static const struct gfxboard boards[] = 0x00000000, 0x00200000, 0x00200000, 0x10000, 0, 0, 2, false, false, ROMTYPE_HARLEQUIN, 0xc2, &harlequin_func }, + { + GFXBOARD_ID_RAINBOWII, + _T("Rainbow II [Zorro II]"), _T("Ingenieurbüro Helfrich"), _T("RainbowII"), + 2145, 32, 0, 0, + 0x00000000, 0x00200000, 0x00200000, 0x00200000, 0, 0, 0, false, false, + ROMTYPE_RAINBOWII, 0xc6, &rainbowii_func + }, #if 0 { _T("Resolver"), _T("DMI"), _T("Resolver"), @@ -347,13 +389,15 @@ static const struct gfxboard boards[] = 0x00000000, 0x00200000, 0x00400000, 0x10000000, 0, 0, -1, false, false, 0, 0, NULL, &s3_trio64_device, 0, GFXBOARD_BUSTYPE_PCI }, +#if 0 { - GFXBOARD_ID_PERMEDIA2_PCI, - _T("BlizzardVision/CyberVision PPC (Permedia2) [PCI]"), _T("3DLabs"), _T("PERMEDIA2_PCI"), + GFXBOARD_ID_GD5446_PCI, + _T("GD5446 [PCI]"), _T("Cirrus Logic"), _T("GD5446_PCI"), 0, 0, 0, 0, - 0x00000000, 0x00800000, 0x00800000, 0x10000000, 0, 0, -1, false, false, - 0, 0, NULL, &permedia2_device, 0, GFXBOARD_BUSTYPE_PCI + 0x00000000, 0x00400000, 0x00400000, 0x10000000, 0, 0, -1, false, false, + 0, 0, NULL, &gd5446_device, 0, GFXBOARD_BUSTYPE_PCI }, +#endif { GFXBOARD_ID_VGA, _T("x86 Bridgeboard VGA [ISA]"), _T("x86"), _T("VGA"), @@ -1147,13 +1191,13 @@ static int gfx_temp_bank_idx; static uae_u32 REGPARAM2 gtb_wget(uaecptr addr) { struct rtggfxboard *gb = &rtggfxboards[gfx_temp_bank_idx]; - addr &= gb->banksize_mask; + addr &= 0xffff; return 0; } static uae_u32 REGPARAM2 gtb_bget(uaecptr addr) { struct rtggfxboard *gb = &rtggfxboards[gfx_temp_bank_idx]; - addr &= gb->banksize_mask; + addr &= 0xffff; if (addr < GFXBOARD_AUTOCONFIG_SIZE) return gb->automemory[addr]; return 0xff; @@ -1162,7 +1206,7 @@ static void REGPARAM2 gtb_bput(uaecptr addr, uae_u32 b) { struct rtggfxboard *gb = &rtggfxboards[gfx_temp_bank_idx]; b &= 0xff; - addr &= gb->banksize_mask; + addr &= 0xffff; if (addr == 0x48) { gfx_temp_bank_idx++; map_banks_z2(gb->gfxmem_bank, expamem_board_pointer >> 16, expamem_board_size >> 16); @@ -1179,7 +1223,7 @@ static void REGPARAM2 gtb_wput(uaecptr addr, uae_u32 b) { struct rtggfxboard *gb = &rtggfxboards[gfx_temp_bank_idx]; b &= 0xffff; - addr &= gb->banksize_mask; + addr &= 0xffff; if (addr == 0x44) { gfx_temp_bank_idx++; map_banks_z3(gb->gfxmem_bank, expamem_board_pointer >> 16, expamem_board_size >> 16); @@ -2862,13 +2906,23 @@ static void REGPARAM2 gfxboard_wput_mem_autoconfig (uaecptr addr, uae_u32 b) } else if (boardnum == GFXBOARD_ID_MERLIN_Z3) { - map_banks_z3(&gb->gfxboard_bank_vram_pcem, start >> 16, gb->gfxboard_bank_vram_pcem.allocated_size >> 16); - gb->pcem_mmio_offset = 0x1000000; - gb->pcem_vram_mask = 0x3fffff; - gb->pcem_vram_offset = 0x800000; - map_banks_z3(&gb->gfxboard_bank_special_pcem, (start + 0x400000) >> 16, 0xc00000 >> 16); + // uses MMIO because ET4000 can have different apertures in VRAM space + copyvrambank(&gb->gfxboard_bank_mmio_wbs_pcem, &gb->gfxboard_bank_vram_pcem, true); + map_banks_z3(&gb->gfxboard_bank_mmio_wbs_pcem, start >> 16, gb->gfxboard_bank_mmio_wbs_pcem.allocated_size >> 16); + gb->pcem_mmio_offset = 0x00000000; + gb->pcem_mmio_mask = 0x3fffff; map_banks_z3(&gb->gfxboard_bank_special_pcem, (start + 0x1000000) >> 16, 0x1000000 >> 16); - gb->pcem_mmio_mask = 0xffff; + gb->configured_regs = gb->gfxmem_bank->start >> 16; + gb->gfxboard_intena = 1; + + } else if (boardnum == GFXBOARD_ID_GRAFFITY_Z3) { + + map_banks_z3(&gb->gfxboard_bank_vram_pcem, (start + 0xc00000) >> 16, gb->gfxboard_bank_vram_pcem.allocated_size >> 16); + map_banks_z3(&gb->gfxboard_bank_special_pcem, (start + 0x800000) >> 16, 65536 >> 16); + map_banks_z3(&gb->gfxboard_bank_special_pcem, (start + 0x400000) >> 16, 65536 >> 16); + gb->pcem_vram_offset = -0x400000; + gb->pcem_vram_mask = 0x1fffff; + gb->pcem_io_mask = 0x3fff; gb->configured_regs = gb->gfxmem_bank->start >> 16; } @@ -3012,6 +3066,23 @@ static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b) gb->pcem_vram_mask = 0x1fffff; gb->pcem_io_mask = 0x3fff; + } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000) { + + ab = &gb->gfxboard_bank_vram_pcem; + gb->gfxboardmem_start = b << 16; + map_banks_z2(ab, b, 0x200000 >> 16); + map_banks_z2(&gb->gfxboard_bank_vram_wordswap_pcem, b + (0x200000 >> 16), 0x200000 >> 16); + + init_board(gb); + + gb->configured_mem = b; + gb->mem_start[0] = b << 16; + gb->mem_end[0] = gb->mem_start[0] + gb->board->banksize; + + gb->pcem_vram_offset = 0x800000; + gb->pcem_vram_mask = 0x1fffff; + gb->pcem_io_mask = 0x3fff; + } else if (boardnum == GFXBOARD_ID_RETINA_Z2) { gb->configured_mem = b; @@ -3061,10 +3132,45 @@ static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b) gb->pcem_vram_offset = 0x800000; gb->pcem_vram_mask = 0x3fffff; + } else if (boardnum == GFXBOARD_ID_MERLIN_Z2) { + + // uses MMIO because ET4000 can have different apertures in VRAM space + ab = &gb->gfxboard_bank_mmio_wbs_pcem; + gb->gfxboardmem_start = b << 16; + map_banks_z2(ab, b, gb->board->banksize >> 16); + + init_board(gb); + + gb->configured_mem = b; + gb->mem_start[0] = b << 16; + gb->mem_end[0] = gb->mem_start[0] + gb->board->banksize; + gb->pcem_mmio_offset = 0x00000000; + gb->pcem_mmio_mask = 0x1fffff; + gb->pcem_io_mask = 0xffff; + gb->gfxboard_intena = 1; + + } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000W32) { + + // uses MMIO because ET4000 can have different apertures in VRAM space + ab = &gb->gfxboard_bank_mmio_wbs_pcem; + gb->gfxboardmem_start = b << 16; + map_banks_z2(ab, b, gb->board->banksize >> 16); + + init_board(gb); + + gb->configured_mem = b; + gb->mem_start[0] = b << 16; + gb->mem_end[0] = gb->mem_start[0] + gb->board->banksize; + gb->pcem_mmio_offset = 0x00000000; + gb->pcem_mmio_mask = 0x0fffff; + gb->pcem_io_mask = 0xffff; + gb->gfxboard_intena = 1; + } else { // Picasso II, Picasso II+ // Piccolo Z2 + // Graffity Z2 ab = &gb->gfxboard_bank_vram_pcem; gb->gfxboardmem_start = b << 16; @@ -3819,7 +3925,8 @@ static void pci_change_config(struct pci_board_state *pci) } } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_S3VIRGE_PCI || gb->rbc->rtgmem_type == GFXBOARD_ID_S3TRIO64_PCI || - gb->rbc->rtgmem_type == GFXBOARD_ID_PERMEDIA2_PCI) { + gb->rbc->rtgmem_type == GFXBOARD_ID_PERMEDIA2_PCI || + gb->rbc->rtgmem_type == GFXBOARD_ID_GD5446_PCI) { if (pci->memory_map_active) { reinit_vram(gb, pci->bar[0] + pci->bridge->memory_start_offset, false); } @@ -4330,6 +4437,52 @@ static const struct pci_board s3virge_pci_board = get_pci_pcem, put_pci_pcem, pci_change_config }; +static const struct pci_config s3trio_pci_config = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct pci_board s3trio_pci_board = +{ + _T("S3TRIO"), + &s3trio_pci_config, NULL, NULL, NULL, NULL, NULL, + { + { voodoo3_mb0_lget, voodoo3_mb0_wget, voodoo3_mb0_bget, voodoo3_mb0_lput, voodoo3_mb0_wput, voodoo3_mb0_bput }, + { NULL }, + { NULL }, + { NULL }, + { NULL }, + { NULL }, + { voodoo3_bios_lget, voodoo3_bios_wget, voodoo3_bios_bget, NULL, NULL, NULL }, + { s3virge_io_lget, s3virge_io_wget, s3virge_io_bget, s3virge_io_lput, s3virge_io_wput, s3virge_io_bput } + }, + true, + get_pci_pcem, put_pci_pcem, pci_change_config +}; + +static const struct pci_config gd5446_pci_config = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct pci_board gd5446_pci_board = +{ + _T("GD5446"), + &gd5446_pci_config, NULL, NULL, NULL, NULL, NULL, + { + { voodoo3_mb0_lget, voodoo3_mb0_wget, voodoo3_mb0_bget, voodoo3_mb0_lput, voodoo3_mb0_wput, voodoo3_mb0_bput }, + { NULL }, + { NULL }, + { NULL }, + { NULL }, + { NULL }, + { voodoo3_bios_lget, voodoo3_bios_wget, voodoo3_bios_bget, NULL, NULL, NULL }, + { s3virge_io_lget, s3virge_io_wget, s3virge_io_bget, s3virge_io_lput, s3virge_io_wput, s3virge_io_bput } + }, + true, + get_pci_pcem, put_pci_pcem, pci_change_config +}; + int gfxboard_get_index_from_id(int id) { if (id == GFXBOARD_UAE_Z2) @@ -4770,11 +4923,15 @@ bool gfxboard_init_memory (struct autoconfig_info *aci) struct pci_bridge *b = pci_bridge_get(); if (b) { 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, 0, aci, gb); + 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, 0, 0, aci, gb); - } else { - gb->pcibs = pci_board_add(b, &s3virge_pci_board, -1, 0, aci, gb); + 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) { + gb->pcibs = pci_board_add(b, &s3trio_pci_board, -1, -1, aci, gb); + } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_S3VIRGE_PCI) { + gb->pcibs = pci_board_add(b, &s3virge_pci_board, -1, -1, aci, gb); } } gb->gfxboard_intena = 1; @@ -4871,7 +5028,9 @@ bool gfxboard_init_registersx(struct autoconfig_info *aci, int regnum) } memset (gb->automemory, 0xff, GFXBOARD_AUTOCONFIG_SIZE); - if (gb->rbc->rtgmem_type == GFXBOARD_ID_PIXEL64 || gb->rbc->rtgmem_type == GFXBOARD_ID_RETINA_Z2) { + if (gb->rbc->rtgmem_type == GFXBOARD_ID_PIXEL64 || + gb->rbc->rtgmem_type == GFXBOARD_ID_RETINA_Z2 || + gb->rbc->rtgmem_type == GFXBOARD_ID_GRAFFITY_Z2) { ew(gb, 0x00, 0xc0 | 0x02); // 128 Z2 size = BOARD_REGISTERS_SIZE * 2; } else { @@ -4879,7 +5038,7 @@ bool gfxboard_init_registersx(struct autoconfig_info *aci, int regnum) size = BOARD_REGISTERS_SIZE; } - ew (gb, 0x04, regnum ? gb->board->model_extra : gb->board->model_registers); + ew (gb, 0x04, regnum ? gb->board->model_extra : gb->board->model_registers & 0xff); ew (gb, 0x10, gb->board->manufacturer >> 8); ew (gb, 0x14, gb->board->manufacturer); @@ -5747,7 +5906,7 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) int boardnum = gb->rbc->rtgmem_type; #if SPCDEBUG -// if ((addr & 0xfffff) != 0x40021) + //if ((addr & 0xfffff) != 0x3da) write_log(_T("PCEM SPECIAL PUT %08x %08x %d PC=%08x\n"), addr, v, size, M68K_GETPC); #endif @@ -5807,6 +5966,16 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) put_io_pcem(addr, v & 0xff, 0); } + } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000) { + + addr &= 0xffff; + 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_CV643D_Z2) { uaecptr addr2 = (addr - gb->gfxboardmem_start) & gb->banksize_mask; @@ -6107,6 +6276,20 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) addr &= 0xffff; + if (addr == 0x401) { + set_monswitch(gb, (v & 0x01) != 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); + } + + } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000W32) { + + addr &= 0xffff; + if (size) { put_io_pcem(addr + 0, (v >> 8) & 0xff, 0); put_io_pcem(addr + 1, (v >> 0) & 0xff, 0); @@ -6139,6 +6322,43 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) if (addr == 0x2008) { gb->gfxboard_intreq_marked = false; } + + } else if (boardnum == GFXBOARD_ID_GRAFFITY_Z2 || boardnum == GFXBOARD_ID_GRAFFITY_Z3) { + + if (boardnum == GFXBOARD_ID_GRAFFITY_Z3) { + if (addr & 0x400000) { + if ((addr & 0x60) == 0x60) { + set_monswitch(gb, true); + } else if ((addr & 0x60) == 0x40) { + set_monswitch(gb, false); + } + return; + } + } else { + if (addr & 0x8000) { + if ((addr & 0x60) == 0x60) { + set_monswitch(gb, true); + } else if ((addr & 0x60) == 0x40) { + set_monswitch(gb, false); + } + return; + } + } + + addr &= 0xffff; + if (addr < 0x4000) { + if (size == 1) { + 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 (size == 2) { + put_io_pcem(addr + 0, (v >> 24) & 0xff, 0); + put_io_pcem(addr + 1, (v >> 16) & 0xff, 0); + put_io_pcem(addr + 2, (v >> 8) & 0xff, 0); + put_io_pcem(addr + 3, (v >> 0) & 0xff, 0); + } + } } } @@ -6149,8 +6369,8 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) uae_u32 v = 0; #if SPCDEBUG -// if ((addr & 0xfffff) != 0x40021) - write_log(_T("PCEM SPECIAL GET %08x %d PC=%08x\n"), addr, size, M68K_GETPC); + //if ((addr & 0xfffff) != 0x3da) + write_log(_T("PCEM SPECIAL GET %08x %d PC=%08x\n"), addr, size, M68K_GETPC); #endif if (boardnum == GFXBOARD_ID_ALTAIS_Z3) { @@ -6208,6 +6428,15 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) v = get_io_pcem(addr, 0); } + } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000) { + + if (size) { + v = get_io_pcem(addr + 0, 0) << 8; + v |= get_io_pcem(addr + 1, 0) << 0; + } else if (size == 0) { + v = get_io_pcem(addr, 0); + } + } else if (boardnum == GFXBOARD_ID_CV643D_Z2) { uaecptr addr2 = (addr - gb->gfxboardmem_start) & gb->banksize_mask; @@ -6453,6 +6682,16 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) v = get_io_pcem(addr, 0); } + } else if (boardnum == GFXBOARD_ID_OMNIBUS_ET4000W32) { + + addr &= 0xffff; + if (size) { + v = get_io_pcem(addr + 0, 0) << 8; + v |= get_io_pcem(addr + 1, 0) << 0; + } else if (size == 0) { + v = get_io_pcem(addr, 0); + } + } else if (boardnum == GFXBOARD_ID_EGS_110_24) { addr &= 0xffff; @@ -6487,7 +6726,25 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) if (addr & 0x4000) { v = gb->gfxboard_intreq_marked ? 0x80 : 00; } + + } else if (boardnum == GFXBOARD_ID_GRAFFITY_Z2 || boardnum == GFXBOARD_ID_GRAFFITY_Z3) { + + addr &= 0xffff; + if (addr < 0x1000) { + if (size == 1) { + v = get_io_pcem(addr + 0, 0) << 8; + v |= get_io_pcem(addr + 1, 0) << 0; + } else if (size == 0) { + v = get_io_pcem(addr, 0); + } else if (size == 2) { + v = get_io_pcem(addr + 0, 0) << 24; + v |= get_io_pcem(addr + 1, 0) << 16; + v |= get_io_pcem(addr + 2, 0) << 8; + v |= get_io_pcem(addr + 3, 0) << 0; + } + } } + return v; } diff --git a/include/gfxboard.h b/include/gfxboard.h index 48909048..dff51b12 100644 --- a/include/gfxboard.h +++ b/include/gfxboard.h @@ -43,6 +43,7 @@ bool gfxboard_isgfxboardscreen(int monid); extern struct gfxboard_func a2410_func; extern struct gfxboard_func harlequin_func; +extern struct gfxboard_func rainbowii_func; extern void vga_io_put(int board, int portnum, uae_u8 v); extern uae_u8 vga_io_get(int board, int portnum); @@ -92,7 +93,13 @@ int pcem_getvramsize(void); #define GFXBOARD_ID_DOMINO 29 #define GFXBOARD_ID_MERLIN_Z2 30 #define GFXBOARD_ID_MERLIN_Z3 31 -#define GFXBOARD_ID_VOODOO5_PCI 32 +#define GFXBOARD_ID_OMNIBUS_ET4000 32 +#define GFXBOARD_ID_OMNIBUS_ET4000W32 33 +#define GFXBOARD_ID_GRAFFITY_Z2 34 +#define GFXBOARD_ID_GRAFFITY_Z3 35 +#define GFXBOARD_ID_RAINBOWII 36 +#define GFXBOARD_ID_GD5446_PCI 37 +#define GFXBOARD_ID_VOODOO5_PCI 38 #define GFXBOARD_BUSTYPE_Z 0 #define GFXBOARD_BUSTYPE_PCI 1 diff --git a/include/rommgr.h b/include/rommgr.h index c7212087..ab66690b 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -211,6 +211,7 @@ extern int decode_cloanto_rom_do(uae_u8 *mem, int size, int real_size); #define ROMTYPE_DSP3210 0x0010008f #define ROMTYPE_ALTAIS 0x00100090 #define ROMTYPE_PROMETHEUSFS 0x00100091 +#define ROMTYPE_RAINBOWII 0x00100092 #define ROMTYPE_NOT 0x00800000 #define ROMTYPE_QUAD 0x01000000 diff --git a/od-win32/picasso96_win.cpp b/od-win32/picasso96_win.cpp index 48c09bdb..4fc5c2ef 100644 --- a/od-win32/picasso96_win.cpp +++ b/od-win32/picasso96_win.cpp @@ -4614,6 +4614,10 @@ static void copyrow(int monid, uae_u8 *src, uae_u8 *dst, int x, int y, int width } } + if (dy < 0 || dy >= state->Height) { + return; + } + uae_u8 *src2 = src + y * srcbytesperrow; uae_u8 *dst2 = dst + dy * dstbytesperrow; diff --git a/pcem/vid_cl5429.cpp b/pcem/vid_cl5429.cpp index 6c330087..b5febbdd 100644 --- a/pcem/vid_cl5429.cpp +++ b/pcem/vid_cl5429.cpp @@ -116,7 +116,9 @@ typedef struct gd5429_t svga_t *mb_vga; uint32_t lfb_base; - + uint32_t mmio_base; + uint32_t gpio_base; + int mmio_vram_overlap; uint8_t sr10_read, sr11_read; @@ -2695,6 +2697,16 @@ static uint8_t cl_pci_read(int func, int addr, void *p) case 0x12: return 0x00; case 0x13: return gd5429->lfb_base >> 24; + case 0x14: return gd5429->mmio_base >> 0; /* mmio */ + case 0x15: return gd5429->mmio_base >> 8; + case 0x16: return gd5429->mmio_base >> 16; + case 0x17: return gd5429->mmio_base >> 24; + + case 0x18: return gd5429->gpio_base >> 0; /* gpio (revb) */ + case 0x19: return gd5429->gpio_base >> 8; + case 0x1a: return gd5429->gpio_base >> 16; + case 0x1b: return gd5429->gpio_base >> 24; + case 0x30: return gd5429->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ case 0x31: return 0x00; case 0x32: return gd5429->pci_regs[0x32]; @@ -2728,6 +2740,64 @@ static void cl_pci_write(int func, int addr, uint8_t val, void *p) gd5429_recalc_mapping(gd5429); break; +#if 0 + case 0x14: + gd5429->mmio_base &= 0xffffff00; + if (gd5429->type < CL_TYPE_GD5446B) { + gd5429->mmio_base |= (val & (0x80|0x40|0x20)) << 0; + } + gd5429_recalc_mapping(gd5429); + break; + case 0x15: + gd5429->mmio_base &= 0xffff0000; + if (gd5429->type == CL_TYPE_GD5446B) { + gd5429->mmio_base |= (val & 0xf0) << 8; + } else { + gd5429->mmio_base |= (val & 0xff) << 8; + } + gd5429_recalc_mapping(gd5429); + break; + case 0x16: + gd5429->mmio_base &= 0xff00ff00; + gd5429->mmio_base |= val << 16; + gd5429_recalc_mapping(gd5429); + break; + case 0x17: + gd5429->mmio_base &= 0x00ffff00; + gd5429->mmio_base |= val << 24; + gd5429_recalc_mapping(gd5429); + break; + + case 0x18: + gd5429->gpio_base &= 0xffffff00; + if (gd5429->type >= CL_TYPE_GD5446B) { + gd5429->gpio_base |= (val & (0x80|0x40|0x20)) << 0; + gd5429_recalc_mapping(gd5429); + } + break; + case 0x19: + gd5429->gpio_base &= 0xffff0000; + if (gd5429->type >= CL_TYPE_GD5446B) { + gd5429->gpio_base |= (val & 0xf0) << 8; + } + gd5429_recalc_mapping(gd5429); + break; + case 0x1a: + gd5429->gpio_base &= 0xff00ff00; + if (gd5429->type >= CL_TYPE_GD5446B) { + gd5429->gpio_base |= val << 16; + gd5429_recalc_mapping(gd5429); + } + break; + case 0x1b: + gd5429->gpio_base &= 0x00ffff00; + if (gd5429->type >= CL_TYPE_GD5446B) { + gd5429->gpio_base |= val << 24; + gd5429_recalc_mapping(gd5429); + } + break; +#endif + case 0x30: case 0x32: case 0x33: gd5429->pci_regs[addr] = val; if (gd5429->pci_regs[0x30] & 0x01) @@ -3271,4 +3341,4 @@ device_t gd5446_device = gd5429_force_redraw, gd5429_add_status_info, gd5434_config -}; \ No newline at end of file +}; diff --git a/pcem/vid_et4000.cpp b/pcem/vid_et4000.cpp index 68e76338..2ada2211 100644 --- a/pcem/vid_et4000.cpp +++ b/pcem/vid_et4000.cpp @@ -805,7 +805,7 @@ et4000_init(const device_t *info) const char *bios_ver = NULL; const char *fn; et4000_t *dev; - int i; +// int i; dev = (et4000_t *) malloc(sizeof(et4000_t)); memset(dev, 0x00, sizeof(et4000_t)); @@ -1189,6 +1189,16 @@ void *et4000_domino_init() return p; } +void *et4000_omnibus_init() +{ + void *p = et4000_init(NULL); + et4000_t *et4000 = (et4000_t *)p; + + void *ramdac = sc1502x_ramdac_init(NULL); + et4000->svga.ramdac = ramdac; + + return p; +} device_t et4000_domino_device = { "Domino", @@ -1201,3 +1211,16 @@ device_t et4000_domino_device = NULL, NULL }; + +device_t et4000_omnibus_device = +{ + "oMniBus", + 0, + et4000_omnibus_init, + et4000_close, + NULL, + et4000_speed_changed, + et4000_force_redraw, + NULL, + NULL +}; diff --git a/pcem/vid_et4000.h b/pcem/vid_et4000.h index 4bc9414f..b7494d3e 100644 --- a/pcem/vid_et4000.h +++ b/pcem/vid_et4000.h @@ -1,3 +1,5 @@ extern device_t et4000_domino_device; extern device_t et4000w32_merlin_z2_device; extern device_t et4000w32_merlin_z3_device; +extern device_t et4000_omnibus_device; +extern device_t et4000w32_omnibus_device; diff --git a/pcem/vid_et4000w32.cpp b/pcem/vid_et4000w32.cpp index f279e34e..f87e489b 100644 --- a/pcem/vid_et4000w32.cpp +++ b/pcem/vid_et4000w32.cpp @@ -18,6 +18,10 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. */ + +// Accelerator fixes (W32/W32i vs W32p), MMU/Accelerator linear addressing, VBlank interrupt, optional BT482 RAMDAC +// by Toni Wilen + #include #include #include @@ -35,6 +39,9 @@ #include "vid_svga_render.h" #include "vid_sdac_ramdac.h" +void *sc1502x_ramdac_init(const device_t *info); +void sc1502x_ramdac_close(void *priv); + #define BIOS_ROM_PATH_DIAMOND "roms/video/et4000w32/et4000w32.bin" #define BIOS_ROM_PATH_CARDEX "roms/video/et4000w32/cardex.vbi" #define BIOS_ROM_PATH_W32 "roms/video/et4000w32/ET4000W32VLB_bios_MX27C512.BIN" @@ -61,9 +68,10 @@ enum { typedef struct et4000w32p_t { mem_mapping_t linear_mapping; - mem_mapping_t mmu_mapping; + mem_mapping_t mmu_mapping, mmu_mapping2; - void *ramdac; + void *ramdac_sdac; + void *ramdac_bt; rom_t bios_rom; @@ -115,11 +123,12 @@ typedef struct et4000w32p_t { uint8_t ctrl; } mmu; - bool blitter_mmio; - uint32_t blitter_mmio_addr; volatile int busy; -} et4000w32p_t; + + int vblank_irq; + +} et4000; static int et4000w32_vbus[4] = { 1, 2, 4, 4 }; @@ -142,7 +151,29 @@ static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t static void et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); uint8_t et4000w32p_in(uint16_t addr, void *priv); -#define et4000w32_log pclog +static int et4000_vga_vsync_enabled(et4000w32p_t *et4000) +{ + if (!(et4000->svga.crtc[0x11] & 0x20) && et4000->vblank_irq > 0) + return 1; + return 0; +} + +static void et4000_update_irqs(et4000w32p_t *et4000) +{ + if (et4000->vblank_irq > 0 && et4000_vga_vsync_enabled(et4000)) + pci_set_irq(NULL, PCI_INTA); + else + pci_clear_irq(NULL, PCI_INTA); +} + +static void et4000_vblank_start(svga_t *svga) +{ + et4000w32p_t *et4000 = (et4000w32p_t*)svga->p; + if (et4000->vblank_irq >= 0) { + et4000->vblank_irq = 1; + et4000_update_irqs(et4000); + } +} #ifdef ENABLE_ET4000W32_LOG int et4000w32_do_log = ENABLE_ET4000W32_LOG; @@ -159,7 +190,7 @@ et4000w32_log(const char *fmt, ...) } } #else -//# define et4000w32_log(fmt, ...) +# define et4000w32_log(fmt, ...) #endif void @@ -179,17 +210,14 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) // icd2061_write(svga->clock_gen, (val >> 2) & 3); break; -#if 0 case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) - sdac_ramdac_out(addr, val, &et4000->ramdac, svga); - else - stg_ramdac_out(addr, val, svga->ramdac, svga); + if (et4000->ramdac_sdac) + sdac_ramdac_out(addr & 3, val, (sdac_ramdac_t*)et4000->ramdac_sdac, svga); return; -#endif + case 0x3cb: /* Banking extension */ if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { svga->write_bank = (svga->write_bank & 0xfffff) | ((val & 1) << 20); @@ -252,14 +280,24 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv) } } if (svga->crtcreg == 0x30) { - if (et4000->pci && (et4000->rev != 5)) + if (et4000->pci && (et4000->rev != 5)) { et4000->linearbase = (et4000->linearbase & 0xc0000000) | ((val & 0xfc) << 22); - else + } else if (!et4000->vlb && !et4000->pci) { + et4000->linearbase = (val & 3) << 22; + } else { et4000->linearbase = val << 22; + } et4000w32p_recalcmapping(et4000); } if (svga->crtcreg == 0x32 || svga->crtcreg == 0x36) et4000w32p_recalcmapping(et4000); + if (svga->crtcreg == 0x11) { + if (!(val & 0x10)) { + et4000->vblank_irq = 0; + } + et4000_update_irqs(et4000); + } + break; case 0x210a: @@ -340,25 +378,30 @@ et4000w32p_in(uint16_t addr, void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_t *svga = &et4000->svga; + uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { + + case 0x3c2: + ret = svga_in(addr, svga); + ret |= et4000->vblank_irq > 0 ? 0x80 : 0x00; + return ret; + case 0x3c5: if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4; break; -#if 0 + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (et4000->type <= ET4000W32P_REVC) - return sdac_ramdac_in(addr, &et4000->ramdac, svga); - else - return stg_ramdac_in(addr, svga->ramdac, svga); -#endif + if (et4000->ramdac_sdac) + return sdac_ramdac_in(addr & 3, (sdac_ramdac_t*)et4000->ramdac_sdac, svga); + return 0; case 0x3cb: return et4000->banking2; case 0x3cd: @@ -459,7 +502,9 @@ et4000w32p_recalctimings(svga_t *svga) svga->dots_per_clock <<= 1; } - bt482_recalctimings(et4000->ramdac, svga); + if (et4000->ramdac_bt) { + bt482_recalctimings(et4000->ramdac_bt, svga); + } //svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); @@ -622,22 +667,34 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000) mem_mapping_disablex(&svga->mapping); mem_mapping_disablex(&et4000->linear_mapping); mem_mapping_disablex(&et4000->mmu_mapping); + mem_mapping_disablex(&et4000->mmu_mapping2); return; } + map = (svga->gdcreg[6] & 0xc) >> 2; + if (svga->crtc[0x36] & 0x20) + map |= 4; + if (svga->crtc[0x36] & 0x08) + map |= 8; + if (svga->crtc[0x36] & 0x10) { /* Linear frame buffer */ - et4000->blitter_mmio = (svga->crtc[0x36] & 0x08) != 0; - et4000->blitter_mmio_addr = et4000->linearbase + svga->vram_max - 0x100; - mem_mapping_set_addrx(&et4000->linear_mapping, et4000->linearbase, svga->vram_max); mem_mapping_disablex(&svga->mapping); mem_mapping_disablex(&et4000->mmu_mapping); + mem_mapping_disablex(&et4000->mmu_mapping2); + mem_mapping_set_addrx(&et4000->linear_mapping, et4000->linearbase, svga->vram_max); + if (map == 0x0c) { + // MMU buffer memory and MMIO mapped over VRAM space65 + if (et4000->type >= ET4000W32P_REVC) { + mem_mapping_set_addrx(&et4000->mmu_mapping2, et4000->linearbase, 0x400000); + } else { + mem_mapping_set_addrx(&et4000->linear_mapping, et4000->linearbase, 0x080000); + mem_mapping_set_addrx(&et4000->mmu_mapping , et4000->linearbase + 0x080000, 0x080000); + mem_mapping_set_addrx(&et4000->mmu_mapping2, et4000->linearbase + 0x200000, 0x200000); + } + } } else { - map = (svga->gdcreg[6] & 0xc) >> 2; - if (svga->crtc[0x36] & 0x20) - map |= 4; - if (svga->crtc[0x36] & 0x08) - map |= 8; mem_mapping_disablex(&et4000->linear_mapping); + mem_mapping_disablex(&et4000->mmu_mapping2); switch (map) { case 0x0: case 0x4: @@ -796,24 +853,18 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) break; case 0xa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00ffffff) | (val << 24); - et4000->acl.internal = et4000->acl.queued; if (et4000->type >= ET4000W32P_REVC) { - et4000w32p_blit_start(et4000); - et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); - if (!(et4000->acl.queued.ctrl_routing & 0x43)) { - et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); - } - if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { - et4000w32p_blit(4, ~0, 0, 0, et4000); + if (et4000->acl.osr & 0x10) { + et4000->acl.internal = et4000->acl.queued; + et4000w32p_blit_start(et4000); + et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); + if (!(et4000->acl.queued.ctrl_routing & 0x43)) { + et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { + et4000w32p_blit(4, ~0, 0, 0, et4000); + } } - } else { - et4000w32_blit_start(et4000); - et4000->acl.cpu_input_num = 0; - if (!(et4000->acl.queued.ctrl_routing & 0x37)) { - et4000->acl.mmu_start = 1; - et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); - } else - et4000->acl.mmu_start = 0; } break; case 0xa4: @@ -920,235 +971,450 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val, uin } } +static void et4000w32p_mmu_write_bank(uint32_t addr, uint8_t val, uint32_t mask, uint32_t mmumask, void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; + svga_t *svga = &et4000->svga; + + if (et4000->mmu.ctrl & (1 << et4000->bank)) { + et4000w32p_accel_write_mmu(et4000, addr & mmumask, val, et4000->bank); + } else { + if (((addr & mask) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { + svga->vram[((addr & mask) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask] = val; + svga->changedvram[(((addr & mask) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask) >> 12] = changeframecount; + } + } +} + +static void et4000w32p_mmu_write_mmio(uint32_t addr, uint8_t val, uint32_t mask, void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; + + if ((addr & 0xff) >= 0x80) { + et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val); + } else { + switch (addr & 0xff) { + case 0x00: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffffff00) | val; + break; + case 0x01: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffff00ff) | (val << 8); + break; + case 0x02: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xff00ffff) | (val << 16); + break; + case 0x03: + et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00ffffff) | (val << 24); + break; + case 0x04: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xffffff00) | val; + break; + case 0x05: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xffff00ff) | (val << 8); + break; + case 0x06: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xff00ffff) | (val << 16); + break; + case 0x07: + et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00ffffff) | (val << 24); + break; + case 0x08: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xffffff00) | val; + break; + case 0x09: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xffff00ff) | (val << 8); + break; + case 0x0a: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xff00ffff) | (val << 16); + break; + case 0x0b: + et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00ffffff) | (val << 24); + break; + case 0x13: + et4000->mmu.ctrl = val; + break; + case 0x30: + et4000->acl.suspend_terminate = val; + break; + case 0x31: + et4000->acl.osr = val; + if (val & 1) { + et4000->acl.internal = et4000->acl.queued; + if (et4000->type >= ET4000W32P_REVC) { + et4000w32p_blit_start(et4000); + et4000w32_log("Destination Address write and start XY Block, xcnt = %i, ycnt = %i\n", et4000->acl.x_count + 1, et4000->acl.y_count + 1); + if (!(et4000->acl.queued.ctrl_routing & 0x43)) { + et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { + et4000w32p_blit(4, ~0, 0, 0, et4000); + } + } else { + et4000w32_blit_start(et4000); + et4000->acl.cpu_input_num = 0; + if (!(et4000->acl.queued.ctrl_routing & 0x37)) { + et4000->acl.mmu_start = 1; + et4000w32_blit(-1, 0, 0, 0xffffffff, et4000); + } else + et4000->acl.mmu_start = 0; + } + } + break; + + default: + break; + } + } +} + static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_t *svga = &et4000->svga; - switch (addr & 0x6000) { - case 0x0000: /* MMU 0 */ - case 0x2000: /* MMU 1 */ - case 0x4000: /* MMU 2 */ - et4000->bank = (addr >> 13) & 3; - if (et4000->mmu.ctrl & (1 << et4000->bank)) { - et4000w32p_accel_write_mmu(et4000, addr & 0x7fff, val, et4000->bank); - } else { - if (((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) < svga->vram_max) { - svga->vram[((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask] = val; - svga->changedvram[(((addr & 0x1fff) + et4000->mmu.base[et4000->bank]) & et4000->vram_mask) >> 12] = changeframecount; + if ((addr & 0xfff00) == 0xfff00) { + et4000w32p_mmu_write_mmio(addr, val, 0xff, priv); + } else { + switch (addr & 0x6000) { + case 0x0000: /* MMU 0 */ + case 0x2000: /* MMU 1 */ + case 0x4000: /* MMU 2 */ + et4000->bank = (addr >> 13) & 3; + et4000w32p_mmu_write_bank(addr, val, 0x1fff, 0x7fff, priv); + break; + case 0x6000: + if ((addr & 0xff00) == 0xff00) { + et4000w32p_mmu_write_mmio(addr, val, 0x1fff, priv); } - } - break; - case 0x6000: - if ((addr & 0xff) >= 0x80) { - et4000w32p_accel_write_fifo(et4000, addr & 0x7fff, val); - } else { - switch (addr & 0xff) { - case 0x00: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffffff00) | val; - break; - case 0x01: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xffff00ff) | (val << 8); - break; - case 0x02: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0xff00ffff) | (val << 16); - break; - case 0x03: - et4000->mmu.base[0] = (et4000->mmu.base[0] & 0x00ffffff) | (val << 24); - break; - case 0x04: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xffffff00) | val; - break; - case 0x05: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xffff00ff) | (val << 8); - break; - case 0x06: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0xff00ffff) | (val << 16); - break; - case 0x07: - et4000->mmu.base[1] = (et4000->mmu.base[1] & 0x00ffffff) | (val << 24); - break; - case 0x08: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xffffff00) | val; - break; - case 0x09: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xffff00ff) | (val << 8); - break; - case 0x0a: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xff00ffff) | (val << 16); - break; - case 0x0b: - et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00ffffff) | (val << 24); - break; - case 0x13: - et4000->mmu.ctrl = val; - break; - case 0x30: - et4000->acl.suspend_terminate = val; - break; - case 0x31: - et4000->acl.osr = val; - break; + break; - default: - break; - } - } - break; + default: + break; + } + } +} + +static void +et4000w32p_mmu_writew(uint32_t addr, uint16_t val, void *priv) +{ + et4000w32p_mmu_write(addr + 0, val >> 0, priv); + et4000w32p_mmu_write(addr + 1, val >> 8, priv); + +} + +static void +et4000w32p_mmu_writel(uint32_t addr, uint32_t val, void *priv) +{ + et4000w32p_mmu_write(addr + 0, val >> 0, priv); + et4000w32p_mmu_write(addr + 1, val >> 8, priv); + et4000w32p_mmu_write(addr + 2, val >> 16, priv); + et4000w32p_mmu_write(addr + 3, val >> 24, priv); +} + +static void +et4000w32p_mmu_write2(uint32_t addr, uint8_t val, void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; + svga_t *svga = &et4000->svga; + + if ((addr & 0xfff00) == 0xfff00) { + et4000w32p_mmu_write_mmio(addr, val, 0xff, priv); + } else if (addr & 0x200000) { + switch (addr & 0x380000) { + case 0x200000: /* MMU 0 */ + case 0x280000: /* MMU 1 */ + case 0x300000: /* MMU 2 */ + et4000->bank = (addr >> 22) & 3; + et4000w32p_mmu_write_bank(addr, val, 0x1fffff, 0xffffff, priv); + break; + case 0x380000: + return et4000w32p_mmu_write_mmio(addr, val, 0x1fffff, priv); + + default: + break; + } + } else { + switch (addr & 0xe0000) { + case 0x080000: /* MMU 0 */ + case 0x0a0000: /* MMU 1 */ + case 0x0c0000: /* MMU 2 */ + et4000->bank = (addr >> 18) & 3; + et4000w32p_mmu_write_bank(addr, val, 0x7ffff, 0xffffff, priv); + break; + case 0x0e0000: + et4000w32p_mmu_write_mmio(addr, val, 0x7ffff, priv); + break; + + default: + break; + } + } +} + +static void +et4000w32p_mmu_writew2(uint32_t addr, uint16_t val, void *priv) +{ + et4000w32p_mmu_write2(addr + 0, val >> 0, priv); + et4000w32p_mmu_write2(addr + 1, val >> 8, priv); + +} + +static void +et4000w32p_mmu_writel2(uint32_t addr, uint32_t val, void *priv) +{ + et4000w32p_mmu_write2(addr + 0, val >> 0, priv); + et4000w32p_mmu_write2(addr + 1, val >> 8, priv); + et4000w32p_mmu_write2(addr + 2, val >> 16, priv); + et4000w32p_mmu_write2(addr + 3, val >> 24, priv); +} + +static uint8_t et4000w32p_mmu_read_bank(uint32_t addr, uint32_t mask, void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; + const svga_t *svga = &et4000->svga; + uint8_t temp; + + if (et4000->mmu.ctrl & (1 << et4000->bank)) { + temp = 0xff; + if (et4000->acl.cpu_dat_pos) { + et4000->acl.cpu_dat_pos--; + temp = et4000->acl.cpu_dat & 0xff; + et4000->acl.cpu_dat >>= 8; + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3)) + et4000w32p_blit(4, ~0, 0, 0, et4000); + + /* ???? */ + return temp; + } + + if ((addr & mask) + et4000->mmu.base[et4000->bank] >= svga->vram_max) + return 0xff; + + return svga->vram[(addr & mask) + et4000->mmu.base[et4000->bank]]; +} + +static uint8_t et4000w32p_mmu_read_mmio(uint32_t addr, void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; + + switch (addr & 0xff) { + case 0x00: + return et4000->mmu.base[0] & 0xff; + case 0x01: + return et4000->mmu.base[0] >> 8; + case 0x02: + return et4000->mmu.base[0] >> 16; + case 0x03: + return et4000->mmu.base[0] >> 24; + case 0x04: + return et4000->mmu.base[1] & 0xff; + case 0x05: + return et4000->mmu.base[1] >> 8; + case 0x06: + return et4000->mmu.base[1] >> 16; + case 0x07: + return et4000->mmu.base[1] >> 24; + case 0x08: + return et4000->mmu.base[2] & 0xff; + case 0x09: + return et4000->mmu.base[2] >> 8; + case 0x0a: + return et4000->mmu.base[2] >> 16; + case 0x0b: + return et4000->mmu.base[2] >> 24; + case 0x13: + return et4000->mmu.ctrl; + + case 0x36: + if (et4000->acl.fifo_queue) { + et4000->acl.status |= ACL_RDST; + et4000->acl.fifo_queue = 0; + } else + et4000->acl.status &= ~ACL_RDST; + return et4000->acl.status; + + case 0x80: + return et4000->acl.internal.pattern_addr & 0xff; + case 0x81: + return et4000->acl.internal.pattern_addr >> 8; + case 0x82: + return et4000->acl.internal.pattern_addr >> 16; + case 0x83: + return et4000->acl.internal.pattern_addr >> 24; + case 0x84: + return et4000->acl.internal.source_addr & 0xff; + case 0x85: + return et4000->acl.internal.source_addr >> 8; + case 0x86: + return et4000->acl.internal.source_addr >> 16; + case 0x87: + return et4000->acl.internal.source_addr >> 24; + case 0x88: + return et4000->acl.internal.pattern_off & 0xff; + case 0x89: + return et4000->acl.internal.pattern_off >> 8; + case 0x8a: + return et4000->acl.internal.source_off & 0xff; + case 0x8b: + return et4000->acl.internal.source_off >> 8; + case 0x8c: + return et4000->acl.internal.dest_off & 0xff; + case 0x8d: + return et4000->acl.internal.dest_off >> 8; + case 0x8e: + if (et4000->type >= ET4000W32P_REVC) + return et4000->acl.internal.pixel_depth; + return et4000->acl.internal.vbus; + case 0x8f: + return et4000->acl.internal.xy_dir; + case 0x90: + return et4000->acl.internal.pattern_wrap; + case 0x92: + return et4000->acl.internal.source_wrap; + case 0x98: + return et4000->acl.internal.count_x & 0xff; + case 0x99: + return et4000->acl.internal.count_x >> 8; + case 0x9a: + return et4000->acl.internal.count_y & 0xff; + case 0x9b: + return et4000->acl.internal.count_y >> 8; + case 0x9c: + return et4000->acl.internal.ctrl_routing; + case 0x9d: + return et4000->acl.internal.ctrl_reload; + case 0x9e: + return et4000->acl.internal.rop_bg; + case 0x9f: + return et4000->acl.internal.rop_fg; + case 0xa0: + return et4000->acl.internal.dest_addr & 0xff; + case 0xa1: + return et4000->acl.internal.dest_addr >> 8; + case 0xa2: + return et4000->acl.internal.dest_addr >> 16; + case 0xa3: + return et4000->acl.internal.dest_addr >> 24; default: break; } + return 0xff; } static uint8_t et4000w32p_mmu_read(uint32_t addr, void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *) priv; - const svga_t *svga = &et4000->svga; - uint8_t temp; - switch (addr & 0x6000) { - case 0x0000: /* MMU 0 */ - case 0x2000: /* MMU 1 */ - case 0x4000: /* MMU 2 */ - et4000->bank = (addr >> 13) & 3; - if (et4000->mmu.ctrl & (1 << et4000->bank)) { - temp = 0xff; - if (et4000->acl.cpu_dat_pos) { - et4000->acl.cpu_dat_pos--; - temp = et4000->acl.cpu_dat & 0xff; - et4000->acl.cpu_dat >>= 8; + if ((addr & 0xfff00) == 0xfff00) { + return et4000w32p_mmu_read_mmio(addr, priv); + } else { + switch (addr & 0x6000) { + case 0x0000: /* MMU 0 */ + case 0x2000: /* MMU 1 */ + case 0x4000: /* MMU 2 */ + et4000->bank = (addr >> 13) & 3; + return et4000w32p_mmu_read_bank(addr, 0x1fff, priv); + case 0x6000: + if ((addr & 0xff00) == 0xff00) { + return et4000w32p_mmu_read_mmio(addr, priv); } - if ((et4000->acl.queued.ctrl_routing & 0x40) && !et4000->acl.cpu_dat_pos && !(et4000->acl.internal.ctrl_routing & 3)) - et4000w32p_blit(4, ~0, 0, 0, et4000); + break; + default: + break; + } + } - /* ???? */ - return temp; - } + return 0xff; +} - if ((addr & 0x1fff) + et4000->mmu.base[et4000->bank] >= svga->vram_max) - return 0xff; +static uint16_t +et4000w32p_mmu_readw(uint32_t addr, void *priv) +{ + uint16_t v = 0; + v |= et4000w32p_mmu_read(addr + 0, priv) << 0; + v |= et4000w32p_mmu_read(addr + 1, priv) << 8; + return v; +} - return svga->vram[(addr & 0x1fff) + et4000->mmu.base[et4000->bank]]; +static uint32_t +et4000w32p_mmu_readl(uint32_t addr, void *priv) +{ + uint32_t v = 0; + v |= et4000w32p_mmu_read(addr + 0, priv) << 0; + v |= et4000w32p_mmu_read(addr + 1, priv) << 8; + v |= et4000w32p_mmu_read(addr + 2, priv) << 16; + v |= et4000w32p_mmu_read(addr + 3, priv) << 24; + return v; +} - case 0x6000: - switch (addr & 0xff) { - case 0x00: - return et4000->mmu.base[0] & 0xff; - case 0x01: - return et4000->mmu.base[0] >> 8; - case 0x02: - return et4000->mmu.base[0] >> 16; - case 0x03: - return et4000->mmu.base[0] >> 24; - case 0x04: - return et4000->mmu.base[1] & 0xff; - case 0x05: - return et4000->mmu.base[1] >> 8; - case 0x06: - return et4000->mmu.base[1] >> 16; - case 0x07: - return et4000->mmu.base[1] >> 24; - case 0x08: - return et4000->mmu.base[2] & 0xff; - case 0x09: - return et4000->mmu.base[2] >> 8; - case 0x0a: - return et4000->mmu.base[2] >> 16; - case 0x0b: - return et4000->mmu.base[2] >> 24; - case 0x13: - return et4000->mmu.ctrl; - - case 0x36: - if (et4000->acl.fifo_queue) { - et4000->acl.status |= ACL_RDST; - et4000->acl.fifo_queue = 0; - } else - et4000->acl.status &= ~ACL_RDST; - return et4000->acl.status; - - case 0x80: - return et4000->acl.internal.pattern_addr & 0xff; - case 0x81: - return et4000->acl.internal.pattern_addr >> 8; - case 0x82: - return et4000->acl.internal.pattern_addr >> 16; - case 0x83: - return et4000->acl.internal.pattern_addr >> 24; - case 0x84: - return et4000->acl.internal.source_addr & 0xff; - case 0x85: - return et4000->acl.internal.source_addr >> 8; - case 0x86: - return et4000->acl.internal.source_addr >> 16; - case 0x87: - return et4000->acl.internal.source_addr >> 24; - case 0x88: - return et4000->acl.internal.pattern_off & 0xff; - case 0x89: - return et4000->acl.internal.pattern_off >> 8; - case 0x8a: - return et4000->acl.internal.source_off & 0xff; - case 0x8b: - return et4000->acl.internal.source_off >> 8; - case 0x8c: - return et4000->acl.internal.dest_off & 0xff; - case 0x8d: - return et4000->acl.internal.dest_off >> 8; - case 0x8e: - if (et4000->type >= ET4000W32P_REVC) - return et4000->acl.internal.pixel_depth; - return et4000->acl.internal.vbus; - case 0x8f: - return et4000->acl.internal.xy_dir; - case 0x90: - return et4000->acl.internal.pattern_wrap; - case 0x92: - return et4000->acl.internal.source_wrap; - case 0x98: - return et4000->acl.internal.count_x & 0xff; - case 0x99: - return et4000->acl.internal.count_x >> 8; - case 0x9a: - return et4000->acl.internal.count_y & 0xff; - case 0x9b: - return et4000->acl.internal.count_y >> 8; - case 0x9c: - return et4000->acl.internal.ctrl_routing; - case 0x9d: - return et4000->acl.internal.ctrl_reload; - case 0x9e: - return et4000->acl.internal.rop_bg; - case 0x9f: - return et4000->acl.internal.rop_fg; - case 0xa0: - return et4000->acl.internal.dest_addr & 0xff; - case 0xa1: - return et4000->acl.internal.dest_addr >> 8; - case 0xa2: - return et4000->acl.internal.dest_addr >> 16; - case 0xa3: - return et4000->acl.internal.dest_addr >> 24; +static uint8_t +et4000w32p_mmu_read2(uint32_t addr, void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; - default: - break; - } + if ((addr & 0xfff00) == 0xfff00) { + return et4000w32p_mmu_read_mmio(addr, priv); + } else if (addr & 0x200000) { + switch (addr & 0x380000) { + case 0x200000: /* MMU 0 */ + case 0x280000: /* MMU 1 */ + case 0x300000: /* MMU 2 */ + return et4000->bank = (addr >> 22) & 3; + et4000w32p_mmu_read_bank(addr, 0x1fffff, priv); + case 0x380000: + return et4000w32p_mmu_read_mmio(addr, priv); - return 0xff; + default: + break; + } + } else { + switch (addr & 0xe0000) { + case 0x080000: /* MMU 0 */ + case 0x0a0000: /* MMU 1 */ + case 0x0c0000: /* MMU 2 */ + et4000->bank = (addr >> 18) & 3; + return et4000w32p_mmu_read_bank(addr, 0x7ffff, priv); + case 0x0e0000: + return et4000w32p_mmu_read_mmio(addr, priv); - default: - break; + default: + break; + } } return 0xff; } +static uint16_t +et4000w32p_mmu_readw2(uint32_t addr, void *priv) +{ + uint16_t v = 0; + v |= et4000w32p_mmu_read2(addr + 0, priv) << 0; + v |= et4000w32p_mmu_read2(addr + 1, priv) << 8; + return v; +} + +static uint32_t +et4000w32p_mmu_readl2(uint32_t addr, void *priv) +{ + uint32_t v = 0; + v |= et4000w32p_mmu_read2(addr + 0, priv) << 0; + v |= et4000w32p_mmu_read2(addr + 1, priv) << 8; + v |= et4000w32p_mmu_read2(addr + 2, priv) << 16; + v |= et4000w32p_mmu_read2(addr + 3, priv) << 24; + return v; +} + void et4000w32_blit_start(et4000w32p_t *et4000) { + // W32 and W32i does not have source/pattern alignment restrictions + int revp = et4000->type > ET4000W32I; + et4000->acl.x_count = et4000->acl.internal.count_x; et4000->acl.y_count = et4000->acl.internal.count_y; @@ -1164,13 +1430,13 @@ et4000w32_blit_start(et4000w32p_t *et4000) if (!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) et4000->acl.status |= ACL_SSO; - if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { + if (revp && et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; et4000->acl.pattern_addr &= ~et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; } et4000->acl.pattern_back = et4000->acl.pattern_addr; - if (!(et4000->acl.internal.pattern_wrap & 0x40)) { + if (revp && !(et4000->acl.internal.pattern_wrap & 0x40)) { if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ et4000->acl.pattern_y = (et4000->acl.pattern_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.pattern_wrap >> 4) & 7] - 1); } else @@ -1179,13 +1445,13 @@ et4000w32_blit_start(et4000w32p_t *et4000) } et4000->acl.pattern_x_back = et4000->acl.pattern_x; - if (et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) { + if (revp && et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]) { et4000->acl.source_x = et4000->acl.source_addr & et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; et4000->acl.source_addr &= ~et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7]; } et4000->acl.source_back = et4000->acl.source_addr; - if (!(et4000->acl.internal.source_wrap & 0x40)) { + if (revp && !(et4000->acl.internal.source_wrap & 0x40)) { if ((et4000w32_wrap_x[et4000->acl.internal.source_wrap & 7] + 1) == 0x00) { /*This is to avoid a division by zero crash*/ et4000->acl.source_y = (et4000->acl.source_addr / (0x7f + 1)) & (et4000w32_wrap_y[(et4000->acl.internal.source_wrap >> 4) & 7] - 1); } else @@ -1194,7 +1460,7 @@ et4000w32_blit_start(et4000w32p_t *et4000) } et4000->acl.source_x_back = et4000->acl.source_x; - if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] == 7) && !(et4000->acl.internal.ctrl_routing & 0x37) && (et4000->acl.internal.rop_fg == 0x5a)) { + if (revp && (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] == 7) && !(et4000->acl.internal.ctrl_routing & 0x37) && (et4000->acl.internal.rop_fg == 0x5a)) { if ((et4000->acl.internal.count_y > 0) && (et4000->acl.pattern_y > 0)) { if (et4000->acl.pattern_addr == et4000->acl.pattern_back) et4000->acl.pattern_y = 0; @@ -1203,7 +1469,7 @@ et4000w32_blit_start(et4000w32p_t *et4000) et4000->acl.pattern_y >>= 4; } } - } else if ((et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] == 15) && !(et4000->acl.internal.ctrl_routing & 0x37) && (et4000->acl.internal.rop_fg == 0x5a)) { + } else if (revp && (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7] == 15) && !(et4000->acl.internal.ctrl_routing & 0x37) && (et4000->acl.internal.rop_fg == 0x5a)) { if ((et4000->acl.internal.count_y > 0) && (et4000->acl.pattern_y > 0)) { if (et4000->acl.pattern_addr == et4000->acl.pattern_back) et4000->acl.pattern_y = 0; @@ -1213,6 +1479,9 @@ et4000w32_blit_start(et4000w32p_t *et4000) } } } + + //pclog("blit P=%08x %d %d ROP=%02x,%02x\n", et4000->acl.pattern_addr, et4000->acl.pattern_x, et4000->acl.pattern_y, et4000->acl.internal.rop_bg, et4000->acl.internal.rop_fg); + //pclog("blit %dx%d S=%08x D=%08x\n", et4000->acl.x_count, et4000->acl.y_count, et4000->acl.source_addr, et4000->acl.dest_addr); } static void @@ -1334,6 +1603,20 @@ et4000w32_decy(et4000w32p_t *et4000) } } +#if 0 +static uint8_t ROPMIX(uint8_t R, uint8_t dest, uint8_t pattern, uint8_t source) +{ + uint8_t out = 0; + for (int c = 0; c < 8; c++) + { + int d = (dest & (1 << c)) ? 1 : 0; + if (source & (1 << c)) d |= 2; + if (pattern & (1 << c)) d |= 4; + if (R & (1 << d)) out |= (1 << c); + } + return out; +} +#else static uint8_t ROPMIX(uint8_t R, uint8_t D, uint8_t P, uint8_t S) { uint8_t out; @@ -2109,6 +2392,7 @@ static uint8_t ROPMIX(uint8_t R, uint8_t D, uint8_t P, uint8_t S) } return out; } +#endif static void et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4000w32p_t *et4000) @@ -2226,13 +2510,16 @@ et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4 } } else { while (count-- && (et4000->acl.y_count >= 0)) { - pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; + uint32_t poffset = (et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask; + uint8_t *pptr = &svga->vram[poffset]; + pattern = *pptr; if (cpu_input == 1) { source = src_dat & 0xff; src_dat >>= 8; - } else /*The source data is from the display memory if the Control Routing register is not set to 1*/ + } else { /*The source data is from the display memory if the Control Routing register is not set to 1*/ source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & et4000->vram_mask]; + } dest = svga->vram[et4000->acl.dest_addr & et4000->vram_mask]; mixmap = mix_dat & 1; @@ -2719,96 +3006,40 @@ et4000w32p_pci_write(int func, int addr, uint8_t val, void *priv) } } -static uint32_t et4000_readl_linear(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - if (et4000->blitter_mmio && addr >= et4000->blitter_mmio_addr) { - uint32_t v = 0; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6000, p) << 0; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6001, p) << 8; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6002, p) << 16; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6003, p) << 24; - return v; - } - return svga_readl_linear(addr, p); -} - -static uint16_t et4000_readw_linear(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - if (et4000->blitter_mmio && addr >= et4000->blitter_mmio_addr) { - uint16_t v = 0; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6000, p) << 0; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6001, p) << 8; - return v; - } - return svga_readw_linear(addr, p); -} - -static uint8_t et4000_read_linear(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - if (et4000->blitter_mmio && addr >= et4000->blitter_mmio_addr) { - uint8_t v = 0; - v |= et4000w32p_mmu_read((addr & 0xff) + 0x6000, p) << 0; - return v; - } - return svga_read_linear(addr, p); -} - -static void et4000_writel_linear(uint32_t addr, uint32_t val, void *p) -{ - svga_t *svga = (svga_t*)p; - et4000w32p_t *et4000 = (et4000w32p_t*)svga->p; - if (et4000->blitter_mmio && addr >= et4000->blitter_mmio_addr) { - et4000w32p_mmu_write((addr & 0xff) + 0x6000, val >> 0, et4000); - et4000w32p_mmu_write((addr & 0xff) + 0x6001, val >> 8, et4000); - et4000w32p_mmu_write((addr & 0xff) + 0x6002, val >> 16, et4000); - et4000w32p_mmu_write((addr & 0xff) + 0x6003, val >> 24, et4000); - return; - } - svga_writel_linear(addr, val, p); -} -static void et4000_writew_linear(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - if (et4000->blitter_mmio && addr >= et4000->blitter_mmio_addr) { - et4000w32p_mmu_write((addr & 0xff) + 0x6000, val >> 0, et4000); - et4000w32p_mmu_write((addr & 0xff) + 0x6001, val >> 8, et4000); - return; - } - svga_writew_linear(addr, val, p); -} -static void et4000_write_linear(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; - if (et4000->blitter_mmio && addr >= et4000->blitter_mmio_addr) { - et4000w32p_mmu_write((addr & 0xff) + 0x6000, val, et4000); - return; - } - svga_write_linear(addr, val, p); -} - - static void bt_out(uint16_t addr, uint8_t val, void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *)priv; uint16_t saddr = 0x3c8 + ((addr >> 2) & 3); - bt482_ramdac_out(saddr, (addr >> 4) & 1, val, et4000->ramdac, &et4000->svga); + bt482_ramdac_out(saddr, (addr >> 4) & 1, val, et4000->ramdac_bt, &et4000->svga); } static uint8_t bt_in(uint16_t addr, void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *)priv; uint16_t saddr = 0x3c8 + ((addr >> 2) & 3); - uint8_t v = bt482_ramdac_in(saddr, (addr >> 4) & 1, et4000->ramdac, &et4000->svga); + uint8_t v = bt482_ramdac_in(saddr, (addr >> 4) & 1, et4000->ramdac_bt, &et4000->svga); return v; } +static void et4000w32_adjust_panning(svga_t *svga) +{ + int ar11 = svga->attrregs[0x13] & 7; + int src = 0, dst = 8; + + switch (svga->bpp) + { + case 24: + src += ar11 & 3; + break; + default: + return; + } + + dst += 24; + svga->scrollcache_dst = dst; + svga->scrollcache_src = src; + +} + void * et4000w32p_init(const device_t *info) { @@ -2837,9 +3068,7 @@ et4000w32p_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000w32_isa); #endif - et4000->type = ET4000W32P_REVC; - et4000->ramdac = bt482_ramdac_init(NULL); - io_sethandlerx(0x000, 0x0020, bt_in, NULL, NULL, bt_out, NULL, NULL, et4000); + et4000->type = ET4000W32I; svga_init(&et4000->svga, et4000, vram_size << 20, et4000w32p_recalctimings, @@ -2847,11 +3076,14 @@ et4000w32p_init(const device_t *info) et4000w32p_hwcursor_draw, NULL); et4000->svga.dac_hwcursor_draw = bt482_hwcursor_draw; - et4000->svga.ramdac = et4000->ramdac; + et4000->svga.vsync_callback = et4000_vblank_start; + et4000->svga.adjust_panning = et4000w32_adjust_panning; et4000->vram_mask = (vram_size << 20) - 1; et4000->svga.decode_mask = (vram_size << 20) - 1; + et4000->svga.crtc[0x11] |= 0x20; + //et4000->type = info->local; switch (et4000->type) { @@ -2966,8 +3198,9 @@ et4000w32p_init(const device_t *info) mem_mapping_disable(&et4000->bios_rom.mapping); #endif - mem_mapping_addx(&et4000->linear_mapping, 0, 0, et4000_read_linear, et4000_readw_linear, et4000_readl_linear, et4000_write_linear, et4000_writew_linear, et4000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &et4000->svga); - mem_mapping_addx(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, et4000); + mem_mapping_addx(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &et4000->svga); + mem_mapping_addx(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, et4000w32p_mmu_readw, et4000w32p_mmu_readl, et4000w32p_mmu_write, et4000w32p_mmu_writew, et4000w32p_mmu_writel, NULL, MEM_MAPPING_EXTERNAL, et4000); + mem_mapping_addx(&et4000->mmu_mapping2, 0, 0, et4000w32p_mmu_read2, et4000w32p_mmu_readw2, et4000w32p_mmu_readl2, et4000w32p_mmu_write2, et4000w32p_mmu_writew2, et4000w32p_mmu_writel2, NULL, MEM_MAPPING_EXTERNAL, et4000); et4000w32p_io_set(et4000); @@ -2991,8 +3224,6 @@ et4000w32p_init(const device_t *info) et4000->svga.packed_chain4 = 1; - svga_set_ramdac_type(&et4000->svga, RAMDAC_8BIT); - return et4000; } @@ -3045,17 +3276,30 @@ et4000w32p_cardex_available(void) } void -et4000w32p_close(void *priv) +et4000w32p_close_bt(void *priv) { et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_close(&et4000->svga); - bt482_ramdac_close(et4000->ramdac); + bt482_ramdac_close(et4000->ramdac_bt); free(et4000); } +void +et4000w32p_close_sc(void *priv) +{ + et4000w32p_t *et4000 = (et4000w32p_t *)priv; + + svga_close(&et4000->svga); + + sc1502x_ramdac_close(et4000->ramdac_sdac); + + free(et4000); +} + + void et4000w32p_speed_changed(void *priv) { @@ -3302,6 +3546,11 @@ void *et4000w32_merlin_z3_init() void *p = et4000w32p_init(NULL); et4000w32p_t *et4000w32p = (et4000w32p_t *)p; + et4000w32p->ramdac_bt = bt482_ramdac_init(NULL); + et4000w32p->svga.ramdac = et4000w32p->ramdac_bt; + io_sethandlerx(0x000, 0x0020, bt_in, NULL, NULL, bt_out, NULL, NULL, et4000w32p); + svga_set_ramdac_type(&et4000w32p->svga, RAMDAC_8BIT); + return p; } void *et4000w32_merlin_z2_init() @@ -3309,15 +3558,43 @@ void *et4000w32_merlin_z2_init() void *p = et4000w32p_init(NULL); et4000w32p_t *et4000w32p = (et4000w32p_t *)p; + et4000w32p->ramdac_bt = bt482_ramdac_init(NULL); + et4000w32p->svga.ramdac = et4000w32p->ramdac_bt; + io_sethandlerx(0x000, 0x0020, bt_in, NULL, NULL, bt_out, NULL, NULL, et4000w32p); + svga_set_ramdac_type(&et4000w32p->svga, RAMDAC_8BIT); + + return p; +} +void *et4000w32_omnibus_z2_init() +{ + void *p = et4000w32p_init(NULL); + et4000w32p_t *et4000w32p = (et4000w32p_t *)p; + + et4000w32p->ramdac_sdac = sc1502x_ramdac_init(NULL); + et4000w32p->svga.ramdac = et4000w32p->ramdac_sdac; + return p; } +device_t et4000w32_omnibus_device = +{ + "oMniBus", + 0, + et4000w32_omnibus_z2_init, + et4000w32p_close_sc, + NULL, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + NULL, + NULL +}; + device_t et4000w32_merlin_z2_device = { "Merlin Z2", 0, et4000w32_merlin_z2_init, - et4000w32p_close, + et4000w32p_close_bt, NULL, et4000w32p_speed_changed, et4000w32p_force_redraw, @@ -3325,13 +3602,12 @@ device_t et4000w32_merlin_z2_device = NULL }; - device_t et4000w32_merlin_z3_device = { "Merlin Z3", 0, et4000w32_merlin_z3_init, - et4000w32p_close, + et4000w32p_close_bt, NULL, et4000w32p_speed_changed, et4000w32p_force_redraw, diff --git a/pcem/vid_svga.cpp b/pcem/vid_svga.cpp index f28b8e1e..a571dbda 100644 --- a/pcem/vid_svga.cpp +++ b/pcem/vid_svga.cpp @@ -812,9 +812,35 @@ int svga_poll(void *p) } } } -// if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2); + + int scrollcache = svga->attrregs[0x13] & 7; + if (svga->render == svga_render_4bpp_highres || + svga->render == svga_render_2bpp_highres) { + svga->scrollcache_dst = (8 - scrollcache) + 24; + } else if (svga->render == svga_render_4bpp_lowres || + svga->render == svga_render_2bpp_lowres) { + svga->scrollcache_dst = ((8 - scrollcache) << 1) + 16; + } else if (svga->render == svga_render_16bpp_highres || + svga->render == svga_render_15bpp_highres || + svga->render == svga_render_8bpp_highres || + svga->render == svga_render_32bpp_highres || + svga->render == svga_render_32bpp_highres_swaprb || + svga->render == svga_render_ABGR8888_highres || + svga->render == svga_render_RGBA8888_highres) { + svga->scrollcache_dst = (8 - ((scrollcache & 6) >> 1)) + 24; + } else { + svga->scrollcache_dst = (8 - (scrollcache & 6)) + 24; + } + svga->scrollcache_src = 0; + svga->scrollcache_dst_reset = svga->scrollcache_dst; + + if (svga->adjust_panning) { + svga->adjust_panning(svga); + } + +// if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2); -// pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven); +// pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven); if (svga->vsync_callback) svga->vsync_callback(svga); @@ -830,7 +856,6 @@ int svga_poll(void *p) svga->sc = svga->crtc[8] & 0x1f; svga->dispon = 1; svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - int scrollcache = svga->attrregs[0x13] & 7; svga->linecountff = 0; svga->hwcursor_on = 0; @@ -842,29 +867,6 @@ int svga_poll(void *p) svga->overlay_on = 0; svga->overlay_latch = svga->overlay; - if (svga->render == svga_render_4bpp_highres || - svga->render == svga_render_2bpp_highres) { - svga->scrollcache_dst = (8 - scrollcache) + 24; - } else if (svga->render == svga_render_4bpp_lowres || - svga->render == svga_render_2bpp_lowres) { - svga->scrollcache_dst = ((8 - scrollcache) << 1) + 16; - } else if (svga->render == svga_render_16bpp_highres || - svga->render == svga_render_15bpp_highres || - svga->render == svga_render_8bpp_highres || - svga->render == svga_render_32bpp_highres || - svga->render == svga_render_32bpp_highres_swaprb || - svga->render == svga_render_ABGR8888_highres || - svga->render == svga_render_RGBA8888_highres) { - svga->scrollcache_dst = (8 - ((scrollcache & 6) >> 1)) + 24; - } else { - svga->scrollcache_dst = (8 - (scrollcache & 6)) + 24; - } - svga->scrollcache_src = 0; - svga->scrollcache_dst_reset = svga->scrollcache_dst; - - if (svga->adjust_panning) { - svga->adjust_panning(svga); - } // pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);