]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
INMOS G300/G364 emulation. EGS 110/24, Visiona, Rainwbow III RTG boards
authorToni Wilen <twilen@winuae.net>
Tue, 19 Mar 2024 16:57:06 +0000 (18:57 +0200)
committerToni Wilen <twilen@winuae.net>
Tue, 19 Mar 2024 16:57:06 +0000 (18:57 +0200)
gfxboard.cpp
include/gfxboard.h
od-win32/winuae_msvc15/winuae_msvc.vcxproj
od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters
pcem/vid_inmos.cpp [new file with mode: 0644]
pcem/vid_inmos.h [new file with mode: 0644]
pcem/vid_svga_render.cpp

index d536c2c87d233c870809e8e3f4ea71ee99aeddfe..1fc6aa8ad0c2853b0a6bd3eefe9607fee0a1b495 100644 (file)
@@ -53,6 +53,7 @@ static bool memlogw = true;
 #include "pcem/vid_voodoo_banshee.h"
 #include "pcem/vid_ncr.h"
 #include "pcem/vid_permedia2.h"
+#include "pcem/vid_inmos.h"
 #include "pci.h"
 #include "pci_hw.h"
 #include "pcem/pcemglue.h"
@@ -265,6 +266,27 @@ static const struct gfxboard boards[] =
                0x00000000, 0x00200000, 0x00200000, 0x00400000, CIRRUS_ID_CLGD5434, 2, 0, false, false,
                0, 0, NULL, &gd5434_vlb_device
        },
+       {
+               GFXBOARD_ID_EGS_110_24,
+               _T("EGS 110/24 [GVP local bus]"), _T("GVP"), _T("EGS_110_24"),
+               2193, 0, 0, 0,
+               0x00000000, 0x00400000, 0x00800000, 0x00800000, 0, 4, 2, false, false,
+               0, 0, NULL, &inmos_egs_110_24_device
+       },
+       {
+               GFXBOARD_ID_VISIONA,
+               _T("Visiona [Zorro II]"), _T("X-Pert Computer Services"), _T("Visiona"),
+               2117, 2, 1, 0,
+               0x00000000, 0x00200000, 0x00400000, 0x00400000, 0, 2, 6, false, false,
+               0, 0, NULL, &inmos_visiona_z2_device
+       },
+       {
+               GFXBOARD_ID_RAINBOWIII,
+               _T("Rainbow III [Zorro III]"), _T("Ingenieurbüro Helfrich"), _T("RainbowIII"),
+               2145, 33, 0, 0,
+               0x00000000, 0x00400000, 0x00400000, 0x02000000, 0, 3, 6, false, false,
+               0, 0, NULL, &inmos_rainbow3_z3_device
+       },
        {
                GFXBOARD_ID_HARLEQUIN,
                _T("Harlequin [Zorro II]"), _T("ACS"), _T("Harlequin_PAL"),
@@ -365,6 +387,8 @@ struct rtggfxboard
        int resolutionchange;
        uae_u8 *gfxboard_surface, *fakesurface_surface;
        bool gfxboard_intreq;
+       bool gfxboard_intreq_marked;
+       bool gfxboard_external_interrupt;
        int gfxboard_intena;
        bool vram_enabled, vram_offset_enabled;
        hwaddr vram_offset[2];
@@ -812,13 +836,19 @@ static void gfxboard_rethink(void)
                        if (gb->board->bustype == GFXBOARD_BUSTYPE_DRACO) {
                                void draco_svga_irq(bool state);
                                draco_svga_irq(gb->gfxboard_intreq);
-                       } else if (gb->gfxboard_intreq &&gb->gfxboard_intena) {
-                               if (gb->board->irq == 2 && gb->gfxboard_intena != 6)
-                                       irq = 2;
-                               else
-                                       irq = 6;
-                               if (irq > 0) {
-                                       safe_interrupt_set(IRQ_SOURCE_GFX, gb->monitor_id, irq == 6);
+                       } else if (gb->gfxboard_intena) {
+                               bool intreq = gb->gfxboard_intreq;
+                               if (gb->gfxboard_external_interrupt) {
+                                       intreq |= gb->gfxboard_intreq_marked;
+                               }
+                               if (intreq) {
+                                       if (gb->board->irq == 2 && gb->gfxboard_intena != 6)
+                                               irq = 2;
+                                       else
+                                               irq = 6;
+                                       if (irq > 0) {
+                                               safe_interrupt_set(IRQ_SOURCE_GFX, gb->monitor_id, irq == 6);
+                                       }
                                }
                        }
                }
@@ -1519,6 +1549,7 @@ void gfxboard_intreq(void *p, int act, bool safe)
                if (gb->board->irq && gb->gfxboard_intena) {
                        if (gb->board->irq > 0) {
                                gb->gfxboard_intreq = 1;
+                               gb->gfxboard_intreq_marked = 1;
                        } else {
                                gb->pcibs->irq_callback(gb->pcibs, true);
                        }
@@ -2794,6 +2825,18 @@ static void REGPARAM2 gfxboard_wput_mem_autoconfig (uaecptr addr, uae_u32 b)
                                gb->configured_regs = gb->gfxmem_bank->start >> 16;
                                gb->gfxboard_intena = 1;
 
+                       } else if (boardnum == GFXBOARD_ID_RAINBOWIII) {
+
+                               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);
+                               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_external_interrupt = true;
+
                        }
 
                } else {
@@ -2951,6 +2994,24 @@ static void REGPARAM2 gfxboard_bput_mem_autoconfig (uaecptr addr, uae_u32 b)
                                        gb->pcem_vram_mask = 0x3fffff;
                                        gb->pcem_io_mask = 0x3fff;
 
+                               } else if (boardnum == GFXBOARD_ID_VISIONA) {
+
+
+                                       ab = &gb->gfxboard_bank_vram_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_vram_offset = 0x800000;
+                                       gb->pcem_vram_mask = 0x3fffff;
+                                       gb->pcem_mmio_mask = 0x3fff;
+                                       gb->pcem_mmio_offset = 0x800000;
+                                       gb->gfxboard_external_interrupt = true;
+
                                } else {
 
                                        // Picasso II, Picasso II+
@@ -4559,6 +4620,9 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
                if (gb->rbc->rtgmem_type == GFXBOARD_ID_ALTAIS_Z3) {
                        aci->start = 0x20000000;
                        aci->size = 0x1000000;
+               } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_EGS_110_24) {
+                       aci->start = 0x0d000000;
+                       aci->size = 0x01000000;
                } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_VGA) {
                        static const int parent[] = { ROMTYPE_A1060, ROMTYPE_A2088, ROMTYPE_A2088T, ROMTYPE_A2286, ROMTYPE_A2386, 0 };
                        aci->parent_romtype = parent;
@@ -4689,6 +4753,25 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
                gb->configured_mem = 1;
                gb->configured_regs = 1;
        }
+       if (gb->rbc->rtgmem_type == GFXBOARD_ID_EGS_110_24) {
+               gb->gfxboard_bank_memory.bget = gfxboard_bget_mem;
+               gb->gfxboard_bank_memory.bput = gfxboard_bput_mem;
+               gb->gfxboard_bank_memory.wput = gfxboard_wput_mem;
+               uaecptr start = 0x0d000000;
+               gb->gfxboardmem_start = start;
+               init_board(gb);
+               copyvrambank(&gb->gfxboard_bank_memory, gb->gfxmem_bank, true);
+               copyvrambank(&gb->gfxboard_bank_vram_pcem, gb->gfxmem_bank, true);
+               map_banks(&gb->gfxboard_bank_vram_pcem, gb->gfxboardmem_start >> 16, gb->gfxboard_bank_vram_pcem.allocated_size >> 16, 0);
+               map_banks(&gb->gfxboard_bank_special_pcem, 0xc080000 >> 16, 1, 0);
+               gb->pcem_vram_offset = 0x800000;
+               gb->pcem_vram_mask = gb->rbc->rtgmem_size - 1;
+               gb->pcem_mmio_offset = 0x1000000;
+               gb->pcem_mmio_mask = 0x3fff;
+               gb->configured_regs = gb->gfxmem_bank->start >> 16;
+               gb->configured_mem = 1;
+               gb->configured_regs = 1;
+       }
 
        if (gb->rbc->rtgmem_type == GFXBOARD_ID_VGA) {
                init_board(gb);
@@ -5943,6 +6026,45 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size)
                        }
                }
        end:;
+
+       } else if (boardnum == GFXBOARD_ID_VISIONA) {
+
+               addr &= 0xffff;
+               if (!(addr & (0x2000 | 0x40000))) {
+                       gfxboard_lput_mmio_pcem(addr, v);
+               }
+               if (addr == 0x204c) {
+                       gb->gfxboard_intena = (v & 1) != 0;
+               }
+               if (addr == 0x2054) {
+                       gb->gfxboard_intreq_marked = false;
+               }
+
+       } else if (boardnum == GFXBOARD_ID_EGS_110_24) {
+
+               addr &= 0xffff;
+               if (!(addr & (0x1000 | 0x2000 | 0x40000))) {
+                       gfxboard_lput_mmio_pcem(addr, v);
+               }
+               if (addr == 0x2050) {
+                       gb->gfxboard_intena = (v & 1) != 0;
+               }
+               if (addr == 0x2058) {
+                       gb->gfxboard_intreq_marked = false;
+               }
+
+       } else if (boardnum == GFXBOARD_ID_RAINBOWIII) {
+
+               addr &= 0xffff;
+               if (!(addr & (0x2000 | 0x40000))) {
+                       gfxboard_lput_mmio_pcem(addr, v);
+               }
+               if (addr == 0x2000) {
+                       gb->gfxboard_intena = (v & 0x20) != 0;
+               }
+               if (addr == 0x2008) {
+                       gb->gfxboard_intreq_marked = false;
+               }
        }
 }
 
@@ -6217,6 +6339,56 @@ static uae_u32 special_pcem_get(uaecptr addr, int size)
                        v = flash_read(gb->p4flashrom, addr);
                }
 
+       } else if (boardnum == GFXBOARD_ID_VISIONA) {
+
+               addr &= 0xffff;
+               if (!(addr & (0x2000 | 0x40000))) {
+                       if (size == 2) {
+                               v = gfxboard_lget_mmio_pcem(addr);
+                       } else if (size == 1) {
+                               v = gfxboard_wget_mmio_pcem(addr);
+                       } else {
+                               v = gfxboard_bget_mmio_pcem(addr);
+                       }
+               }
+               if (addr == 0x2044) {
+                       v = gb->gfxboard_intreq_marked ? 4 : 0;
+               }
+
+       } else if (boardnum == GFXBOARD_ID_EGS_110_24) {
+
+               addr &= 0xffff;
+               if (!(addr & (0x2000 | 0x40000))) {
+                       if (size == 2) {
+                               v = gfxboard_lget_mmio_pcem(addr);
+                       } else if (size == 1) {
+                               v = gfxboard_wget_mmio_pcem(addr);
+                       } else {
+                               v = gfxboard_bget_mmio_pcem(addr);
+                       }
+               } else if (addr == 0x2044) {
+                       v = gb->gfxboard_intreq_marked ? 4 : 0;
+               } else if (addr == 0x204c) {
+                       v = 0xf0ffffff;
+               } else if (addr == 0x207c) {
+                       v = 0xf9ffffff;
+               }
+
+       } else if (boardnum == GFXBOARD_ID_RAINBOWIII) {
+
+               addr &= 0xffff;
+               if (!(addr & (0x2000 | 0x40000))) {
+                       if (size == 2) {
+                               v = gfxboard_lget_mmio_pcem(addr);
+                       } else if (size == 1) {
+                               v = gfxboard_wget_mmio_pcem(addr);
+                       } else {
+                               v = gfxboard_bget_mmio_pcem(addr);
+                       }
+               }
+               if (addr & 0x4000) {
+                       v = gb->gfxboard_intreq_marked ? 0x80 : 00;
+               }
        }
        return v;
 }
index fa104814e3425afb23b54eeb66c38f745b490d9f..996321f51ae8b311bad07c8f7cfa21b17b260810 100644 (file)
@@ -86,7 +86,10 @@ int pcem_getvramsize(void);
 #define GFXBOARD_ID_ALTAIS_Z3 23
 #define GFXBOARD_ID_S3TRIO64_PCI 24
 #define GFXBOARD_ID_PERMEDIA2_PCI 25
-#define GFXBOARD_ID_VOODOO5_PCI 26
+#define GFXBOARD_ID_RAINBOWIII 26
+#define GFXBOARD_ID_VISIONA 27
+#define GFXBOARD_ID_EGS_110_24 28
+#define GFXBOARD_ID_VOODOO5_PCI 29
 
 #define GFXBOARD_BUSTYPE_Z 0
 #define GFXBOARD_BUSTYPE_PCI 1
index ec8896eb94416f125ffd3f4feb7e088fb3883221..ab467929aa4724960dfe7e1452fb18d819ab26ef 100644 (file)
     <CharacterSet>Unicode</CharacterSet>
     <PlatformToolset>v143</PlatformToolset>
     <SpectreMitigation>false</SpectreMitigation>
-    <EnableASAN>true</EnableASAN>
+    <EnableASAN>false</EnableASAN>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|ARM64EC'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ClCompile Include="..\..\pcem\sound_speaker.cpp" />
     <ClCompile Include="..\..\pcem\timer.cpp" />
     <ClCompile Include="..\..\pcem\vid_cl5429.cpp" />
+    <ClCompile Include="..\..\pcem\vid_inmos.cpp" />
     <ClCompile Include="..\..\pcem\vid_ncr.cpp" />
     <ClCompile Include="..\..\pcem\vid_permedia2.cpp" />
     <ClCompile Include="..\..\pcem\vid_s3.cpp" />
index 1ad70f79ca0e9a78118de72fc2f03ac4f8f85e13..01a36910e03094902ee603e042c92cf82efb3c1e 100644 (file)
     <ClCompile Include="..\..\pcem\vid_permedia2.cpp">
       <Filter>pcem</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\pcem\vid_inmos.cpp">
+      <Filter>pcem</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\resources\35floppy.ico">
diff --git a/pcem/vid_inmos.cpp b/pcem/vid_inmos.cpp
new file mode 100644 (file)
index 0000000..beb1686
--- /dev/null
@@ -0,0 +1,653 @@
+
+/* INMOS G300/G364 emulation by Toni Wilen 2024 */
+
+#include <stdlib.h>
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "pci.h"
+#include "mem.h"
+#include "rom.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_inmos.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+#include "vid_sdac_ramdac.h"
+
+extern void activate_debugger(void);
+
+enum
+{
+    INMOS_TYPE_G300 = 3,
+    INMOS_TYPE_G360,
+    INMOS_TYPE_G364
+};
+
+typedef struct inmos_t
+{
+    mem_mapping_t linear_mapping;
+    mem_mapping_t mmio_mapping;
+
+    rom_t bios_rom;
+
+    svga_t svga;
+    sdac_ramdac_t ramdac;
+
+    int chip;
+    uint64_t status_time;
+
+    uint32_t linear_base, linear_size;
+    uint32_t mmio_base, mmio_size;
+    uint32_t mmio_mask;
+
+    uint32_t vram_mask;
+
+    uint32_t regs[0x400];
+    uint32_t hwcursor_col[4];
+    int addressalign;
+    int syncdelay;
+
+    float (*getclock)(int clock, void *p);
+    void *getclock_p;
+
+    int vblank_irq;
+
+} inmos_t;
+
+void inmos_updatemapping(inmos_t*);
+void inmos_updatebanking(inmos_t*);
+
+static void inmos_update_irqs(inmos_t *inmos)
+{
+    if (inmos->vblank_irq) {
+        inmos->vblank_irq = 0;
+        pci_set_irq(NULL, PCI_INTA);
+        pci_clear_irq(NULL, PCI_INTA);
+    }
+}
+
+static void inmos_vblank_start(svga_t *svga)
+{
+    inmos_t *inmos = (inmos_t*)svga->p;
+    uint32_t control = inmos->regs[0x160];
+    if (control & 1) {
+        inmos->vblank_irq = 1;
+        inmos_update_irqs(inmos);
+    }
+}
+
+void inmos_hwcursor_draw(svga_t *svga, int displine)
+{
+    inmos_t *inmos = (inmos_t*)svga->p;
+    int addr = svga->hwcursor_latch.addr;
+    int offset = svga->hwcursor_latch.x;
+    int line_offset = 0;
+
+    offset <<= svga->horizontal_linedbl;
+    if (svga->interlace && svga->hwcursor_oddeven)
+        svga->hwcursor_latch.addr += line_offset;
+
+    for (int x = 0; x < 8; x++)
+    {
+        uint16_t dat = inmos->regs[0x200 + addr + x];
+        for (int xx = 0; xx < 8; xx++)
+        {
+            if (offset >= 0) {
+                int cidx = ((dat & 0x0002) ? 2 : 0) | ((dat & 0x0001) ? 1 : 0);
+                if (cidx > 0) {
+                    ((uint32_t*)buffer32->line[displine])[offset + 32] = inmos->hwcursor_col[cidx];
+                }
+            }
+            offset++;
+            dat >>= 2;
+        }
+    }
+    svga->hwcursor_latch.addr += 8;
+    if (svga->interlace && !svga->hwcursor_oddeven)
+        svga->hwcursor_latch.addr += line_offset;
+}
+
+void inmos_recalctimings(svga_t *svga)
+{
+    inmos_t *inmos = (inmos_t*)svga->p;
+
+    if (inmos->chip == INMOS_TYPE_G300) {
+
+        uint32_t control = inmos->regs[0x160];
+        int vo = (control >> 19) & 3;
+        int vramoffset = 1;
+        if (vo == 1) {
+            vramoffset = 2;
+        } else if (vo == 2) {
+            vramoffset = 3;
+        } else {
+            vramoffset = 4;
+        }
+
+        svga->bpp = 1 << ((control >> 17) & 3);
+        int bs = 0;
+        if ((control >> 8) & 1) {
+            svga->bpp = 32;
+            bs = 2;
+            svga->rowoffset <<= 2;
+        }
+
+        int meminit = inmos->regs[0x12b];
+        int tdelay = inmos->regs[0x12c];
+        int len = (meminit + tdelay) * 4;
+
+        svga->htotal = inmos->regs[0x123] * 4;
+        svga->rowoffset = 2048 + (svga->htotal << bs) - (len << bs);
+
+        int row = inmos->regs[0x180] / 0x2000;
+        int col = inmos->regs[0x180] % 0x2000;
+        int width = svga->rowoffset / (4 * 4);
+
+        svga->ma_latch = col * width + row;
+
+        svga->rowoffset >>= 3;
+
+        svga->vtotal = (inmos->regs[0x128] + inmos->regs[0x0127] * 3 + inmos->regs[0x12a]) / 2;
+        svga->dispend = inmos->regs[0x128] / 2;
+        svga->split = 99999;
+        svga->vblankstart = svga->vtotal;
+        svga->vsyncstart = svga->vtotal;
+        svga->interlace = (control >> 1) & 1;
+
+        if (!(control & 1)) {
+            svga->bpp = 0;
+        }
+    
+    } else if (inmos->chip >= INMOS_TYPE_G360) {
+
+        uint32_t control = inmos->regs[0x060];
+        int vo = (control >> 12) & 3;
+        bool interleave = ((control >> 18) & 1) != 0;
+        int meminit = inmos->regs[0x02d];
+        int tdelay = inmos->regs[0x02e];
+        int len = meminit + tdelay;
+
+        int vramoffset = 1;
+        if (vo == 1) {
+            vramoffset = 256;
+        } else if (vo == 2) {
+            vramoffset = 512;
+        } else if (vo == 3) {
+            vramoffset = 1024;
+        }
+
+        int bv = (control >> 20) & 7;
+        int bpp = 0;
+        int bs = 0;
+        switch (bv)
+        {
+            default:
+                bpp = 0;
+                break;
+            case 0:
+                bpp = 1;
+                break;
+            case 1:
+                bpp = 2;
+                break;
+            case 2:
+                bpp = 4;
+                break;
+            case 3:
+                bpp = 8;
+                break;
+            case 4:
+                bpp = 15;
+                bs = 1;
+                break;
+            case 5:
+                bpp = 16;
+                bs = 1;
+                break;
+            case 6:
+                bpp = 32;
+                bs = 2;
+                break;
+        }
+
+        svga->htotal = inmos->regs[0x023] * 4;
+        svga->rowoffset = 2048 + (svga->htotal << bs) - (len << bs);
+
+        uint32_t start = inmos->regs[0x080];
+        pclog("%08x\n", control);
+        int row = start / 0x2000;
+        int col = start % 0x2000;
+        int width = svga->rowoffset / (4 * 4);
+
+        svga->ma_latch = start * 2;
+        svga->rowoffset >>= 3;
+        inmos->syncdelay = (control >> 15) & 7;
+        svga->vtotal = (inmos->regs[0x02a] + inmos->regs[0x029] * 3 + inmos->regs[0x26]) / 2;
+        svga->dispend = inmos->regs[0x02a] / 2;
+        svga->split = 99999;
+        svga->vblankstart = svga->vtotal;
+        svga->vsyncstart = svga->vtotal;
+        svga->interlace = (control >> 1) & 1;
+
+        svga->bpp = bpp;
+
+        svga->hwcursor.ena = (control >> 23) == 0;
+
+        if (!(control & 1)) {
+            svga->bpp = 0;
+        }
+
+    
+    }
+
+    svga->crtc[0x17] |= 0x80;
+    svga->gdcreg[6] |= 1;
+    svga->video_res_override = 1;
+    svga->hdisp = svga->htotal;
+
+    svga->video_res_x = svga->hdisp;
+    svga->video_res_y = svga->dispend;
+    svga->video_bpp = svga->bpp;
+    svga->fullchange = changeframecount;
+
+    svga->render = svga_render_blank;
+    switch (svga->bpp)
+    {
+        // Also supports 1 and 2 bpp modes
+        case 4:
+            svga->render = svga_render_8bpp_highres;
+            break;
+        case 8:
+            svga->render = svga_render_8bpp_highres;
+            break;
+        case 15:
+            svga->render = svga_render_15bpp_highres;
+            break;
+        case 16:
+            svga->render = svga_render_16bpp_highres;
+            break;
+        case 32:
+            svga->render = svga_render_ABGR8888_highres;
+            break;
+    }
+
+    svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
+}
+
+static uint8_t mirrorbits(uint8_t v)
+{
+    uint8_t vout = 0;
+    for (int i = 0; i < 8; i++) {
+        vout |= (v & (1 << i)) ? (1 << (7 - i)) : 0;
+    }
+    return vout;
+}
+
+static void load_palette(int idx, uint32_t val, svga_t *svga)
+{
+    uint8_t r = val & 0xff;
+    uint8_t g = (val >> 8) & 0xff;
+    uint8_t b = (val >> 16) & 0xff;
+    uint8_t vidx = mirrorbits(idx);
+    // Chip reads VRAM "backwards": mirror palette index bits.
+    svga->pallook[vidx] = makecol32(r, g, b);
+}
+
+static void inmos_mmio_write(uint32_t addr, uint8_t val, void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+}
+
+static void inmos_mmio_write_w(uint32_t addr, uint16_t val, void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+}
+static void inmos_mmio_write_l(uint32_t addr, uint32_t val, void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+    svga_t *svga = &inmos->svga;
+
+    int reg = (addr >> inmos->addressalign) & inmos->mmio_mask;
+    inmos->regs[reg] = val;
+
+    //pclog("ADDR %08x REG %08x = %08x\n", addr, reg, val);
+
+    if (inmos->chip == INMOS_TYPE_G300) {
+
+        if (reg < 0x100) {
+            load_palette(reg, val, svga);
+        } else {
+            if (reg == 0x12a) {
+                inmos->regs[0x180] = inmos->regs[0x12a];
+            }
+            svga_recalctimings(&inmos->svga);
+        }
+
+    } else if (inmos->chip >= INMOS_TYPE_G360) {
+
+        if (reg >= 0x100 && reg < 0x200) {
+            load_palette(reg - 0x100, val, svga);
+        } else if (reg >= 0xa0 && reg < 0xa4) {
+            uint8_t r = val & 0xff;
+            uint8_t g = (val >> 8) & 0xff;
+            uint8_t b = (val >> 16) & 0xff;
+            inmos->hwcursor_col[reg - 0xa0] = makecol32(r, g, b);
+        } else if (reg == 0x0c7) {
+            int v = (val >> 12) & 0xfff;
+            inmos->svga.hwcursor.x = v;
+            if (v & 0x800) {
+                inmos->svga.hwcursor.x = (v & 0x7ff) - 0x800;
+            }
+            v = (val >> 0) & 0xfff;
+            inmos->svga.hwcursor.y = v;
+            if (v & 0x800) {
+                inmos->svga.hwcursor.y = (v & 0x7ff) - 0x800;
+            }
+        } else if (reg < 0x100) {
+            svga_recalctimings(&inmos->svga);
+        }
+        if (reg == 0x000) {
+            inmos->addressalign = (val & (1 << 6)) ? 3 : 2;
+        }
+    }
+}
+static uint8_t inmos_mmio_read(uint32_t addr, void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+    uint8_t val = 0;
+    return val;
+}
+static uint16_t inmos_mmio_readw(uint32_t addr, void *p)
+{
+    uint16_t v = 0;
+    return v;
+}
+
+static uint32_t inmos_mmio_readl(uint32_t addr, void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+
+    int reg = (addr >> inmos->addressalign) & inmos->mmio_mask;
+    uint32_t v = inmos->regs[reg];
+    return v;
+}
+
+static uint8_t inmos_read_linear(uint32_t addr, void *p)
+{
+    svga_t *svga = (svga_t*)p;
+    inmos_t *inmos = (inmos_t*)svga->p;
+    uint8_t *fbp = (uint8_t*)(&svga->vram[addr & svga->vram_mask]);
+    uint8_t v = *fbp;
+    return v;
+}
+static uint16_t inmos_readw_linear(uint32_t addr, void *p)
+{
+    svga_t *svga = (svga_t*)p;
+    inmos_t *inmos = (inmos_t*)svga->p;
+    uint16_t *fbp = (uint16_t*)(&svga->vram[addr & svga->vram_mask]);
+    uint16_t v = *fbp;
+    return v;
+}
+static uint32_t inmos_readl_linear(uint32_t addr, void *p)
+{
+    svga_t *svga = (svga_t*)p;
+    inmos_t *inmos = (inmos_t*)svga->p;
+    uint32_t *fbp = (uint32_t*)(&svga->vram[addr & svga->vram_mask]);
+    uint32_t v = *fbp;
+    return v;
+}
+
+static void inmos_write_linear(uint32_t addr, uint8_t val, void *p)
+{
+    svga_t *svga = (svga_t*)p;
+    inmos_t *inmos = (inmos_t*)svga->p;
+    addr &= svga->vram_mask;
+    uint8_t *fbp = (uint8_t*)(&svga->vram[addr]);
+    *fbp = val;
+    svga->changedvram[addr >> 12] = changeframecount;
+}
+static void inmos_writew_linear(uint32_t addr, uint16_t val, void *p)
+{
+    svga_t *svga = (svga_t*)p;
+    inmos_t *inmos = (inmos_t*)svga->p;
+    addr &= svga->vram_mask;
+    uint16_t *fbp = (uint16_t*)(&svga->vram[addr]);
+    *fbp = val;
+    svga->changedvram[addr >> 12] = changeframecount;
+}
+static void inmos_writel_linear(uint32_t addr, uint32_t val, void *p)
+{
+    svga_t *svga = (svga_t*)p;
+    inmos_t *inmos = (inmos_t*)svga->p;
+    addr &= svga->vram_mask;
+    uint32_t *fbp = (uint32_t*)(&svga->vram[addr]);
+    *fbp = val;
+    svga->changedvram[addr >> 12] = changeframecount;
+}
+
+
+void inmos_updatebanking(inmos_t *inmos)
+{
+    svga_t *svga = &inmos->svga;
+
+}
+
+void inmos_updatemapping(inmos_t *inmos)
+{
+    svga_t *svga = &inmos->svga;
+
+    inmos_updatebanking(inmos);
+
+    mem_mapping_disablex(&inmos->mmio_mapping);
+    mem_mapping_disablex(&inmos->linear_mapping);
+
+    if (inmos->chip == INMOS_TYPE_G300) {
+        inmos->linear_base = 0;
+        mem_mapping_set_addrx(&inmos->linear_mapping, inmos->linear_base, inmos->linear_size);
+        inmos->mmio_base = 0x800000;
+        inmos->mmio_size = 0x4000;
+        mem_mapping_set_addrx(&inmos->mmio_mapping, inmos->mmio_base, inmos->mmio_size);
+    } else if (inmos->chip >= INMOS_TYPE_G360) {
+        inmos->linear_base = 0;
+        mem_mapping_set_addrx(&inmos->linear_mapping, inmos->linear_base, inmos->linear_size);
+        inmos->mmio_base = 0x1000000;
+        inmos->mmio_size = 0x4000;
+        mem_mapping_set_addrx(&inmos->mmio_mapping, inmos->mmio_base, inmos->mmio_size);
+    }
+
+    mem_mapping_enablex(&inmos->mmio_mapping);
+    mem_mapping_enablex(&inmos->linear_mapping);
+}
+
+static void inmos_adjust_panning(svga_t *svga)
+{
+    inmos_t *inmos = (inmos_t *)svga->p;
+    int src = 0, dst = 8;
+
+    dst += 24;
+    svga->scrollcache_dst = dst;
+    svga->scrollcache_src = src + inmos->syncdelay * ((svga->bpp + 7) >> 3) * 4;
+}
+
+static inline uint32_t dword_remap(uint32_t in_addr)
+{
+    return in_addr;
+}
+
+static void *inmos_init(int chip)
+{
+    inmos_t *inmos = (inmos_t*)calloc(sizeof(inmos_t), 1);
+    svga_t *svga = &inmos->svga;
+    int vram;
+    uint32_t vram_size;
+
+    memset(inmos, 0, sizeof(inmos_t));
+
+    vram = device_get_config_int("memory");
+    if (vram)
+        vram_size = vram << 20;
+    else
+        vram_size = 512 << 10;
+    inmos->vram_mask = vram_size - 1;
+
+    svga_init(&inmos->svga, inmos, vram_size,
+        inmos_recalctimings,
+        NULL, NULL,
+        inmos_hwcursor_draw,
+        NULL);
+
+    inmos->linear_size = 0x800000;
+    mem_mapping_addx(&inmos->linear_mapping, 0, 0, inmos_read_linear, inmos_readw_linear, inmos_readl_linear, inmos_write_linear, inmos_writew_linear, inmos_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &inmos->svga);
+    mem_mapping_addx(&inmos->mmio_mapping, 0x800000, 0x4000, inmos_mmio_read, inmos_mmio_readw, inmos_mmio_readl, inmos_mmio_write, inmos_mmio_write_w, inmos_mmio_write_l, NULL, MEM_MAPPING_EXTERNAL, inmos);
+
+    svga->decode_mask = (4 << 20) - 1;
+    switch (vram)
+    {
+        case 0: /*512kb*/
+            svga->vram_mask = (1 << 19) - 1;
+            svga->vram_max = 4 << 20;
+            break;
+        case 1: /*1MB*/
+            svga->vram_mask = (1 << 20) - 1;
+            svga->vram_max = 4 << 20;
+            break;
+        case 2: default: /*2MB*/
+            svga->vram_mask = (2 << 20) - 1;
+            svga->vram_max = 4 << 20;
+            break;
+        case 4: /*4MB*/
+            svga->vram_mask = (4 << 20) - 1;
+            svga->vram_max = 4 << 20;
+            break;
+    }
+
+    svga->vsync_callback = inmos_vblank_start;
+    svga->adjust_panning = inmos_adjust_panning;
+
+    inmos->chip = chip;
+    inmos->addressalign = 2;
+    inmos->svga.hwcursor.xsize = 64;
+    inmos->svga.hwcursor.ysize = 64;
+
+    inmos_updatemapping(inmos);
+
+    return inmos;
+}
+
+void *inmos_rainbow3_z3_init()
+{
+    inmos_t *inmos = (inmos_t*)inmos_init(INMOS_TYPE_G360);
+
+    inmos->svga.fb_only = -1;
+    inmos->mmio_mask = 0x3ff;
+    inmos->getclock = sdac_getclock;
+    inmos->getclock_p = &inmos->ramdac;
+    sdac_init(&inmos->ramdac);
+    svga_set_ramdac_type(&inmos->svga, RAMDAC_8BIT);
+
+    return inmos;
+}
+
+void *inmos_visiona_z2_init()
+{
+    inmos_t *inmos = (inmos_t*)inmos_init(INMOS_TYPE_G300);
+
+    inmos->svga.fb_only = -1;
+    inmos->mmio_mask = 0x1ff;
+    inmos->getclock = sdac_getclock;
+    inmos->getclock_p = &inmos->ramdac;
+    sdac_init(&inmos->ramdac);
+    svga_set_ramdac_type(&inmos->svga, RAMDAC_8BIT);
+
+    return inmos;
+}
+
+void *inmos_egs_110_24_init()
+{
+    inmos_t *inmos = (inmos_t *)inmos_init(INMOS_TYPE_G364);
+
+    inmos->svga.fb_only = -1;
+    inmos->mmio_mask = 0x3ff;
+    inmos->getclock = sdac_getclock;
+    inmos->getclock_p = &inmos->ramdac;
+    sdac_init(&inmos->ramdac);
+    svga_set_ramdac_type(&inmos->svga, RAMDAC_8BIT);
+
+    return inmos;
+}
+
+void inmos_close(void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+
+    svga_close(&inmos->svga);
+
+    free(inmos);
+}
+
+void inmos_speed_changed(void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+
+    svga_recalctimings(&inmos->svga);
+}
+
+void inmos_force_redraw(void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+
+    inmos->svga.fullchange = changeframecount;
+}
+
+void inmos_add_status_info(char *s, int max_len, void *p)
+{
+    inmos_t *inmos = (inmos_t*)p;
+    uint64_t new_time = timer_read();
+    uint64_t status_diff = new_time - inmos->status_time;
+    inmos->status_time = new_time;
+
+    if (!status_diff)
+        status_diff = 1;
+
+    svga_add_status_info(s, max_len, &inmos->svga);
+}
+
+device_t inmos_visiona_z2_device =
+{
+    "Visiona",
+    0,
+    inmos_visiona_z2_init,
+    inmos_close,
+    NULL,
+    inmos_speed_changed,
+    inmos_force_redraw,
+    inmos_add_status_info,
+    NULL
+};
+
+device_t inmos_rainbow3_z3_device =
+{
+    "Rainbow III",
+    0,
+    inmos_rainbow3_z3_init,
+    inmos_close,
+    NULL,
+    inmos_speed_changed,
+    inmos_force_redraw,
+    inmos_add_status_info,
+    NULL
+};
+
+device_t inmos_egs_110_24_device =
+{
+    "EGS 110/24",
+    0,
+    inmos_egs_110_24_init,
+    inmos_close,
+    NULL,
+    inmos_speed_changed,
+    inmos_force_redraw,
+    inmos_add_status_info,
+    NULL
+};
diff --git a/pcem/vid_inmos.h b/pcem/vid_inmos.h
new file mode 100644 (file)
index 0000000..9257f8d
--- /dev/null
@@ -0,0 +1,3 @@
+extern device_t inmos_rainbow3_z3_device;
+extern device_t inmos_visiona_z2_device;
+extern device_t inmos_egs_110_24_device;
index cbf1eb94d08a64fda85e5748ed734612ed68df37..05213ec1e6d8fde4bd24f05425d6ff17a314ef3f 100644 (file)
@@ -1113,6 +1113,7 @@ void svga_render_32bpp_highres_swaprb(svga_t *svga)
         {
                 int x;
                 int offset = svga->scrollcache_dst;
+                int shift = svga->scrollcache_src;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -1154,6 +1155,7 @@ void svga_render_ABGR8888_highres(svga_t *svga)
         {
                 int x;
                 int offset = svga->scrollcache_dst;
+                int shift = svga->scrollcache_src;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000)
@@ -1164,7 +1166,7 @@ void svga_render_ABGR8888_highres(svga_t *svga)
                 {
                         for (x = 0; x <= svga->hdisp; x++)
                         {
-                                uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+                                uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + shift + (x << 2)) & svga->vram_display_mask]);
                                 *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
                         }
                         svga->ma += x * 4;
@@ -1174,7 +1176,7 @@ void svga_render_ABGR8888_highres(svga_t *svga)
                         for (x = 0; x <= svga->hdisp; x++)
                         {
                                 uint32_t addr = svga->remap_func(svga, svga->ma);
-                                uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                uint32_t dat = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
                                 *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
                                 svga->ma += 4;
                         }