From daf27a573e5141f42561c9f33b2f94fa431f2a99 Mon Sep 17 00:00:00 2001 From: cracyc Date: Fri, 28 May 2021 17:02:41 -0500 Subject: [PATCH] x68k: fix 512 line double scan modes --- src/mame/video/x68k.cpp | 89 +++++++++++++++++++++++++----------- src/mame/video/x68k_crtc.cpp | 73 ++++++----------------------- src/mame/video/x68k_crtc.h | 1 + 3 files changed, 78 insertions(+), 85 deletions(-) diff --git a/src/mame/video/x68k.cpp b/src/mame/video/x68k.cpp index f51eff76886..484292d9748 100644 --- a/src/mame/video/x68k.cpp +++ b/src/mame/video/x68k.cpp @@ -203,11 +203,14 @@ void x68k_state::draw_text(bitmap_rgb32 &bitmap, int xscr, int yscr, rectangle r uint32_t loc; // location in TVRAM uint32_t colour; int bit; + int divisor = 1; + if(m_crtc->gfx_double_scan()) + divisor = 2; for(line=rect.min_y;line<=rect.max_y;line++) // per scanline { // adjust for scroll registers - loc = (((line - m_crtc->vbegin()) + yscr) & 0x3ff) * 64; + loc = ((((line- m_crtc->vbegin()) / divisor) + yscr) & 0x3ff) * 64; loc += (xscr / 16) & 0x7f; loc &= 0xffff; bit = 15 - (xscr & 0x0f); @@ -241,6 +244,9 @@ bool x68k_state::draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprect, ui int shift; bool blend, ret = false; uint16_t *pal = (uint16_t *)m_gfxpalette->basemem().base(); + int divisor = 1; + if(m_crtc->gfx_double_scan()) + divisor = 2; for(int scanline=cliprect.min_y;scanline<=cliprect.max_y;scanline++) // per scanline { @@ -296,7 +302,7 @@ bool x68k_state::draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprect, ui case 0x00: // 16 colours xscr = m_crtc->xscr_gfx(page) & 0x1ff; yscr = m_crtc->yscr_gfx(page) & 0x1ff; - lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x1ff) * 512; + lineoffset = (((scanline - m_crtc->vbegin() / divisor) + yscr) & 0x1ff) * 512; loc = xscr & 0x1ff; shift = 4; if((m_video.reg[2] & 0x1a00) == 0x1a00) @@ -342,7 +348,7 @@ bool x68k_state::draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprect, ui { xscr = m_crtc->xscr_gfx(page) & 0x1ff; yscr = m_crtc->yscr_gfx(page) & 0x1ff; - lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x1ff) * 512; + lineoffset = (((scanline - m_crtc->vbegin() / divisor) + yscr) & 0x1ff) * 512; loc = xscr & 0x1ff; shift = 4; if((m_video.reg[2] & 0x1a00) == 0x1a00) @@ -387,7 +393,7 @@ bool x68k_state::draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprect, ui case 0x03: // 65536 colours xscr = m_crtc->xscr_gfx(0) & 0x1ff; yscr = m_crtc->yscr_gfx(0) & 0x1ff; - lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x1ff) * 512; + lineoffset = (((scanline - m_crtc->vbegin() / divisor) + yscr) & 0x1ff) * 512; loc = xscr & 0x1ff; for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++) { @@ -409,20 +415,25 @@ void x68k_state::draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect) { int priority, scanline, pixel; bool gfxblend=false; - //rectangle rect; - //int xscr,yscr; - //int gpage; + rectangle gfxrect = cliprect; + int divisor = 1; + if(m_crtc->gfx_double_scan()) + { + gfxrect.max_y >>= 1; + gfxrect.min_y >>= 1; + divisor = 2; + } if(m_crtc->gfx_layer_buffer()) // if graphic layers are set to buffer, then they aren't visible return; - m_gfxbitmap.fill(0, cliprect); + m_gfxbitmap.fill(0, gfxrect); if((m_video.reg[2] & 0x1800) == 0x1000) - m_special.fill(0, cliprect); + m_special.fill(0, gfxrect); for(priority=3;priority>=0;priority--) { - gfxblend = draw_gfx_scanline(m_gfxbitmap,cliprect,priority); + gfxblend = draw_gfx_scanline(m_gfxbitmap,gfxrect,priority); } for(scanline=cliprect.min_y;scanline<=cliprect.max_y;scanline++) @@ -433,13 +444,13 @@ void x68k_state::draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect) { if((m_video.reg[0] & 0x03) == 3) { - colour = m_gfxbitmap.pix(scanline, pixel); + colour = m_gfxbitmap.pix(scanline / divisor, pixel); if(colour || (m_video.gfx_pri == 2)) bitmap.pix(scanline, pixel) = GGGGGRRRRRBBBBBI(colour); } else if(gfxblend) { - colour = m_gfxbitmap.pix(scanline, pixel); + colour = m_gfxbitmap.pix(scanline / divisor, pixel); if(((m_video.reg[2] & 0x1900) == 0x1900) && (m_video.gfx_pri != 2) && (colour & 1)) blend = true; else @@ -454,7 +465,7 @@ void x68k_state::draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect) } else { - colour = m_gfxbitmap.pix(scanline, pixel) & 0xff; + colour = m_gfxbitmap.pix(scanline / divisor, pixel) & 0xff; if(((m_video.reg[2] & 0x1900) == 0x1900) && (m_video.gfx_pri != 2) && (colour & 1)) { blend = true; @@ -507,6 +518,9 @@ void x68k_state::draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle clip b1-0, H-Res (0 = 8x8 tilemaps, 1 = 16x16 tilemaps, 2 or 3 = unknown) */ int ptr,pri; + int divisor = 1; + if(!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) + divisor = 2; for(ptr=508;ptr>=0;ptr-=4) // stepping through sprites { @@ -532,7 +546,7 @@ void x68k_state::draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle clip sx += m_video.bg_hshift; sx += m_sprite_shift; - m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect,code,colour,xflip,yflip,m_crtc->hbegin()+sx,m_crtc->vbegin()+(sy*m_video.bg_double),0x10000,0x10000*m_video.bg_double,0x00); + m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect,code,colour,xflip,yflip,m_crtc->hbegin()+sx,(m_crtc->vbegin() / divisor)+(sy*m_video.bg_double),0x10000,0x10000*m_video.bg_double,0x00); } } } @@ -544,6 +558,9 @@ void x68k_state::draw_bg(bitmap_ind16 &bitmap, screen_device &screen, int layer, tilemap_t* x68k_bg0; tilemap_t* x68k_bg1; tilemap_t* map; + int divisor = 1; + if(!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) + divisor = 2; if((m_spritereg[0x408] & 0x03) == 0x00) // Sprite/BG H-Res 0=8x8, 1=16x16, 2 or 3 = undefined. { @@ -562,7 +579,7 @@ void x68k_state::draw_bg(bitmap_ind16 &bitmap, screen_device &screen, int layer, map = (m_spritereg[0x404] & 0x0006) == 0x02 ? x68k_bg0 : x68k_bg1; map->set_scrollx(0,(sclx - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff); - map->set_scrolly(0,(scly - m_crtc->vbegin()) & 0x3ff); + map->set_scrolly(0,(scly - (m_crtc->vbegin() / divisor)) & 0x3ff); map->draw(screen, bitmap, rect, opaque ? TILEMAP_DRAW_OPAQUE : 0, 0); } @@ -698,24 +715,33 @@ uint32_t x68k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, bool clear = false; if(m_video.reg[2] & 0x0040) { + rectangle pcgrect = rect; + if(!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) + { + pcgrect.max_y >>= 1; + pcgrect.min_y >>= 1; + } if(m_spritereg[0x404] & 0x0008) { clear = true; - draw_bg(m_pcgbitmap, screen, 1, true, rect); + draw_bg(m_pcgbitmap, screen, 1, true, pcgrect); } else if(m_spritereg[0x404] & 0x0001) { clear = true; - draw_bg(m_pcgbitmap, screen, 0, true, rect); + draw_bg(m_pcgbitmap, screen, 0, true, pcgrect); } } if(clear) { + int divisor = 1; + if(!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) + divisor = 2; for(scanline=rect.min_y;scanline<=rect.max_y;scanline++) { for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++) { - uint8_t colour = m_pcgbitmap.pix(scanline, pixel) & 0xff; + uint8_t colour = m_pcgbitmap.pix(scanline / divisor, pixel) & 0xff; bitmap.pix(scanline, pixel) = m_pcgpalette->pen(colour); } } @@ -732,22 +758,30 @@ uint32_t x68k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, // Sprite / BG Tiles if(priority == m_video.sprite_pri /*&& (m_spritereg[0x404] & 0x0200)*/ && (m_video.reg[2] & 0x0040)) { - m_pcgbitmap.fill(0, rect); - draw_sprites(m_pcgbitmap,1,rect); + rectangle pcgrect = rect; + int divisor = 1; + if(!(m_video.bg_hvres & 0x0c) && m_crtc->gfx_double_scan()) + { + pcgrect.max_y >>= 1; + pcgrect.min_y >>= 1; + divisor = 2; + } + m_pcgbitmap.fill(0, pcgrect); + draw_sprites(m_pcgbitmap,1,pcgrect); if(m_spritereg[0x404] & 0x0008) - draw_bg(m_pcgbitmap, screen, 1, false, rect); + draw_bg(m_pcgbitmap, screen, 1, false, pcgrect); - draw_sprites(m_pcgbitmap,2,rect); + draw_sprites(m_pcgbitmap,2,pcgrect); if(m_spritereg[0x404] & 0x0001) - draw_bg(m_pcgbitmap, screen, 0, false, rect); + draw_bg(m_pcgbitmap, screen, 0, false, pcgrect); - draw_sprites(m_pcgbitmap,3,rect); + draw_sprites(m_pcgbitmap,3,pcgrect); for(scanline=rect.min_y;scanline<=rect.max_y;scanline++) { for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++) { - uint8_t colour = m_pcgbitmap.pix(scanline, pixel) & 0xff; + uint8_t colour = m_pcgbitmap.pix(scanline / divisor, pixel) & 0xff; if(colour && (m_pcgpalette->pen(colour) & 0xffffff)) bitmap.pix(scanline, pixel) = m_pcgpalette->pen(colour); } @@ -767,11 +801,14 @@ uint32_t x68k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, if((m_video.reg[2] & 0x1800) == 0x1000) // special priority { uint16_t colour; + int divisor = 1; + if(m_crtc->gfx_double_scan()) + divisor = 2; for(scanline=rect.min_y;scanline<=rect.max_y;scanline++) { for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++) { - colour = m_special.pix(scanline, pixel) & 0xff; + colour = m_special.pix(scanline / divisor, pixel) & 0xff; if(colour) bitmap.pix(scanline, pixel) = m_gfxpalette->pen(colour & ~1); } diff --git a/src/mame/video/x68k_crtc.cpp b/src/mame/video/x68k_crtc.cpp index b3dd9bb62fb..3792ae68b4a 100644 --- a/src/mame/video/x68k_crtc.cpp +++ b/src/mame/video/x68k_crtc.cpp @@ -152,18 +152,14 @@ void x68k_crtc_device::refresh_mode() { // Calculate data from register values m_vmultiple = 1; - if ((m_reg[20] & 0x10) != 0 && (m_reg[20] & 0x0c) == 0) - m_vmultiple = 2; // 31.5kHz + 256 lines = doublescan if (m_interlace) m_vmultiple = 0.5f; // 31.5kHz + 1024 lines or 15kHz + 512 lines = interlaced m_htotal = (m_reg[0] + 1) * 8; m_vtotal = (m_reg[4] + 1) / m_vmultiple; // default is 567 (568 scanlines) m_hbegin = (m_reg[2] * 8) + 1; - m_hend = (m_reg[3] * 8); - m_vbegin = (m_reg[6]) / m_vmultiple; + m_hend = m_reg[3] * 8; + m_vbegin = m_reg[6] / m_vmultiple; m_vend = (m_reg[7] - 1) / m_vmultiple; - if ((m_vmultiple == 2) && !(m_reg[7] & 1)) // otherwise if the raster irq line == vblank line, the raster irq fires too late - m_vend++; m_hsync_end = (m_reg[1]) * 8; m_vsync_end = (m_reg[5]) / m_vmultiple; m_hsyncadjust = m_reg[8]; @@ -193,8 +189,8 @@ void x68k_crtc_device::refresh_mode() unsigned div = (m_reg[20] & 0x03) == 0 ? 4 : 2; if (BIT(m_reg[20], 4) && !BIT(m_reg[20], 1)) div = BIT(m_reg[20], 0) ? 3 : 6; - if ((m_reg[20] & 0x0c) == 0) - div *= 2; + if (!(m_reg[20] & 0x1f)) + div = 8; attotime refresh = attotime::from_hz((BIT(m_reg[20], 4) ? clock_69m() : clock_39m()) / div) * (scr.max_x * scr.max_y); LOG("screen().configure(%i,%i,[%i,%i,%i,%i],%f)\n", scr.max_x, scr.max_y, visiblescr.min_x, visiblescr.min_y, visiblescr.max_x, visiblescr.max_y, refresh.as_hz()); screen().configure(scr.max_x, scr.max_y, visiblescr, refresh.as_attoseconds()); @@ -211,59 +207,18 @@ TIMER_CALLBACK_MEMBER(x68k_crtc_device::hsync) if (m_operation & 8) text_copy((m_reg[22] & 0xff00) >> 8, (m_reg[22] & 0x00ff), (m_reg[21] & 0xf)); - if (m_vmultiple == 2) // 256-line (doublescan) + if (hstate == 1) { - if (hstate == 1) - { - if (m_oddscanline) - { - int scan = screen().vpos(); - hsync_time = screen().time_until_pos(scan, (m_htotal + m_hend) / 2); - m_scanline_timer->adjust(hsync_time); - if ((scan != 0) && (scan < m_vend)) - screen().update_partial(scan - 1); - } - else - { - int scan = screen().vpos(); - hsync_time = screen().time_until_pos(scan, m_hend / 2); - m_scanline_timer->adjust(hsync_time); - if ((scan != 0) && (scan < m_vend)) - screen().update_partial(scan - 1); - } - } - if (hstate == 0) - { - if (m_oddscanline) - { - int scan = screen().vpos() + 1; - hsync_time = screen().time_until_pos(scan, m_hbegin / 2); - m_scanline_timer->adjust(hsync_time, 1); - m_oddscanline = false; - } - else - { - hsync_time = screen().time_until_pos(screen().vpos(), (m_htotal + m_hbegin) / 2); - m_scanline_timer->adjust(hsync_time, 1); - m_oddscanline = true; - } - } + int scan = screen().vpos(); + hsync_time = screen().time_until_pos(scan, m_hend); + m_scanline_timer->adjust(hsync_time); + if ((scan != 0) && (scan < m_vend)) + screen().update_partial(scan - 1); } - else // 512-line + if (hstate == 0) { - if (hstate == 1) - { - int scan = screen().vpos(); - hsync_time = screen().time_until_pos(scan, m_hend); - m_scanline_timer->adjust(hsync_time); - if ((scan != 0) && (scan < m_vend)) - screen().update_partial(scan - 1); - } - if (hstate == 0) - { - hsync_time = screen().time_until_pos(screen().vpos() + 1, m_hbegin); - m_scanline_timer->adjust(hsync_time, 1); - } + hsync_time = screen().time_until_pos(screen().vpos() + 1, m_hbegin); + m_scanline_timer->adjust(hsync_time, 1); } } @@ -390,7 +345,7 @@ void x68k_crtc_device::crtc_w(offs_t offset, u16 data, u16 mem_mask) attotime irq_time = attotime::zero; if ((data / m_vmultiple) != screen().vpos()) { - irq_time = screen().time_until_pos((data) / m_vmultiple,2); + irq_time = screen().time_until_pos((data - 1) / m_vmultiple,2); m_rint_callback(1); } m_raster_irq_timer->adjust(irq_time, (data) / m_vmultiple); diff --git a/src/mame/video/x68k_crtc.h b/src/mame/video/x68k_crtc.h index d7b90e4b3ff..bc9f81bae0b 100644 --- a/src/mame/video/x68k_crtc.h +++ b/src/mame/video/x68k_crtc.h @@ -39,6 +39,7 @@ public: u16 yscr_gfx(int page) const { return m_reg[13 + page * 2]; } u8 vfactor() const { return (m_reg[20] & 0x0c) >> 2; } bool is_1024x1024() const { return BIT(m_reg[20], 10); } + bool gfx_double_scan() const { return (m_reg[20] & 0x1e) == 0x10; } bool gfx_layer_buffer() const { return BIT(m_reg[20], 11); } bool text_layer_buffer() const { return BIT(m_reg[20], 12); } u16 hbegin() const { return m_hbegin; }