]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Merlin blitter fix, oMniBus, Graffity and Rainbow II RTG cards.
authorToni Wilen <twilen@winuae.net>
Wed, 3 Apr 2024 16:01:44 +0000 (19:01 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 3 Apr 2024 16:01:44 +0000 (19:01 +0300)
expansion.cpp
framebufferboards.cpp
gfxboard.cpp
include/gfxboard.h
include/rommgr.h
od-win32/picasso96_win.cpp
pcem/vid_cl5429.cpp
pcem/vid_et4000.cpp
pcem/vid_et4000.h
pcem/vid_et4000w32.cpp
pcem/vid_svga.cpp

index e311aeeee7665efb86c520a281fcc6bdd9615097..ec9fd19659a1eec1fba22f86669b23b7e8cfa602 100644 (file)
@@ -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 */
        {
index 103d2cbe7fa80a3eb049c8b3432b48eb7cc7ed38..68682ae194b8d313ddf09274806f7d1c8c7ea0c8 100644 (file)
@@ -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
+};
index f60cdf48da0c8eba7a175c78baec0253191d1f76..26214fd0326d77c4df5140ed222031f160c279ff 100644 (file)
@@ -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;
 }
 
index 489090482d8d17a600f7d1a73a884bb953a00b85..dff51b1215b3832a0178093fa97196e7b2501b43 100644 (file)
@@ -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
index c72120875578f5fefefe30989cc477513fa48f05..ab66690b91e0dae00432a357b27781df2e17dffc 100644 (file)
@@ -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
index 48c09bdbf57c35f1e117c000eacc36ef0c1b9cef..4fc5c2eff9de21d570d79e63d891ffa9daf60d85 100644 (file)
@@ -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;
 
index 6c330087c1b835c59b08536ceab41d942976aa1d..b5febbddc0ee84f04a8bc5dc73c4b4c7d9dbd44f 100644 (file)
@@ -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
+};
index 68e763383512338091fba3a7a65b7cc99aca166a..2ada22119ffd75a00fc887821ccc065acfe00f8b 100644 (file)
@@ -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
+};
index 4bc9414fc321e06ddfc008034bbdadad5c7f172a..b7494d3e1510658f723008e174211e157e8f97a8 100644 (file)
@@ -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;
index f279e34e87d588c7100cba5bceec22e31c21c94f..f87e489b284b688318343035a8a299d9ede0299f 100644 (file)
  *          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 <stdio.h>
 #include <stdint.h>
 #include <string.h>
@@ -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,
index f28b8e1ee5b9743602d406cc560bf49092b53c15..a571dbda7b3c994cf0e4ad0a325f3bf30f4d8cb1 100644 (file)
@@ -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);