From 12289b11d33061bebfcfda7c5e17a288ced686af Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 3 Mar 2024 18:58:13 +0200 Subject: [PATCH] Preliminary Permedia 2 (CyberVision/BlizzardVision PPC) emulation. --- expansion.cpp | 6 + gfxboard.cpp | 69 +- include/gfxboard.h | 5 +- include/pci.h | 1 - od-win32/winuae_msvc15/winuae_msvc.vcxproj | 1 + .../winuae_msvc15/winuae_msvc.vcxproj.filters | 3 + pcem/pcemglue.cpp | 32 +- pcem/vid_cl5429.cpp | 2 +- pcem/vid_ncr.cpp | 2 +- pcem/vid_permedia2.cpp | 1162 +++++++++++++++++ pcem/vid_permedia2.h | 2 + pcem/vid_s3.cpp | 2 +- pcem/vid_s3_virge.cpp | 4 +- pcem/vid_svga.cpp | 2 - pcem/vid_svga.h | 2 - pcem/vid_voodoo_banshee.cpp | 2 +- pci.cpp | 53 +- 17 files changed, 1275 insertions(+), 75 deletions(-) create mode 100644 pcem/vid_permedia2.cpp create mode 100644 pcem/vid_permedia2.h diff --git a/expansion.cpp b/expansion.cpp index 44cbf6c2..0cda586e 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -6052,6 +6052,12 @@ const struct expansionromtype expansionroms[] = { NULL, 0, false, EXPANSIONTYPE_RTG }, + { + _T("xvision"), _T("CyberVision/BlizzardVision PPC"), _T("DCE"), + NULL, NULL, NULL, NULL, ROMTYPE_NONE, 0, 0, BOARD_IGNORE, false, + NULL, 0, + false, EXPANSIONTYPE_RTG + }, { _T("x86vga"), _T("x86 VGA"), NULL, NULL, NULL, NULL, NULL, ROMTYPE_x86_VGA | ROMTYPE_NONE, 0, 0, BOARD_IGNORE, true, diff --git a/gfxboard.cpp b/gfxboard.cpp index 1773bc3a..00a94d56 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -52,6 +52,7 @@ static bool memlogw = true; #include "pcem/vid_s3.h" #include "pcem/vid_voodoo_banshee.h" #include "pcem/vid_ncr.h" +#include "pcem/vid_permedia2.h" #include "pci.h" #include "pci_hw.h" #include "pcem/pcemglue.h" @@ -301,6 +302,13 @@ static const struct gfxboard boards[] = 0x00000000, 0x00200000, 0x00400000, 0x10000000, 0, 0, -1, false, false, 0, 0, NULL, &s3_trio64_device, 0, GFXBOARD_BUSTYPE_PCI }, + { + GFXBOARD_ID_PERMEDIA2_PCI, + _T("Permedia 2 [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_VGA, _T("x86 Bridgeboard VGA [ISA]"), _T("x86"), _T("VGA"), @@ -3699,7 +3707,9 @@ static void pci_change_config(struct pci_board_state *pci) reinit_vram(gb, pci->bar[1] + pci->bridge->memory_start_offset, false); } } - } else if (gb->rbc->rtgmem_type == GFXBOARD_ID_S3VIRGE_PCI || gb->rbc->rtgmem_type == GFXBOARD_ID_S3TRIO64_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) { if (pci->memory_map_active) { reinit_vram(gb, pci->bar[0] + pci->bridge->memory_start_offset, false); } @@ -3959,6 +3969,55 @@ static const struct pci_board voodoo3_pci_board = get_pci_pcem, put_pci_pcem, pci_change_config }; +static void REGPARAM2 permedia2_mmio_lput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b) +{ + put_mem_pcem(addr, b, 2); +} +static void REGPARAM2 permedia2_mmio_wput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b) +{ + put_mem_pcem(addr, b, 1); +} +static void REGPARAM2 permedia2_mmio_bput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b) +{ + put_mem_pcem(addr, b, 0); +} +static uae_u32 REGPARAM2 permedia2_mmio_lget(struct pci_board_state *pcibs, uaecptr addr) +{ + return get_mem_pcem(addr, 2); +} +static uae_u32 REGPARAM2 permedia2_mmio_wget(struct pci_board_state *pcibs, uaecptr addr) +{ + return get_mem_pcem(addr, 1); +} +static uae_u32 REGPARAM2 permedia2_mmio_bget(struct pci_board_state *pcibs, uaecptr addr) +{ + return get_mem_pcem(addr, 0); +} + + +static const struct pci_config permedia2_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 permedia2_pci_board = +{ + _T("PERMEDIA2"), + &permedia2_pci_config, NULL, NULL, NULL, NULL, NULL, + { + { permedia2_mmio_lget, permedia2_mmio_wget, permedia2_mmio_bget, permedia2_mmio_lput, permedia2_mmio_wput, permedia2_mmio_bput }, + { voodoo3_mb0_lget, voodoo3_mb0_wget, voodoo3_mb0_bget, voodoo3_mb0_lput, voodoo3_mb0_wput, voodoo3_mb0_bput }, + { voodoo3_mb0_lget, voodoo3_mb0_wget, voodoo3_mb0_bget, voodoo3_mb0_lput, voodoo3_mb0_wput, voodoo3_mb0_bput }, + { NULL }, + { NULL }, + { NULL }, + { voodoo3_bios_lget, voodoo3_bios_wget, voodoo3_bios_bget, NULL, NULL, NULL }, + { NULL } + }, + true, + get_pci_pcem, put_pci_pcem, pci_change_config +}; + + void gfxboard_s3virge_lfb_endianswap(int m) { for (int i = 0; i < MAX_RTG_BOARDS; i++) { @@ -4161,7 +4220,6 @@ static const struct pci_board s3virge_pci_board = get_pci_pcem, put_pci_pcem, pci_change_config }; - int gfxboard_get_index_from_id(int id) { if (id == GFXBOARD_UAE_Z2) @@ -4598,10 +4656,13 @@ bool gfxboard_init_memory (struct autoconfig_info *aci) gb->configured_regs = 1; 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) + 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); - else + } 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->gfxboard_intena = 1; return true; diff --git a/include/gfxboard.h b/include/gfxboard.h index 22863a88..fa104814 100644 --- a/include/gfxboard.h +++ b/include/gfxboard.h @@ -84,8 +84,9 @@ int pcem_getvramsize(void); #define GFXBOARD_ID_RETINA_Z2 21 #define GFXBOARD_ID_RETINA_Z3 22 #define GFXBOARD_ID_ALTAIS_Z3 23 -#define GFXBOARD_ID_VOODOO5_PCI 24 -#define GFXBOARD_ID_S3TRIO64_PCI 25 +#define GFXBOARD_ID_S3TRIO64_PCI 24 +#define GFXBOARD_ID_PERMEDIA2_PCI 25 +#define GFXBOARD_ID_VOODOO5_PCI 26 #define GFXBOARD_BUSTYPE_Z 0 #define GFXBOARD_BUSTYPE_PCI 1 diff --git a/include/pci.h b/include/pci.h index ffbd5482..766fe63e 100644 --- a/include/pci.h +++ b/include/pci.h @@ -5,7 +5,6 @@ extern void pci_dump(int); extern bool dkb_wildfire_pci_init(struct autoconfig_info *aci); extern bool prometheus_init(struct autoconfig_info *aci); -extern bool cbvision_init(struct autoconfig_info *aci); extern bool grex_init(struct autoconfig_info *aci); extern bool mediator_init(struct autoconfig_info *aci); extern bool mediator_init2(struct autoconfig_info *aci); diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj b/od-win32/winuae_msvc15/winuae_msvc.vcxproj index 02048453..ec8896eb 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj @@ -1379,6 +1379,7 @@ + diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters index c1b68ddf..1ad70f79 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters @@ -1006,6 +1006,9 @@ pcem + + pcem + diff --git a/pcem/pcemglue.cpp b/pcem/pcemglue.cpp index 2b07faaf..bbfd7829 100644 --- a/pcem/pcemglue.cpp +++ b/pcem/pcemglue.cpp @@ -525,6 +525,22 @@ void pcemglue_hsync(void) } } +void pcemvideorbswap(bool swapped) +{ + for (int c = 0; c < 65536; c++) { + if (swapped) { + video_15to32[c] = (((c >> 10) & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 0) & 31) << 19); + } else { + video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); + } + if (swapped) { + video_16to32[c] = (((c >> 11) & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 0) & 31) << 19); + } else { + video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); + } + } +} + void initpcemvideo(void *p, bool swapped) { int c, d, e; @@ -572,23 +588,9 @@ void initpcemvideo(void *p, bool swapped) if (!video_15to32) video_15to32 = (uint32_t*)malloc(4 * 65536); - for (c = 0; c < 65536; c++) { - if (swapped) { - video_15to32[c] = (((c >> 10) & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 0) & 31) << 19); - } else { - video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); - } - } - if (!video_16to32) video_16to32 = (uint32_t*)malloc(4 * 65536); - for (c = 0; c < 65536; c++) { - if (swapped) { - video_16to32[c] = (((c >> 11) & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 0) & 31) << 19); - } else { - video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); - } - } + pcemvideorbswap(swapped); if (!buffer32) { buffer32 = (PCBITMAP *)calloc(sizeof(PCBITMAP) + sizeof(uint8_t *) * 4096, 1); diff --git a/pcem/vid_cl5429.cpp b/pcem/vid_cl5429.cpp index 744e2e69..6c330087 100644 --- a/pcem/vid_cl5429.cpp +++ b/pcem/vid_cl5429.cpp @@ -2772,7 +2772,7 @@ static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size) gd5429_hwcursor_draw, gd5429_overlay_draw); - gd5429->svga.vblank_start = gd5429_vblank_start; + gd5429->svga.vsync_callback = gd5429_vblank_start; gd5429->svga.adjust_panning = gd5429_adjust_panning; mem_mapping_set_handlerx(&gd5429->svga.mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel); diff --git a/pcem/vid_ncr.cpp b/pcem/vid_ncr.cpp index 26e15c93..557abc9f 100644 --- a/pcem/vid_ncr.cpp +++ b/pcem/vid_ncr.cpp @@ -1145,7 +1145,7 @@ static void *ncr_init(char *bios_fn, int chip) break; } - svga->vblank_start = ncr_vblank_start; + svga->vsync_callback = ncr_vblank_start; svga->adjust_panning = ncr_adjust_panning; ncr_io_set(ncr); diff --git a/pcem/vid_permedia2.cpp b/pcem/vid_permedia2.cpp new file mode 100644 index 00000000..55f94180 --- /dev/null +++ b/pcem/vid_permedia2.cpp @@ -0,0 +1,1162 @@ + +/* + +Preliminary Permedia 2 (Amiga CyberVision/BlizzardVision PPC) emulation by Toni Wilen 2024 + +Emulated: + +- Standard Graphics processor modes supported (8/15/16/24/32 bits). Other weird modes are not supported. +- VRAM aperture byte swapping and RAMDAC red/blue swapping modes. (Used at least by Picasso96 driver) +- Hardware cursor. + +Not emulated but planned: + +- 2D blitter. NOBLITTER=YES required in Picasso96 tool types +- Overlay + +Not emulated and Someone Else's Problem: + +- SVGA core. Amiga programs seem to always use Graphics processor mode. +- 3D. 3D is someone else's problem. (Maybe some PCem or x86Box developer is interested?) +- Other Permedia 2 special features (front/back buffer swapping, stereo support etc) + +*/ + +#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_permedia2.h" +#include "vid_svga.h" +#include "vid_svga_render.h" +#include "vid_sdac_ramdac.h" + +extern void activate_debugger(void); + +typedef struct permedia2_t +{ + mem_mapping_t linear_mapping[2]; + mem_mapping_t mmio_mapping; + + rom_t bios_rom; + + svga_t svga; + sdac_ramdac_t ramdac; + uint8_t pci_regs[256]; + int card; + + uint8_t ma_ext; + + int chip; + uint8_t int_line; + uint8_t id_ext_pci; + + uint32_t linear_base[2], linear_size; + uint32_t mmio_base, mmio_size; + + uint32_t intena, intreq; + + uint32_t bank[4]; + uint32_t vram_mask; + + float (*getclock)(int clock, void *p); + void *getclock_p; + + int vblank_irq; + + uint8_t ramdac_reg; + uint8_t ramdac_pal, ramdac_palcomp; + uint8_t ramdac_cpal, ramdac_cpalcomp; + uint8_t ramdac_vals[256]; + uint32_t vc_regs[256]; + uint32_t ramdac_hwc_col[4]; + uint16_t ramdac_cramaddr; + uint8_t ramdac_cram[1024]; + + uint8_t linear_byte_control[2]; + +} permedia2_t; + +static __inline uint32_t do_byteswap_32(uint32_t v) +{ + return _byteswap_ulong(v); +} + +void permedia2_updatemapping(permedia2_t*); +void permedia2_updatebanking(permedia2_t*); + +static int permedia2_vsync_enabled(permedia2_t *permedia2) +{ + if (permedia2->intena & 0x10) { + return 1; + } + return 0; +} + +static void permedia2_update_irqs(permedia2_t *permedia2) +{ + if (permedia2->vblank_irq > 0 && permedia2_vsync_enabled(permedia2)) { + permedia2->intreq |= 0x10; + pci_set_irq(NULL, PCI_INTA); + } else { + pci_clear_irq(NULL, PCI_INTA); + } +} + +static void permedia2_vblank_start(svga_t *svga) +{ + permedia2_t *permedia2 = (permedia2_t *)svga->p; + if (permedia2->vblank_irq >= 0) { + permedia2->vblank_irq = 1; + permedia2_update_irqs(permedia2); + } +} + + + +void permedia2_out(uint16_t addr, uint8_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) + { + case 0x3C6: + val &= ~0x10; + sdac_ramdac_out((addr & 3) | 4, val, &permedia2->ramdac, svga); + return; + case 0x3C7: case 0x3C8: case 0x3C9: + sdac_ramdac_out(addr & 3, val, &permedia2->ramdac, svga); + return; + + case 0x3c4: + svga->seqaddr = val & 0x3f; + break; + case 0x3c5: + { + old = svga->seqregs[svga->seqaddr]; + svga->seqregs[svga->seqaddr] = val; + if (old != val && svga->seqaddr >= 0x0a) { + svga->fullchange = changeframecount; + } + switch (svga->seqaddr) + { + default: + break; + } + if (old != val) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + + case 0x3d4: + svga->crtcreg = val & svga->crtcreg_mask; + return; + case 0x3d5: + { + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) + { + case 0x11: + if (!(val & 0x10)) { + permedia2->vblank_irq = 0; + } + permedia2_update_irqs(permedia2); + if ((val & ~0x30) == (old & ~0x30)) + old = val; + break; + } + if (old != val) + { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + } + break; + } + svga_out(addr, val, svga); +} + +uint8_t permedia2_in(uint16_t addr, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->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 |= permedia2->vblank_irq > 0 ? 0x80 : 0x00; + return ret; + case 0x3c5: + switch(svga->seqaddr) + { + default: + break; + } + if (svga->seqaddr >= 0x08 && svga->seqaddr < 0x40) + return svga->seqregs[svga->seqaddr]; + break; + + case 0x3d4: + return svga->crtcreg; + case 0x3d5: + return svga->crtc[svga->crtcreg]; + } + return svga_in(addr, svga); +} + +void permedia2_recalctimings(svga_t *svga) +{ + permedia2_t *permedia2 = (permedia2_t*)svga->p; + bool svga_mode = (svga->seqregs[0x05] & 0x08) != 0; + int bpp = 8; + + if (svga_mode) { + + + + } else { + // graphics processor mode + svga->ma_latch = permedia2->vc_regs[0 / 4] & 0xfffff; + svga->rowoffset = permedia2->vc_regs[8 / 4] & 0xfffff; + svga->htotal = (((permedia2->vc_regs[0x10 / 4] & 2047) - (permedia2->vc_regs[0x20 / 4] & 2047)) + 1) * 4; + svga->vtotal = permedia2->vc_regs[0x38 / 4] & 2047; + svga->vsyncstart = svga->vtotal; + svga->dispend = svga->vtotal - (permedia2->vc_regs[0x40 / 4] & 2047) + 1; + svga->hdisp = svga->htotal; + svga->split = 99999; + svga->vblankstart = svga->vtotal; + + svga->crtc[0x17] |= 0x80; + svga->gdcreg[6] |= 1; + + svga->video_res_override = 1; + + switch(permedia2->ramdac_vals[0x18] & 15) + { + case 0: + default: + bpp = 8; + break; + case 4: + bpp = 15; + break; + case 6: + bpp = 16; + break; + case 8: + bpp = 32; + svga->hdisp /= 2; + break; + case 9: + bpp = 24; + svga->hdisp *= 2; + svga->hdisp /= 3; + break; + } + svga->video_res_x = svga->hdisp; + svga->video_res_y = svga->dispend; + + svga->bpp = bpp; + svga->video_bpp = bpp; + + bool oswaprb = svga->swaprb; + svga->swaprb = (permedia2->ramdac_vals[0x18] & 0x20) == 0; + if (oswaprb != svga->swaprb) { + void pcemvideorbswap(bool swapped); + pcemvideorbswap(svga->swaprb); + } + } + + + switch (bpp) + { + case 4: + svga->render = svga_render_4bpp_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 24: + svga->render = svga_render_24bpp_highres; + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; + } + + svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp; +} + +static void permedia2_hwcursor_draw(svga_t *svga, int displine) +{ + permedia2_t *permedia2 = (permedia2_t*)svga->p; + int addr = svga->hwcursor_latch.addr; + int addradd = 0; + uint8_t dat[2]; + int offset = svga->hwcursor_latch.x; + uint8_t control = permedia2->ramdac_vals[6]; + int cmode = control & 3; + + offset <<= svga->horizontal_linedbl; + + if (svga->hwcursor.xsize == 32) { + addradd = ((control >> 4) & 3) * (32 * 32 / 8); + } + + for (int x = 0; x < svga->hwcursor.xsize; x += 8) + { + dat[0] = permedia2->ramdac_cram[addr + addradd]; + dat[1] = permedia2->ramdac_cram[addr + 0x200 + addradd]; + for (int xx = 0; xx < 8; xx++) + { + if (offset >= 0) { + int cidx = 0; + int comp = 0; + int cval = ((dat[1] & 0x80) ? 2 : 0) | ((dat[0] & 0x80) ? 1 : 0); + if (cmode == 1) { + cidx = cval; + } else if (cmode == 2) { + if (cval == 0 || cval == 1) { + cidx = cval + 1; + } else if (cval == 3) { + comp = 1; + } + } else { + cidx = cval - 1; + } + + if (comp) { + ((uint32_t*)buffer32->line[displine])[offset + 32] ^= 0xffffff; + } else if (cidx > 0) { + ((uint32_t*)buffer32->line[displine])[offset + 32] = permedia2->ramdac_hwc_col[cidx]; + } + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + addr++; + } + svga->hwcursor_latch.addr += svga->hwcursor.xsize / 8; + +} + + +static void permedia2_write(uint32_t addr, uint8_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + addr = (addr & 0xffff) + permedia2->bank[(addr >> 15) & 3]; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint8_t *)&svga->vram[addr] = val; +} +static void permedia2_writew(uint32_t addr, uint16_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + addr = (addr & 0xffff) + permedia2->bank[(addr >> 15) & 3]; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint16_t *)&svga->vram[addr] = val; +} +static void permedia2_writel(uint32_t addr, uint32_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + addr = (addr & 0xffff) + permedia2->bank[(addr >> 15) & 3]; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint32_t *)&svga->vram[addr] = val; +} + +static uint8_t permedia2_read(uint32_t addr, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + addr = (addr & 0xffff) + permedia2->bank[(addr >> 15) & 3]; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; +} +static uint16_t permedia2_readw(uint32_t addr, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + addr = (addr & 0xffff) + permedia2->bank[(addr >> 15) & 3]; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffff; + return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; +} +static uint32_t permedia2_readl(uint32_t addr, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + addr = (addr & 0xffff) + permedia2->bank[(addr >> 15) & 3]; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffff; + + return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; +} + +static void permedia2_ramdac_write(int reg, uint8_t v, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + + if (reg == 0) { // palettewriteaddress + permedia2->ramdac_reg = v; + permedia2->ramdac_pal = v; + permedia2->ramdac_palcomp = 0; + permedia2->ramdac_cramaddr &= 0x0300; + permedia2->ramdac_cramaddr |= v; + } else if (reg == 8) { // palettedata + int idx = permedia2->ramdac_pal; + int comp = permedia2->ramdac_palcomp; + if (!comp) { + svga->vgapal[idx].r = v; + } else if (comp == 1) { + svga->vgapal[idx].g = v; + } else { + svga->vgapal[idx].b = v; + } + svga->pallook[idx] = makecol32(svga->vgapal[idx].r, svga->vgapal[idx].g, svga->vgapal[idx].b); + permedia2->ramdac_palcomp++; + if (permedia2->ramdac_palcomp >= 3) { + permedia2->ramdac_palcomp = 0; + permedia2->ramdac_pal++; + } + } else if (reg == 0x20) { // cursorcoloraddress + permedia2->ramdac_cpal = v; + permedia2->ramdac_cpalcomp = 0; + } else if (reg == 0x28) { // cursorcolordata + int idx = permedia2->ramdac_cpal; + int comp = permedia2->ramdac_cpalcomp; + if (!comp) { + permedia2->ramdac_hwc_col[idx] &= 0x00ffff; + permedia2->ramdac_hwc_col[idx] |= v << 16; + } else if (comp == 1) { + permedia2->ramdac_hwc_col[idx] &= 0xff00ff; + permedia2->ramdac_hwc_col[idx] |= v << 8; + } else { + permedia2->ramdac_hwc_col[idx] &= 0xffff00; + permedia2->ramdac_hwc_col[idx] |= v << 0; + } + permedia2->ramdac_cpalcomp++; + if (permedia2->ramdac_cpalcomp >= 3) { + permedia2->ramdac_cpalcomp = 0; + permedia2->ramdac_cpal++; + permedia2->ramdac_cpal &= 3; + } + } else if (reg == 0x50) { // indexeddata + permedia2->ramdac_vals[permedia2->ramdac_reg] = v; + if (permedia2->ramdac_reg == 0x06) { // cursorcontrol + svga->hwcursor.ena = (v & 3) != 0; + svga->hwcursor.ysize = svga->hwcursor.xsize = (v & 0x40) ? 64 : 32; + permedia2->ramdac_cramaddr &= 0x00ff; + permedia2->ramdac_cramaddr |= ((v >> 2) & 3) << 8; + } else if (permedia2->ramdac_reg == 0x18) { // colormode + svga_recalctimings(&permedia2->svga); + } + } else if (reg == 0x58) { // cursorramdata + permedia2->ramdac_cram[permedia2->ramdac_cramaddr] = v; + permedia2->ramdac_cramaddr++; + permedia2->ramdac_cramaddr &= 1023; + } else if (reg == 0x60) { // cursorxlow + svga->hwcursor.x += 64; + svga->hwcursor.x &= 0xff00; + svga->hwcursor.x |= v; + svga->hwcursor.x -= 64; + } else if (reg == 0x68) { // cursorxhigh + svga->hwcursor.x += 64; + svga->hwcursor.x &= 0x00ff; + svga->hwcursor.x |= v << 8; + svga->hwcursor.x -= 64; + } else if (reg == 0x70) { // cursorylow + svga->hwcursor.y += 64; + svga->hwcursor.y &= 0xff00; + svga->hwcursor.y |= v; + svga->hwcursor.y -= 64; + } else if (reg == 0x78) { // cursoryhigh + svga->hwcursor.y += 64; + svga->hwcursor.y &= 0x00ff; + svga->hwcursor.y |= v << 8; + svga->hwcursor.y -= 64; + } +} + +static uint32_t permedia2_ramdac_read(int reg, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + uint32_t v = 0; + + if (reg == 0) { + // address register + v = permedia2->ramdac_reg; + } else if (reg == 0x18) { // palettereadaddress + int idx = permedia2->ramdac_pal; + int comp = permedia2->ramdac_palcomp; + if (!comp) { + v = svga->vgapal[idx].r; + } else if (comp == 1) { + v = svga->vgapal[idx].g; + } else { + v = svga->vgapal[idx].b; + } + permedia2->ramdac_palcomp++; + if (permedia2->ramdac_palcomp >= 3) { + permedia2->ramdac_palcomp = 0; + permedia2->ramdac_pal++; + } + } else if (reg == 0x50) { + // data register + v = permedia2->ramdac_vals[permedia2->ramdac_reg]; + switch (permedia2->ramdac_reg) + { + case 0x29: // pixelclockstatus + v = 0x10; // PLL locked + break; + case 0x33: // memoryclockstatus + v = 0x10; // PLL locked + break; + } + } + + return v; +} + +static void permedia2_mmio_write(uint32_t addr, uint8_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t*)p; + pclog("PM2 MMIO WRITEB %08x -> %02x\n", addr, val); +} + +static void permedia2_mmio_write_w(uint32_t addr, uint16_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t*)p; + pclog("PM2 MMIO WRITEW %08x -> %04x\n", addr, val); +} + +static void permedia2_mmio_write_l(uint32_t addr, uint32_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t*)p; + int reg = addr & 0xffff; + + if (addr & 0x10000) { + val = do_byteswap_32(val); + } + if (reg >= 0x4000 && reg < 0x5000) { + permedia2_ramdac_write(reg & 0xff, val, p); + } else if (reg >= 0x3000 && reg < 0x4000) { + int vcreg = reg & 0xff; + permedia2->vc_regs[vcreg / 4] = val; + svga_recalctimings(&permedia2->svga); + } else if (reg < 0x2000) { + switch(reg) + { + case 0x08: + permedia2->intena = val; + break; + case 0x10: + if (val & 0x10) { + permedia2->vblank_irq = 0; + } + permedia2->intreq &= ~val; + break; + case 0x50: + //pclog("Aperture 1: %02x\n", val); + permedia2->linear_byte_control[0] = val & 3; + break; + case 0x58: + //pclog("Aperture 2: %02x\n", val); + permedia2->linear_byte_control[1] = val & 3; + break; + } + //pclog("control write %08x = %08x\n", addr, val); + } else { + pclog("Unsupported PM2 MMIO Write %08x = %08x\n", addr, val); + } +} + +static uint32_t permedia2_mmio_readl(uint32_t addr, void *p) +{ + permedia2_t *permedia2 = (permedia2_t*)p; + uint32_t v = 0; + int reg = (addr & 0xffff); + + if (reg >= 0x4000 && reg < 0x5000) { + v = permedia2_ramdac_read(reg & 0xff, p); + } else if (reg >= 0x3000 && reg < 0x4000) { + int vcreg = reg & 0xff; + v = permedia2->vc_regs[vcreg / 4]; + } else if (reg < 0x2000) { + switch (reg) + { + case 0x08: + v = permedia2->intena; + break; + case 0x10: + v = permedia2->intreq; + break; + case 0x18: + v = 0x100; + break; + } + //pclog("control read %08x = %08x\n", addr, v); + } else { + pclog("Unsupported PM2 MMIO Read %08x\n", addr); + } + if (addr & 0x10000) { + v = do_byteswap_32(v); + } + return v; +} + +static uint16_t permedia2_mmio_readw(uint32_t addr, void *p) +{ + uint32_t v = permedia2_mmio_readl(addr, p); + if (addr & 2) { + v >>= 16; + } + return v; +} +static uint8_t permedia2_mmio_read(uint32_t addr, void *p) +{ + uint32_t v = permedia2_mmio_readl(addr, p); + if (addr & 2) { + v >>= 16; + } + if (addr & 1) { + v >>= 8; + } + return v; +} + +static uint8_t permedia2_read_linear1(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t*)p; + permedia2_t *permedia2 = (permedia2_t*)svga->p; + + uint8_t *fbp = (uint8_t*)(&svga->vram[addr & svga->vram_mask]); + uint8_t v = *fbp; + return v; +} +static uint16_t permedia2_readw_linear1(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t*)p; + permedia2_t *permedia2 = (permedia2_t*)svga->p; + + uint16_t *fbp = (uint16_t*)(&svga->vram[addr & svga->vram_mask]); + uint16_t v = *fbp; + + if (permedia2->linear_byte_control[0] == 2) { + v = (v >> 8) | (v << 8); + } + + return v; +} +static uint32_t permedia2_readl_linear1(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t*)p; + permedia2_t *permedia2 = (permedia2_t*)svga->p; + + uint32_t *fbp = (uint32_t*)(&svga->vram[addr & svga->vram_mask]); + uint32_t v = *fbp; + + if (permedia2->linear_byte_control[0] == 2) { + v = do_byteswap_32(v); + v = (v >> 16) | (v << 16); + } else if (permedia2->linear_byte_control[0] == 1) { + v = do_byteswap_32(v); + } + + return v; +} + +static uint8_t permedia2_read_linear2(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + permedia2_t *permedia2 = (permedia2_t *)svga->p; + + uint8_t *fbp = (uint8_t *)(&svga->vram[addr & svga->vram_mask]); + uint8_t v = *fbp; + return v; +} +static uint16_t permedia2_readw_linear2(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + permedia2_t *permedia2 = (permedia2_t *)svga->p; + + uint16_t *fbp = (uint16_t *)(&svga->vram[addr & svga->vram_mask]); + uint16_t v = *fbp; + + if (permedia2->linear_byte_control[1] == 2) { + v = (v >> 8) | (v << 8); + } + + return v; +} +static uint32_t permedia2_readl_linear2(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + permedia2_t *permedia2 = (permedia2_t *)svga->p; + + uint32_t *fbp = (uint32_t *)(&svga->vram[addr & svga->vram_mask]); + uint32_t v = *fbp; + + if (permedia2->linear_byte_control[1] == 2) { + v = do_byteswap_32(v); + v = (v >> 16) | (v << 16); + } else if (permedia2->linear_byte_control[1] == 1) { + v = do_byteswap_32(v); + } + + return v; +} + +static void permedia2_write_linear1(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t*)p; + permedia2_t *permedia2 = (permedia2_t*)svga->p; + + addr &= svga->vram_mask; + uint8_t *fbp = (uint8_t*)(&svga->vram[addr]); + *fbp = val; + svga->changedvram[addr >> 12] = changeframecount; +} +static void permedia2_writew_linear1(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t*)p; + permedia2_t *permedia2 = (permedia2_t*)svga->p; + + if (permedia2->linear_byte_control[0] == 2) { + val = (val >> 8) | (val << 8); + } + + addr &= svga->vram_mask; + uint16_t *fbp = (uint16_t *)(&svga->vram[addr]); + *fbp = val; + svga->changedvram[addr >> 12] = changeframecount; +} +static void permedia2_writel_linear1(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t*)p; + permedia2_t *permedia2 = (permedia2_t*)svga->p; + + if (permedia2->linear_byte_control[0] == 2) { + val = (val >> 16) | (val << 16); + val = do_byteswap_32(val); + } else if (permedia2->linear_byte_control[0] == 1) { + val = do_byteswap_32(val); + } + + addr &= svga->vram_mask; + uint32_t *fbp = (uint32_t*)(&svga->vram[addr]); + *fbp = val; + svga->changedvram[addr >> 12] = changeframecount; +} + +static void permedia2_write_linear2(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + permedia2_t *permedia2 = (permedia2_t *)svga->p; + + addr &= svga->vram_mask; + uint8_t *fbp = (uint8_t *)(&svga->vram[addr]); + *fbp = val; + svga->changedvram[addr >> 12] = changeframecount; +} +static void permedia2_writew_linear2(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + permedia2_t *permedia2 = (permedia2_t *)svga->p; + + if (permedia2->linear_byte_control[1] == 2) { + val = (val >> 8) | (val << 8); + } + + addr &= svga->vram_mask; + uint16_t *fbp = (uint16_t *)(&svga->vram[addr]); + *fbp = val; + svga->changedvram[addr >> 12] = changeframecount; +} +static void permedia2_writel_linear2(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + permedia2_t *permedia2 = (permedia2_t *)svga->p; + + if (permedia2->linear_byte_control[1] == 2) { + val = (val >> 16) | (val << 16); + val = do_byteswap_32(val); + } else if (permedia2->linear_byte_control[1] == 1) { + val = do_byteswap_32(val); + } + + addr &= svga->vram_mask; + uint32_t *fbp = (uint32_t *)(&svga->vram[addr]); + *fbp = val; + svga->changedvram[addr >> 12] = changeframecount; +} + +void permedia2_updatebanking(permedia2_t *permedia2) +{ + svga_t *svga = &permedia2->svga; + + svga->banked_mask = 0xffff; +} + +void permedia2_updatemapping(permedia2_t *permedia2) +{ + svga_t *svga = &permedia2->svga; + + permedia2_updatebanking(permedia2); + + mem_mapping_disablex(&svga->mapping); + mem_mapping_disablex(&permedia2->mmio_mapping); + mem_mapping_disablex(&permedia2->linear_mapping[0]); + mem_mapping_disablex(&permedia2->linear_mapping[1]); + + if (permedia2->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM) { + if (permedia2->linear_base[0]) { + mem_mapping_set_addrx(&permedia2->linear_mapping[0], permedia2->linear_base[0], 0x00800000); + } + if (permedia2->linear_base[1]) { + mem_mapping_set_addrx(&permedia2->linear_mapping[1], permedia2->linear_base[1], 0x00800000); + } + if (permedia2->mmio_base) { + mem_mapping_set_addrx(&permedia2->mmio_mapping, permedia2->mmio_base, 0x20000); + } + } +} + +static void permedia2_adjust_panning(svga_t *svga) +{ + int ar11 = svga->attrregs[0x13] & 7; + int src = 0, dst = 8; + + switch (svga->bpp) + { + case 15: + case 16: + dst = (ar11 & 4) ? 7 : 8; + break; + case 24: + src = ar11 >> 1; + break; + default: + return; + } + + dst += 24; + svga->scrollcache_dst = dst; + svga->scrollcache_src = src; + +} + +static inline uint32_t dword_remap(uint32_t in_addr) +{ + return in_addr; +} + +static void permedia2_io_remove(permedia2_t *permedia2) +{ + io_removehandlerx(0x03c0, 0x0020, permedia2_in, NULL, NULL, permedia2_out, NULL, NULL, permedia2); +} +static void permedia2_io_set(permedia2_t *permedia2) +{ + permedia2_io_remove(permedia2); + + io_sethandlerx(0x03c0, 0x0020, permedia2_in, NULL, NULL, permedia2_out, NULL, NULL, permedia2); +} + +uint8_t permedia2_pci_read(int func, int addr, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + switch (addr) + { + case 0x00: return 0x4c; /* 3DLabs */ + case 0x01: return 0x10; + + case 0x02: return permedia2->id_ext_pci; + case 0x03: return 0x3d; + + case PCI_REG_COMMAND: + return permedia2->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + + case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: return 1; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + case 0x0a: return 0x80; /*Supports VGA interface*/ + case 0x0b: return 0x03; + + // Control space (MMIO) + case 0x10: return 0x00; + case 0x11: return 0x00; + case 0x12: return (permedia2->mmio_base >> 16) & 0xfe; + case 0x13: return permedia2->mmio_base >> 24; + // Aperture 1 + case 0x14: return 0x00; + case 0x15: return 0x00; + case 0x16: return (permedia2->linear_base[0] >> 16) & 0x80; + case 0x17: return permedia2->linear_base[0] >> 24; + // Aperture 2 + case 0x18: return 0x00; + case 0x19: return 0x00; + case 0x1a: return (permedia2->linear_base[1] >> 16) & 0x80; + case 0x1b: return permedia2->linear_base[1] >> 24; + + case 0x2c: return 0x4c; + case 0x2d: return 0x10; + case 0x2e: return permedia2->id_ext_pci;; + case 0x2f: return 0x3d; + + case 0x30: return permedia2->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return permedia2->pci_regs[0x32]; + case 0x33: return permedia2->pci_regs[0x33]; + + case 0x3c: return permedia2->int_line; + case 0x3d: return PCI_INTA; + } + return 0; +} + +void permedia2_pci_write(int func, int addr, uint8_t val, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + svga_t *svga = &permedia2->svga; + switch (addr) + { + case PCI_REG_COMMAND: + permedia2->pci_regs[PCI_REG_COMMAND] = val & 0x23; + if (val & PCI_COMMAND_IO) + permedia2_io_set(permedia2); + else + permedia2_io_remove(permedia2); + permedia2_updatemapping(permedia2); + break; + + case 0x12: + permedia2->mmio_base &= 0xff00ffff; + permedia2->mmio_base |= (val & 0xfe) << 16; + permedia2_updatemapping(permedia2); + break; + case 0x13: + permedia2->mmio_base &= 0x00ffffff; + permedia2->mmio_base |= val << 24; + permedia2_updatemapping(permedia2); + break; + + case 0x16: + permedia2->linear_base[0] &= 0xff00ffff; + permedia2->linear_base[0] |= (val & 0x80) << 16; + permedia2_updatemapping(permedia2); + break; + case 0x17: + permedia2->linear_base[0] &= 0x00ffffff; + permedia2->linear_base[0] |= val << 24; + permedia2_updatemapping(permedia2); + break; + + case 0x1a: + permedia2->linear_base[1] &= 0xff00ffff; + permedia2->linear_base[1] |= (val & 0x80) << 16; + permedia2_updatemapping(permedia2); + break; + case 0x1b: + permedia2->linear_base[1] &= 0x00ffffff; + permedia2->linear_base[1] |= val << 24; + permedia2_updatemapping(permedia2); + break; + + case 0x30: case 0x32: case 0x33: + permedia2->pci_regs[addr] = val; + if (permedia2->pci_regs[0x30] & 0x01) + { + uint32_t addr = (permedia2->pci_regs[0x32] << 16) | (permedia2->pci_regs[0x33] << 24); + mem_mapping_set_addrx(&permedia2->bios_rom.mapping, addr, 0x8000); + } else { + mem_mapping_disablex(&permedia2->bios_rom.mapping); + } + return; + + case 0x3c: + permedia2->int_line = val; + return; + } +} + + +static void *permedia2_init(char *bios_fn, int chip) +{ + permedia2_t *permedia2 = (permedia2_t*)calloc(sizeof(permedia2_t), 1); + svga_t *svga = &permedia2->svga; + int vram; + uint32_t vram_size; + + memset(permedia2, 0, sizeof(permedia2_t)); + + vram = device_get_config_int("memory"); + if (vram) + vram_size = vram << 20; + else + vram_size = 512 << 10; + permedia2->vram_mask = vram_size - 1; + + rom_init(&permedia2->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + svga_init(&permedia2->svga, permedia2, vram_size, + permedia2_recalctimings, + permedia2_in, permedia2_out, + permedia2_hwcursor_draw, + NULL); + + mem_mapping_addx(&permedia2->linear_mapping[0], 0, 0, permedia2_read_linear1, permedia2_readw_linear1, permedia2_readl_linear1, permedia2_write_linear1, permedia2_writew_linear1, permedia2_writel_linear1, NULL, MEM_MAPPING_EXTERNAL, &permedia2->svga); + mem_mapping_addx(&permedia2->linear_mapping[1], 0, 0, permedia2_read_linear2, permedia2_readw_linear2, permedia2_readl_linear2, permedia2_write_linear2, permedia2_writew_linear2, permedia2_writel_linear2, NULL, MEM_MAPPING_EXTERNAL, &permedia2->svga); + mem_mapping_set_handlerx(&permedia2->svga.mapping, permedia2_read, permedia2_readw, permedia2_readl, permedia2_write, permedia2_writew, permedia2_writel); + mem_mapping_addx(&permedia2->mmio_mapping, 0, 0, permedia2_mmio_read, permedia2_mmio_readw, permedia2_mmio_readl, permedia2_mmio_write, permedia2_mmio_write_w, permedia2_mmio_write_l, NULL, MEM_MAPPING_EXTERNAL, permedia2); + mem_mapping_set_px(&permedia2->svga.mapping, permedia2); + mem_mapping_disablex(&permedia2->mmio_mapping); + + svga->vram_max = 8 << 20; + svga->decode_mask = svga->vram_max - 1; + svga->vram_mask = svga->vram_max - 1; + + permedia2->pci_regs[4] = 3; + permedia2->pci_regs[5] = 0; + permedia2->pci_regs[6] = 0; + permedia2->pci_regs[7] = 2; + permedia2->pci_regs[0x32] = 0x0c; + permedia2->pci_regs[0x3d] = 1; + permedia2->pci_regs[0x3e] = 4; + permedia2->pci_regs[0x3f] = 0xff; + + + svga->vsync_callback = permedia2_vblank_start; + svga->adjust_panning = permedia2_adjust_panning; + + permedia2->chip = chip; + + permedia2_updatemapping(permedia2); + + permedia2->card = pci_add(permedia2_pci_read, permedia2_pci_write, permedia2); + + return permedia2; +} + +void *permedia2_init() +{ + permedia2_t *permedia2 = (permedia2_t *)permedia2_init("permedia2.bin", 0); + + permedia2->svga.fb_only = -1; + + permedia2->getclock = sdac_getclock; + permedia2->getclock_p = &permedia2->ramdac; + permedia2->id_ext_pci = 0x07; + sdac_init(&permedia2->ramdac); + svga_set_ramdac_type(&permedia2->svga, RAMDAC_8BIT); + svga_recalctimings(&permedia2->svga); + + return permedia2; +} + +void permedia2_close(void *p) +{ + permedia2_t *permedia2 = (permedia2_t*)p; + + svga_close(&permedia2->svga); + + free(permedia2); +} + +void permedia2_speed_changed(void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + + svga_recalctimings(&permedia2->svga); +} + +void permedia2_force_redraw(void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + + permedia2->svga.fullchange = changeframecount; +} + +void permedia2_add_status_info(char *s, int max_len, void *p) +{ + permedia2_t *permedia2 = (permedia2_t *)p; + uint64_t new_time = timer_read(); + + svga_add_status_info(s, max_len, &permedia2->svga); +} + +device_t permedia2_device = +{ + "Permedia 2", + 0, + permedia2_init, + permedia2_close, + NULL, + permedia2_speed_changed, + permedia2_force_redraw, + permedia2_add_status_info, + NULL +}; diff --git a/pcem/vid_permedia2.h b/pcem/vid_permedia2.h new file mode 100644 index 00000000..ebdb5f07 --- /dev/null +++ b/pcem/vid_permedia2.h @@ -0,0 +1,2 @@ + +extern device_t permedia2_device; diff --git a/pcem/vid_s3.cpp b/pcem/vid_s3.cpp index 8b65deac..f1f04ce1 100644 --- a/pcem/vid_s3.cpp +++ b/pcem/vid_s3.cpp @@ -2847,7 +2847,7 @@ static void *s3_init(char *bios_fn, int chip) svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); svga->crtc[0x37] = 1 | (7 << 5); - svga->vblank_start = s3_vblank_start; + svga->vsync_callback = s3_vblank_start; s3_io_set(s3); diff --git a/pcem/vid_s3_virge.cpp b/pcem/vid_s3_virge.cpp index 64dff2e7..e7de4ae0 100644 --- a/pcem/vid_s3_virge.cpp +++ b/pcem/vid_s3_virge.cpp @@ -3960,7 +3960,7 @@ static void *s3_virge_init() s3_virge_in, s3_virge_out, s3_virge_hwcursor_draw, s3_virge_overlay_draw); - virge->svga.vblank_start = s3_virge_vblank_start; + virge->svga.vsync_callback = s3_virge_vblank_start; rom_init(&virge->bios_rom, "s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (PCI) @@ -4059,7 +4059,7 @@ static void *s3_virge_375_init() s3_virge_in, s3_virge_out, s3_virge_hwcursor_draw, s3_virge_overlay_draw); - virge->svga.vblank_start = s3_virge_vblank_start; + virge->svga.vsync_callback = s3_virge_vblank_start; rom_init(&virge->bios_rom, "86c375_1.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (PCI) diff --git a/pcem/vid_svga.cpp b/pcem/vid_svga.cpp index 370482b0..a08eff71 100644 --- a/pcem/vid_svga.cpp +++ b/pcem/vid_svga.cpp @@ -702,8 +702,6 @@ int svga_poll(void *p) } if (svga->vc == svga->dispend) { - if (svga->vblank_start && (svga->crtc[0x17] & 0x80)) - svga->vblank_start(svga); // pclog("VC dispend\n"); svga->dispon=0; if (svga->crtc[10] & 0x20) svga->cursoron = 0; diff --git a/pcem/vid_svga.h b/pcem/vid_svga.h index 2f17d137..1cff4095 100644 --- a/pcem/vid_svga.h +++ b/pcem/vid_svga.h @@ -124,8 +124,6 @@ typedef struct svga_t void (*overlay_draw)(struct svga_t *svga, int displine); - void (*vblank_start)(struct svga_t *svga); - void (*adjust_panning)(struct svga_t *svga); /*Called when VC=R18 and friends. If this returns zero then MA resetting diff --git a/pcem/vid_voodoo_banshee.cpp b/pcem/vid_voodoo_banshee.cpp index 784e6e23..cda8bee4 100644 --- a/pcem/vid_voodoo_banshee.cpp +++ b/pcem/vid_voodoo_banshee.cpp @@ -2839,7 +2839,7 @@ static void *banshee_init_common(char *fn, int has_sgram, int type, int voodoo_t break; } - banshee->svga.vblank_start = banshee_vblank_start; + banshee->svga.vsync_callback = banshee_vblank_start; return banshee; } diff --git a/pci.cpp b/pci.cpp index 60d643e9..3c3ab70f 100644 --- a/pci.cpp +++ b/pci.cpp @@ -1747,7 +1747,7 @@ bool pci_validate_address(uaecptr addr, uae_u32 size, bool io) static void add_pci_devices(struct pci_bridge *pcib, struct autoconfig_info *aci) { - int slot = 0; + int slot = 1; if (is_device_rom(&currprefs, ROMTYPE_NE2KPCI, 0) >= 0) { pci_board_add(pcib, &ne2000_pci_board, slot++, 0, aci, NULL); @@ -1889,7 +1889,15 @@ static int grex_get_index(uaecptr addr) if ((addr & 0xfffc1000) == 0xfffc0000) { int v = (addr & 0x3f000) >> 13; - slot = countbit(v); + if (!v) { + // CyberVision/BlizzardVision + return 0; + } else { + slot = countbit(v); + if (slot >= 0) { + slot++; + } + } slot |= ((addr >> 8) & 7) << 8; } return slot; @@ -1932,42 +1940,6 @@ static bool grex_pci_init(struct autoconfig_info *aci) return true; } -// CyberVision/BlizzardVision without VGA chip... - -static int xvision_get_index(uaecptr addr) -{ - struct pci_bridge *pcib = get_pci_bridge(addr); - if ((addr & 0xfffcf700) == 0xfffc0000) - return 0; - return -1; -} - -static bool cbvision(struct autoconfig_info *aci) -{ - struct pci_bridge *pcib = pci_bridge_alloc(); - - bridges[PCI_BRIDGE_XVISION] = pcib; - pcib->label = _T("CBVision"); - pcib->intena = 0; - pcib->intreq_mask = 0x0008; - pcib->get_index = xvision_get_index; - pcib->baseaddress = 0xe0000000; - pcib->baseaddress_end = 0xffffffff; - pcib->configured = -1; - pcib->pcipcidma = true; - pcib->amigapicdma = true; - - map_banks(&pci_config_bank, 0xfffc0000 >> 16, 0x20000 >> 16, 0); - map_banks(&pci_mem_bank, 0xe0000000 >> 16, 0x10000000 >> 16, 0); - map_banks(&pci_io_bank, 0xfffa0000 >> 16, 0x20000 >> 16, 0); - map_banks(&pci_bridge_bank, 0xfffe0000 >> 16, 0x10000 >> 16, 0); - pcib->io_offset = 0xfffa0000; - aci->zorro = 0; - aci->parent_of_previous = true; - pci_init(); - return true; -} - // Mediator // Mediator 4000MK2 @@ -2283,11 +2255,6 @@ bool prometheus_init(struct autoconfig_info *aci) return prometheus_pci_init(aci); } -bool cbvision_init(struct autoconfig_info *aci) -{ - return cbvision(aci); -} - bool grex_init(struct autoconfig_info *aci) { return grex_pci_init(aci); -- 2.47.3