From: Toni Wilen Date: Sun, 8 Nov 2020 10:32:28 +0000 (+0200) Subject: Graphics board emulation fixes. X-Git-Tag: 4900~257 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=6552795764f0b1282a47528ba01a874beeff4b42;p=francis%2Fwinuae.git Graphics board emulation fixes. --- diff --git a/gfxboard.cpp b/gfxboard.cpp index 89d3b451..431d38ce 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -16,6 +16,7 @@ #define MEMDEBUGMASK 0x7fffff #define MEMDEBUGTEST 0x3fc000 #define MEMDEBUGCLEAR 0 +#define SPCDEBUG 0 #define PICASSOIV_DEBUG_IO 0 #if MEMLOGR @@ -110,6 +111,7 @@ struct gfxboard uae_u8 er_type; struct gfxboard_func *func; device_t *pcemdev; + uae_u8 er_flags; }; #define ISP4() (gb->rbc->rtgmem_type == GFXBOARD_ID_PICASSO4_Z2 || gb->rbc->rtgmem_type == GFXBOARD_ID_PICASSO4_Z3) @@ -173,21 +175,21 @@ static const struct gfxboard boards[] = _T("CyberVision 64 Zorro III"), _T("Phase 5"), _T("CV64_Z3"), 8512, 34, 0, 0x00000000, 0x00200000, 0x00400000, 0x20000000, 0, 3, 2, false, - 0, 0, NULL, &s3_cybervision_trio64_device + 0, 0, NULL, &s3_cybervision_trio64_device, 0x40 }, { GFXBOARD_ID_CV643D_Z2, _T("CyberVision 64/3D Zorro II"), _T("Phase 5"), _T("CV643D_Z2"), 8512, 67, 0, 0x00000000, 0x00400000, 0x00400000, 0x00400000, 0, 2, 2, false, - 0, 0, NULL, &s3_virge_device + 0, 0, NULL, &s3_virge_device, 0xc0 }, { GFXBOARD_ID_CV643D_Z3, _T("CyberVision 64/3D Zorro III"), _T("Phase 5"), _T("CV643D_Z3"), 8512, 67, 0, 0x00000000, 0x00400000, 0x00400000, 0x10000000, 0, 3, 2, false, - 0, 0, NULL, &s3_virge_device + 0, 0, NULL, &s3_virge_device, 0x40 }, { GFXBOARD_ID_PICASSO2, @@ -3558,6 +3560,7 @@ bool gfxboard_init_memory (struct autoconfig_info *aci) int bank; uae_u8 z2_flags, z3_flags, type; struct uae_prefs *p = aci->prefs; + uae_u8 flags = 0; gfxboard_init (aci, gb); @@ -3580,22 +3583,26 @@ bool gfxboard_init_memory (struct autoconfig_info *aci) } } if (gb->board->configtype == 3) { - type = 0x80 | z3_flags | (gb->board->model_registers ? 0x08 : 0x00); - ew (gb, 0x08, 0x10 | 0x20); + type = 0x80 | z3_flags; + flags |= 0x10 | 0x20; } else { - type = z2_flags | 0x08 | 0xc0; + type = z2_flags | 0xc0; } - ew (gb, 0x04, gb->board->model_memory); - ew (gb, 0x10, gb->board->manufacturer >> 8); - ew (gb, 0x14, gb->board->manufacturer); + type |= gb->board->model_registers ? 0x08 : 0x00; + flags |= gb->board->er_flags; + + ew(gb, 0x04, gb->board->model_memory); + ew(gb, 0x10, gb->board->manufacturer >> 8); + ew(gb, 0x14, gb->board->manufacturer); uae_u32 ser = gb->board->serial; - ew (gb, 0x18, ser >> 24); /* ser.no. Byte 0 */ - ew (gb, 0x1c, ser >> 16); /* ser.no. Byte 1 */ - ew (gb, 0x20, ser >> 8); /* ser.no. Byte 2 */ - ew (gb, 0x24, ser >> 0); /* ser.no. Byte 3 */ + ew(gb, 0x18, ser >> 24); /* ser.no. Byte 0 */ + ew(gb, 0x1c, ser >> 16); /* ser.no. Byte 1 */ + ew(gb, 0x20, ser >> 8); /* ser.no. Byte 2 */ + ew(gb, 0x24, ser >> 0); /* ser.no. Byte 3 */ - ew (gb, 0x00, type); + ew(gb, 0x00, type); + ew(gb, 0x08, flags); if (ISP4()) { int roms[] = { 91, -1 }; @@ -4611,17 +4618,20 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) struct rtggfxboard *gb = getgfxboard(addr); int boardnum = gb->rbc->rtgmem_type; +#if SPCDEBUG // if ((addr & 0xfffff) != 0x40021) -// write_log(_T("PCEM SPECIAL PUT %08x %08x %d\n"), addr, v, size); + write_log(_T("PCEM SPECIAL PUT %08x %08x %d PC=%08x\n"), addr, v, size, M68K_GETPC); +#endif if (boardnum == GFXBOARD_ID_CV643D_Z2) { + uaecptr addr2 = (addr - gb->gfxboardmem_start) & gb->banksize_mask; uaecptr addrd = addr2 + gb->gfxboardmem_start; if (gb->pcem_pci_configured) { if (addr2 >= 0x3c0000 && addr2 < 0x3d0000) { addrd &= 0x3fff; if (size == 1) { - v = do_byteswap_16(v); + addrd ^= 2; } else { addrd ^= 3; } @@ -4634,7 +4644,7 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) } else if (addr2 == 0x3a0000 + 8) { // Z2 endian select gb->pcem_data[1] = v; - gb->pcem_vram_offset = (v & 0x40) ? 0 : 0x800000; + gb->pcem_vram_offset = (v & 0xc0) << 16; return; } else if (addr2 == 0x3a0000 + 0) { if (size == 1) { @@ -4662,7 +4672,14 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) return; } } - if (addr2 >= 0x3e8000 && addr2 < 0x3f0000) { + if (addr2 >= 0x3c8000 && addr2 < 0x3d0000) { + if (size == 0) + gfxboard_bput_mmio_pcem(addrd, v); + else if (size == 1) + gfxboard_wput_mmio_pcem(addrd, v); + else + gfxboard_lput_mmio_pcem(addrd, v); + } else if (addr2 >= 0x3e8000 && addr2 < 0x3f0000) { if (size == 0) gfxboard_bput_mmio_pcem(addrd, v); else if (size == 1) @@ -4670,26 +4687,12 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size) else gfxboard_lput_mmio_pcem(addrd, v); } else if (addr2 >= 0x3e0000 && addr2 < 0x3e8000) { - int em = (gb->pcem_data[1] >> 7) & 1; - switch (em) - { - case 0: - if (size == 0) - gfxboard_bput_mmio_pcem(addrd, v); - else if (size == 1) - gfxboard_wput_mmio_pcem(addrd, v); - else - gfxboard_lput_mmio_pcem(addrd, v); - break; - case 1: - if (size == 0) - gfxboard_bput_mmio_wbs_pcem(addrd, v); - else if (size == 1) - gfxboard_wput_mmio_wbs_pcem(addrd, v); - else - gfxboard_lput_mmio_wbs_pcem(addrd, v); - break; - } + if (size == 0) + gfxboard_bput_mmio_wbs_pcem(addrd, v); + else if (size == 1) + gfxboard_wput_mmio_wbs_pcem(addrd, v); + else + gfxboard_lput_mmio_wbs_pcem(addrd, v); } } else if (boardnum == GFXBOARD_ID_CV64_Z3) { @@ -4889,8 +4892,10 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) int boardnum = gb->rbc->rtgmem_type; uae_u32 v = 0; +#if SPCDEBUG // if ((addr & 0xfffff) != 0x40021) -// write_log(_T("PCEM SPECIAL GET %08x %d\n"), addr, size); + write_log(_T("PCEM SPECIAL GET %08x %d PC=%08x\n"), addr, size, M68K_GETPC); +#endif if (boardnum == GFXBOARD_ID_CV643D_Z2) { uaecptr addr2 = (addr - gb->gfxboardmem_start) & gb->banksize_mask; @@ -4901,11 +4906,10 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) addrd &= 0x3fff; if (size == 0) { addrd ^= 3; + } else if (size == 1) { + addrd ^= 2; } v = get_io_pcem(addrd, size); - if (size == 1) { - v = do_byteswap_16(v); - } } } else { if (addr2 >= 0x3c0000 && addr2 < 0x3c8000) { @@ -4917,7 +4921,14 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) v = gfxboard_lget_pci_pcem(addrd); } } - if (addr2 >= 0x3e8000 && addr2 < 0x3f0000) { + if (addr2 >= 0x3c8000 && addr2 < 0x3d0000) { + if (size == 0) + v = gfxboard_bget_mmio_pcem(addrd); + else if (size == 1) + v = gfxboard_wget_mmio_pcem(addrd); + else + v = gfxboard_lget_mmio_pcem(addrd); + } else if (addr2 >= 0x3e8000 && addr2 < 0x3f0000) { if (size == 0) v = gfxboard_bget_mmio_pcem(addrd); else if (size == 1) @@ -4925,26 +4936,12 @@ static uae_u32 special_pcem_get(uaecptr addr, int size) else v = gfxboard_lget_mmio_pcem(addrd); } else if (addr2 >= 0x3e0000 && addr2 < 0x3e8000) { - int em = (gb->pcem_data[1] >> 7) & 1; - switch (em) - { - case 0: - if (size == 0) - v = gfxboard_bget_mmio_pcem(addrd); - else if (size == 1) - v = gfxboard_wget_mmio_pcem(addrd); - else - v = gfxboard_lget_mmio_pcem(addrd); - break; - case 1: - if (size == 0) - v = gfxboard_bget_mmio_wbs_pcem(addrd); - else if (size == 1) - v = gfxboard_wget_mmio_wbs_pcem(addrd); - else - v = gfxboard_lget_mmio_wbs_pcem(addrd); - break; - } + if (size == 0) + v = gfxboard_bget_mmio_wbs_pcem(addrd); + else if (size == 1) + v = gfxboard_wget_mmio_wbs_pcem(addrd); + else + v = gfxboard_lget_mmio_wbs_pcem(addrd); } } else if (boardnum == GFXBOARD_ID_CV64_Z3) { diff --git a/pcem/vid_cl5429.cpp b/pcem/vid_cl5429.cpp index f3763e0b..ddf3a6c5 100644 --- a/pcem/vid_cl5429.cpp +++ b/pcem/vid_cl5429.cpp @@ -149,16 +149,21 @@ uint8_t gd5429_read_linear(uint32_t addr, void *p); static void ibm_gd5428_mapping_update(gd5429_t *gd5429); -static int s3_vga_vsync_enabled(gd5429_t *gd5429) +static int gd5429_interrupt_enabled(gd5429_t* gd5429) { - if (!(gd5429->svga.crtc[0x11] & 0x20) && (gd5429->svga.crtc[0x11] & 0x10) && (gd5429->type < PCI || (gd5429->svga.gdcreg[0x17] & 4))) + return !PCI || (gd5429->svga.gdcreg[0x17] & 4); +} + +static int gd5429_vga_vsync_enabled(gd5429_t *gd5429) +{ + if (!(gd5429->svga.crtc[0x11] & 0x20) && (gd5429->svga.crtc[0x11] & 0x10) && gd5429_interrupt_enabled(gd5429)) return 1; return 0; } static void gd5429_update_irqs(gd5429_t *gd5429) { - if (gd5429->vblank_irq > 0 && s3_vga_vsync_enabled(gd5429)) + if (gd5429->vblank_irq > 0 && gd5429_vga_vsync_enabled(gd5429)) pci_set_irq(NULL, PCI_INTA); else pci_clear_irq(NULL, PCI_INTA); @@ -396,12 +401,13 @@ static void gd5429_vblank_start(svga_t *svga) static void gd5429_overlay_draw(svga_t *svga, int displine) { gd5429_t *gd5429 = (gd5429_t*)svga->p; + int shift = gd5429->type >= CL_TYPE_GD5446 ? 2 : 0; int h_acc = svga->overlay_latch.h_acc; int r[8], g[8], b[8], ck[8]; int x_read = 4, x_write = 4; int x; uint32_t *p; - uint8_t *src = &svga->vram[svga->overlay_latch.addr & svga->vram_mask]; + uint8_t *src = &svga->vram[(svga->overlay_latch.addr << shift) & svga->vram_mask]; int bpp = svga->bpp; int bytesperpix = (bpp + 7) / 8; uint8_t *src2 = &svga->vram[(svga->ma - (svga->hdisp * bytesperpix)) & svga->vram_display_mask]; @@ -457,7 +463,7 @@ static void gd5429_overlay_draw(svga_t *svga, int displine) if (svga->overlay_latch.v_acc >= 256) { svga->overlay_latch.v_acc -= 256; - svga->overlay_latch.addr += svga->overlay.pitch; + svga->overlay_latch.addr += svga->overlay.pitch << 1; } } @@ -851,13 +857,13 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) case 0x3c: svga->overlay.addr &= ~0x0f0000; svga->overlay.addr |= (val << 16) & 0x0f0000; - svga->overlay.pitch &= ~(1 << 11); - svga->overlay.pitch |= ((val >> 5) & 1) << 11; + svga->overlay.pitch &= ~0x100; + svga->overlay.pitch |= (val & 0x20) << 3; gd5429_update_overlay(gd5429); break; case 0x3d: - svga->overlay.pitch &= ~(0xff << 3); - svga->overlay.pitch |= val << 3; + svga->overlay.pitch &= ~0xff; + svga->overlay.pitch |= val; gd5429_update_overlay(gd5429); break; case 0x3e: @@ -2128,8 +2134,8 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p) } count--; } - dst = svga->vram[gd5429->blt.dst_addr & svga->vram_mask]; - svga->changedvram[(gd5429->blt.dst_addr & svga->vram_mask) >> 12] = changeframecount; + dst = svga->vram[(gd5429->blt.dst_addr + bplcnt) & svga->vram_mask]; + svga->changedvram[((gd5429->blt.dst_addr + bplcnt) & svga->vram_mask) >> 12] = changeframecount; //pclog("Blit %i,%i %06X %06X %06X %02X %02X %02X %02X\n", gd5429->blt.width, gd5429->blt.height_internal, gd5429->blt.src_addr, gd5429->blt.dst_addr, gd5429->blt.src_addr & svga->vram_mask, svga->vram[gd5429->blt.src_addr & svga->vram_mask], 0x80 >> (gd5429->blt.dst_addr & 7), src, dst); switch (gd5429->blt.rop) diff --git a/pcem/vid_s3.cpp b/pcem/vid_s3.cpp index f5133388..bc4acd34 100644 --- a/pcem/vid_s3.cpp +++ b/pcem/vid_s3.cpp @@ -144,6 +144,7 @@ typedef struct s3_t uint64_t status_time; uint8_t subsys_cntl, subsys_stat; + int vblank_irq; uint32_t hwc_fg_col, hwc_bg_col; int hwc_col_stack_pos; @@ -180,7 +181,7 @@ static void s3_wait_fifo_idle(s3_t *s3) static int s3_vga_vsync_enabled(s3_t *s3) { - if (!(s3->svga.crtc[0x11] & 0x20) && (s3->svga.crtc[0x11] & 0x10) && (s3->svga.crtc[0x32] & 0x10)) + if ((s3->svga.crtc[0x32] & 0x10) && !(s3->svga.crtc[0x11] & 0x20) && s3->vblank_irq > 0) return 1; return 0; } @@ -188,7 +189,7 @@ static int s3_vga_vsync_enabled(s3_t *s3) static void s3_update_irqs(s3_t *s3) { int enabled = s3_vga_vsync_enabled(s3); - if ((s3->subsys_cntl & s3->subsys_stat & INT_MASK) || (enabled && (s3->subsys_stat & INT_VSY))) + if (((s3->subsys_cntl & s3->subsys_stat & INT_MASK) && (s3->svga.crtc[0x32] & 0x10)) || (enabled && (s3->subsys_stat & INT_VSY))) pci_set_irq(s3->card, PCI_INTA); else pci_clear_irq(s3->card, PCI_INTA); @@ -198,6 +199,12 @@ static void s3_update_irqs(s3_t *s3) } } +static void s3_update_irqs_thread(s3_t* s3, int mask) +{ + if ((s3->subsys_cntl & s3->subsys_stat & mask) && (s3->svga.crtc[0x32] & 0x10)) + pci_set_irq(s3->card, PCI_INTA); +} + void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) switch ((addr) & 3) \ @@ -929,7 +936,7 @@ static void fifo_thread(void *param) } s3->blitter_busy = 0; s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); + s3_update_irqs_thread(s3, INT_FIFO_EMP); } s3->fifo_thread_state = 0; } @@ -937,6 +944,9 @@ static void fifo_thread(void *param) static void s3_vblank_start(svga_t *svga) { s3_t *s3 = (s3_t *)svga->p; + if (s3->vblank_irq >= 0) { + s3->vblank_irq = 1; + } if ((s3->subsys_cntl & INT_VSY) || s3_vga_vsync_enabled(s3)) { s3->subsys_stat |= INT_VSY; s3_update_irqs(s3); @@ -1017,14 +1027,19 @@ void s3_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; + if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) + return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; switch (svga->crtcreg) { case 0x11: - if (!(val & 0x10)) - s3->subsys_stat &= ~INT_VSY; + if (!(val & 0x10)) { + if (s3->vblank_irq > 0) + s3->vblank_irq = -1; + } else if (s3->vblank_irq < 0) { + s3->vblank_irq = 0; + } s3_update_irqs(s3); if ((val & ~0x30) == (old & ~0x30)) old = val; @@ -1179,6 +1194,7 @@ uint8_t s3_in(uint16_t addr, void *p) case 0x3c2: ret = svga_in(addr, svga); ret |= (s3->subsys_stat & INT_VSY) ? 0x80 : 0x00; + ret |= s3->vblank_irq > 0 ? 0x80 : 0x00; return ret; case 0x3c5: diff --git a/pcem/vid_s3_virge.cpp b/pcem/vid_s3_virge.cpp index 8fbf4df3..288776e6 100644 --- a/pcem/vid_s3_virge.cpp +++ b/pcem/vid_s3_virge.cpp @@ -309,21 +309,28 @@ enum #define INT_3DF_EMP (1 << 6) #define INT_MASK 0xff -static int is_interrupt_active(virge_t *virge) +static int virge_vga_vsync_enabled(virge_t *virge) { - if ((virge->svga.crtc[0x32] & 0x10) && ((!(virge->svga.crtc[0x11] & 0x20) && virge->vblank_irq > 0) || (virge->subsys_stat & virge->subsys_cntl & INT_MASK))) + if ((virge->svga.crtc[0x32] & 0x10) && !(virge->svga.crtc[0x11] & 0x20) && virge->vblank_irq > 0) return 1; return 0; } static void s3_virge_update_irqs(virge_t *virge) { - if (is_interrupt_active(virge)) + if (((virge->subsys_stat & virge->subsys_cntl & INT_MASK) && virge->svga.crtc[0x32] & 0x10) || virge_vga_vsync_enabled(virge)) pci_set_irq(virge->card, PCI_INTA); else pci_clear_irq(virge->card, PCI_INTA); } +static void s3_virge_update_irqs_thread(virge_t* virge, int mask) +{ + if ((virge->subsys_stat & virge->subsys_cntl & INT_MASK & mask) && virge->svga.crtc[0x32] & 0x10) + pci_set_irq(virge->card, PCI_INTA); +} + + static void s3_virge_out(uint16_t addr, uint8_t val, void *p) { virge_t *virge = (virge_t *)p; @@ -360,12 +367,16 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga->crtcreg = val;// & 0x7f; return; case 0x3d5: - //pclog("Write CRTC R%02X %02X %04x(%08x):%08x\n", svga->crtcreg, val, CS, cs, pc); + //pclog("Write CRTC R%02X %02X %04x(%08x):%08x\n", svga->crtcreg, val, CS, cs, 0); if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) + if (svga->crtcreg >= 0x2d && svga->crtcreg <= 0x3f && svga->crtcreg != 0x38 && svga->crtcreg != 0x39 && (svga->crtc[0x38] & 0xcc) != 0x48) + return; + if (svga->crtcreg >= 0x40 && (svga->crtc[0x39] & 0xe0) != 0xa0) + return; + if ((svga->crtcreg == 0x36 || svga->crtcreg == 0x37 || svga->crtcreg == 0x68) && (svga->crtc[0x39] & 0xe5) != 0xa5) return; if (svga->crtcreg >= 0x80) return; @@ -1358,7 +1369,7 @@ static void fifo_thread(void *param) } virge->virge_busy = 0; virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP; - s3_virge_update_irqs(virge); + s3_virge_update_irqs_thread(virge, INT_FIFO_EMP | INT_3DF_EMP); } virge->fifo_thread_state = 0; } @@ -3414,7 +3425,7 @@ static void render_thread(void *param) } virge->s3d_busy = 0; virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); + s3_virge_update_irqs_thread(virge, INT_S3D_DONE); } virge->render_thread_state = 0; }