From: Toni Wilen Date: Tue, 19 Mar 2024 16:57:06 +0000 (+0200) Subject: INMOS G300/G364 emulation. EGS 110/24, Visiona, Rainwbow III RTG boards X-Git-Tag: 5300~81 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=f9bc546d95188c03212b4c0cd29143daabf3777e;p=francis%2Fwinuae.git INMOS G300/G364 emulation. EGS 110/24, Visiona, Rainwbow III RTG boards --- diff --git a/gfxboard.cpp b/gfxboard.cpp index d536c2c8..1fc6aa8a 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -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; } diff --git a/include/gfxboard.h b/include/gfxboard.h index fa104814..996321f5 100644 --- a/include/gfxboard.h +++ b/include/gfxboard.h @@ -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 diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj b/od-win32/winuae_msvc15/winuae_msvc.vcxproj index ec8896eb..ab467929 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj @@ -137,7 +137,7 @@ Unicode v143 false - true + false Application @@ -1378,6 +1378,7 @@ + diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters index 1ad70f79..01a36910 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters @@ -1009,6 +1009,9 @@ pcem + + pcem + diff --git a/pcem/vid_inmos.cpp b/pcem/vid_inmos.cpp new file mode 100644 index 00000000..beb16865 --- /dev/null +++ b/pcem/vid_inmos.cpp @@ -0,0 +1,653 @@ + +/* INMOS G300/G364 emulation by Toni Wilen 2024 */ + +#include +#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 index 00000000..9257f8d9 --- /dev/null +++ b/pcem/vid_inmos.h @@ -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; diff --git a/pcem/vid_svga_render.cpp b/pcem/vid_svga_render.cpp index cbf1eb94..05213ec1 100644 --- a/pcem/vid_svga_render.cpp +++ b/pcem/vid_svga_render.cpp @@ -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; }