summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/x68k_crtc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/x68k_crtc.cpp')
-rw-r--r--src/mame/video/x68k_crtc.cpp644
1 files changed, 0 insertions, 644 deletions
diff --git a/src/mame/video/x68k_crtc.cpp b/src/mame/video/x68k_crtc.cpp
deleted file mode 100644
index 70453f92b53..00000000000
--- a/src/mame/video/x68k_crtc.cpp
+++ /dev/null
@@ -1,644 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald,Carl
-
-#include "emu.h"
-#include "video/x68k_crtc.h"
-#include "screen.h"
-
-//#define VERBOSE 0
-#include "logmacro.h"
-
-// device type definitions
-DEFINE_DEVICE_TYPE(VINAS, vinas_device, "vinas", "IX0902/IX0903 VINAS CRTC")
-DEFINE_DEVICE_TYPE(VICON, vicon_device, "vicon", "IX1093 VICON CRTC")
-
-x68k_crtc_device::x68k_crtc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_video_interface(mconfig, *this)
- , m_vdisp_callback(*this)
- , m_rint_callback(*this)
- , m_hsync_callback(*this)
- , m_tvram_read_callback(*this)
- , m_gvram_read_callback(*this)
- , m_tvram_write_callback(*this)
- , m_gvram_write_callback(*this)
- , m_clock_69m(0)
- , m_clock_50m(0)
- , m_operation(0)
- , m_vblank(false)
- , m_hblank(false)
- , m_htotal(0)
- , m_vtotal(0)
- , m_hend(0)
- , m_vend(0)
- , m_hsync_end(0)
- , m_vsync_end(0)
- , m_hsyncadjust(0)
- , m_vmultiple(1)
- , m_height(0)
- , m_width(0)
- , m_visible_height(0)
- , m_visible_width(0)
- , m_hshift(0)
- , m_vshift(0)
- , m_interlace(false)
- , m_oddscanline(false)
-{
- std::fill(std::begin(m_reg), std::end(m_reg), 0);
-}
-
-vinas_device::vinas_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : x68k_crtc_device(mconfig, VINAS, tag, owner, clock)
-{
-}
-
-vicon_device::vicon_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : x68k_crtc_device(mconfig, VICON, tag, owner, clock)
-{
-}
-
-void x68k_crtc_device::device_resolve_objects()
-{
- m_vdisp_callback.resolve_safe();
- m_rint_callback.resolve_safe();
- m_hsync_callback.resolve_safe();
- m_tvram_read_callback.resolve_safe(0);
- m_gvram_read_callback.resolve_safe(0);
- m_tvram_write_callback.resolve_safe();
- m_gvram_write_callback.resolve_safe();
-}
-
-void x68k_crtc_device::device_start()
-{
- m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(x68k_crtc_device::hsync), this));
- m_operation_end_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(x68k_crtc_device::operation_end), this));
- m_raster_end_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(x68k_crtc_device::raster_end), this));
- m_raster_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(x68k_crtc_device::raster_irq), this));
- m_vblank_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(x68k_crtc_device::vblank_irq), this));
-
- // save state
- save_item(NAME(m_reg));
- save_item(NAME(m_operation));
- save_item(NAME(m_vblank));
- save_item(NAME(m_hblank));
- save_item(NAME(m_htotal));
- save_item(NAME(m_vtotal));
- save_item(NAME(m_hend));
- save_item(NAME(m_vend));
- save_item(NAME(m_hsync_end));
- save_item(NAME(m_vsync_end));
- save_item(NAME(m_hsyncadjust));
- save_item(NAME(m_vmultiple));
- save_item(NAME(m_height));
- save_item(NAME(m_width));
- save_item(NAME(m_visible_height));
- save_item(NAME(m_visible_width));
- save_item(NAME(m_hshift));
- save_item(NAME(m_vshift));
- save_item(NAME(m_interlace));
- save_item(NAME(m_oddscanline));
-}
-
-void x68k_crtc_device::device_reset()
-{
- // initialise CRTC, set registers to defaults for the standard text mode (768x512)
- m_reg[0] = 137; // Horizontal total (in characters)
- m_reg[1] = 14; // Horizontal sync end
- m_reg[2] = 28; // Horizontal start
- m_reg[3] = 124; // Horizontal end
- m_reg[4] = 567; // Vertical total
- m_reg[5] = 5; // Vertical sync end
- m_reg[6] = 40; // Vertical start
- m_reg[7] = 552; // Vertical end
- m_reg[8] = 27; // Horizontal adjust
-
- //m_scanline = screen().vpos();// = m_reg[6]; // Vertical start
-
- // start VBlank timer
- m_vblank = true;
- attotime const irq_time = screen().time_until_pos(m_reg[6],2);
- m_vblank_irq_timer->adjust(irq_time);
-
- // start HBlank timer
- m_scanline_timer->adjust(screen().scan_period(), 1);
-
- m_vdisp_callback(1);
- m_rint_callback(1);
- m_hsync_callback(1);
-}
-
-void x68k_crtc_device::text_copy(unsigned src, unsigned dest, u8 planes)
-{
- // copys one raster in T-VRAM to another raster
- offs_t src_ram = src * 256; // 128 bytes per scanline
- offs_t dest_ram = dest * 256;
-
- // update RAM in each plane
- for (int words = 256; words > 0; words--, src_ram++, dest_ram++)
- {
- for (u8 plane = 0; plane <= 3; plane++)
- if (BIT(planes, plane))
- m_tvram_write_callback(dest_ram + 0x10000 * plane, m_tvram_read_callback(src_ram + 0x10000 * plane, 0xffff), 0xffff);
- }
-}
-
-TIMER_CALLBACK_MEMBER(x68k_crtc_device::operation_end)
-{
- int bit = param;
- m_operation &= ~bit;
-}
-
-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_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];
-
- rectangle scr(0, m_htotal - 8, 0, m_vtotal);
- if (scr.max_y <= m_vend)
- scr.max_y = m_vend + 2;
- if (scr.max_x <= m_hend)
- scr.max_x = m_hend + 2;
- rectangle visiblescr(m_hbegin, m_hend, m_vbegin, m_vend);
-
- // expand visible area to the size indicated by CRTC reg 20
- int length = m_hend - m_hbegin;
- if (length < m_width)
- {
- visiblescr.min_x = m_hbegin - ((m_width - length)/2);
- visiblescr.max_x = m_hend + ((m_width - length)/2);
- }
- length = m_vend - m_vbegin;
- if (length < m_height)
- {
- visiblescr.min_y = m_vbegin - ((m_height - length)/2);
- visiblescr.max_y = m_vend + ((m_height - length)/2);
- }
- // bounds check
- if (visiblescr.min_x < 0)
- visiblescr.min_x = 0;
- if (visiblescr.min_y < 0)
- visiblescr.min_y = 0;
- if (visiblescr.max_x >= scr.max_x)
- visiblescr.max_x = scr.max_x - 2;
- if (visiblescr.max_y >= scr.max_y - 1)
- visiblescr.max_y = scr.max_y - 2;
-
-// LOG("CRTC regs - %i %i %i %i - %i %i %i %i - %i - %i\n", m_reg[0], m_reg[1], m_reg[2], m_reg[3],
-// m_reg[4], m_reg[5], m_reg[6], m_reg[7], m_reg[8], m_reg[9]);
- 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;
- 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());
-}
-
-TIMER_CALLBACK_MEMBER(x68k_crtc_device::hsync)
-{
- int hstate = param;
- attotime hsync_time;
-
- m_hblank = hstate;
- m_hsync_callback(!m_hblank);
-
- 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 (m_oddscanline)
- {
- int scan = screen().vpos();
- if (scan > m_vend)
- scan = m_vbegin;
- hsync_time = screen().time_until_pos(scan, (m_htotal + m_hend) / 2);
- m_scanline_timer->adjust(hsync_time);
- if (scan != 0)
- screen().update_partial(scan);
- }
- else
- {
- int scan = screen().vpos();
- if (scan > m_vend)
- scan = m_vbegin;
- hsync_time = screen().time_until_pos(scan, m_hend / 2);
- m_scanline_timer->adjust(hsync_time);
- if (scan != 0)
- screen().update_partial(scan);
- }
- }
- if (hstate == 0)
- {
- if (m_oddscanline)
- {
- int scan = screen().vpos();
- if (scan > m_vend)
- scan = m_vbegin;
- else
- scan++;
- 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;
- }
- }
- }
- else // 512-line
- {
- if (hstate == 1)
- {
- int scan = screen().vpos();
- if (scan > m_vend)
- scan = 0;
- hsync_time = screen().time_until_pos(scan, m_hend);
- m_scanline_timer->adjust(hsync_time);
- if (scan != 0)
- screen().update_partial(scan);
- }
- if (hstate == 0)
- {
- hsync_time = screen().time_until_pos(screen().vpos() + 1, m_hbegin);
- m_scanline_timer->adjust(hsync_time, 1);
- }
- }
-}
-
-TIMER_CALLBACK_MEMBER(x68k_crtc_device::raster_end)
-{
- m_rint_callback(1);
-}
-
-TIMER_CALLBACK_MEMBER(x68k_crtc_device::raster_irq)
-{
- int scan = param;
- attotime irq_time;
- attotime end_time;
-
- if (scan <= m_vtotal)
- {
- m_rint_callback(0);
- screen().update_partial(scan);
- irq_time = screen().time_until_pos(scan, m_hbegin);
- // end of HBlank period clears GPIP6 also?
- end_time = screen().time_until_pos(scan, m_hend);
- m_raster_irq_timer->adjust(irq_time, scan);
- m_raster_end_timer->adjust(end_time);
- LOG("GPIP6: Raster triggered at line %i (%i)\n", scan,screen().vpos());
- }
-}
-
-TIMER_CALLBACK_MEMBER(x68k_crtc_device::vblank_irq)
-{
- int val = param;
- attotime irq_time;
- int vblank_line;
-
- if (val == 1) // V-DISP on
- {
- m_vblank = 1;
- vblank_line = m_vbegin;
- irq_time = screen().time_until_pos(vblank_line, 2);
- m_vblank_irq_timer->adjust(irq_time);
- LOG("CRTC: VBlank on\n");
- }
- if (val == 0) // V-DISP off
- {
- m_vblank = 0;
- vblank_line = m_vend;
- if (vblank_line > m_vtotal)
- vblank_line = m_vtotal;
- irq_time = screen().time_until_pos(vblank_line, 2);
- m_vblank_irq_timer->adjust(irq_time, 1);
- LOG("CRTC: VBlank off\n");
- }
-
- m_vdisp_callback(!m_vblank);
-}
-
-
-// CRTC "VINAS 1+2 / VICON" at 0xe80000
-/* 0xe80000 - Registers (all are 16-bit):
- * 0 - Horizontal Total (in characters)
- * 1 - Horizontal Sync End
- * 2 - Horizontal Display Begin
- * 3 - Horizontal Display End
- * 4 - Vertical Total (in scanlines)
- * 5 - Vertical Sync End
- * 6 - Vertical Display Begin
- * 7 - Vertical Display End
- * 8 - Fine Horizontal Sync Adjustment
- * 9 - Raster Line (for Raster IRQ mapped to MFP GPIP6)
- * 10/11 - Text Layer X and Y Scroll
- * 12/13 - Graphic Layer 0 X and Y Scroll
- * 14/15 - Graphic Layer 1 X and Y Scroll
- * 16/17 - Graphic Layer 2 X and Y Scroll
- * 18/19 - Graphic Layer 3 X and Y Scroll
- * 20 - bit 12 - Text VRAM mode : 0 = display, 1 = buffer
- * bit 11 - Graphic VRAM mode : 0 = display, 1 = buffer
- * bit 10 - "Real" screen size : 0 = 512x512, 1 = 1024x1024
- * bits 8,9 - Colour mode :
- * 00 = 16 colour 01 = 256 colour
- * 10 = Undefined 11 = 65,536 colour
- * bit 4 - Horizontal Frequency : 0 = 15.98kHz, 1 = 31.50kHz
- * bits 2,3 - Vertical dots :
- * 00 = 256 01 = 512
- * 10 or 11 = 1024 (interlaced)
- * bits 0,1 - Horizontal dots :
- * 00 = 256 01 = 512
- * 10 = 768 11 = 50MHz clock mode (Compact XVI or later)
- * 21 - bit 9 - Text Screen Access Mask Enable
- * bit 8 - Text Screen Simultaneous Plane Access Enable
- * bits 4-7 - Text Screen Simultaneous Plane Access Select
- * bits 0-3 - Text Screen Line Copy Plane Select
- * Graphic Screen High-speed Clear Page Select
- * 22 - Text Screen Line Copy
- * bits 15-8 - Source Line
- * bits 7-0 - Destination Line
- * 23 - Text Screen Mask Pattern
- *
- * 0xe80481 - Operation Port (8-bit):
- * bit 3 - Text Screen Line Copy Begin
- * bit 1 - Graphic Screen High-speed Clear Begin
- * bit 0 - Image Taking Begin (?)
- * Operation Port bits are cleared automatically when the requested
- * operation is completed.
- */
-void x68k_crtc_device::crtc_w(offs_t offset, u16 data, u16 mem_mask)
-{
- if (offset < 0x24)
- COMBINE_DATA(&m_reg[offset]);
- switch (offset)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- refresh_mode();
- break;
- case 9: // CRTC raster IRQ (GPIP6)
- {
- data = m_reg[9];
- attotime irq_time = screen().time_until_pos((data) / m_vmultiple,2);
-
- if (data != screen().vpos())
- m_rint_callback(1);
- if (irq_time.as_double() > 0)
- m_raster_irq_timer->adjust(irq_time, (data) / m_vmultiple);
- }
- LOG("CRTC: Write to raster IRQ register - %i\n",data);
- break;
- case 20:
- if (ACCESSING_BITS_0_7)
- {
- m_interlace = false;
- switch (data & 0x0c)
- {
- case 0x00:
- m_height = 256;
- break;
- case 0x08:
- case 0x0c: // TODO: 1024 vertical, if horizontal freq = 31kHz
- m_height = 512;
- m_interlace = true; // if 31kHz, 1024 lines = interlaced
- break;
- case 0x04:
- m_height = 512;
- if (!(m_reg[20] & 0x0010)) // if 15kHz, 512 lines = interlaced
- m_interlace = true;
- break;
- }
- switch (data & 0x03)
- {
- case 0x00:
- m_width = 256;
- break;
- case 0x01:
- m_width = 512;
- break;
- case 0x02:
- case 0x03: // 0x03 = 50MHz clock mode (XVI only)
- m_width = 768;
- break;
- }
- }
-/* if (ACCESSING_BITS_8_15)
- {
- m_interlace = false;
- if (data & 0x0400)
- m_interlace = true;
- }*/
- logerror("CRTC: Register 20 = %04x\n", m_reg[20]);
- refresh_mode();
- break;
- case 576: // operation register
- m_operation = data;
- if (data & 0x02) // high-speed graphic screen clear
- {
- for (offs_t addr = 0; addr < 0x40000; addr++)
- m_gvram_write_callback(addr, 0, 0xffff);
- m_operation_end_timer->adjust(attotime::from_msec(10), 0x02); // time taken to do operation is a complete guess.
- }
- break;
- }
-// LOG("%s CRTC: Wrote %04x to CRTC register %i\n",machine().describe_context(), data, offset);
-}
-
-u16 x68k_crtc_device::crtc_r(offs_t offset)
-{
- if (offset < 24)
- {
-// LOG("%s CRTC: Read %04x from CRTC register %i\n",machine().describe_context(), m_reg[offset], offset);
- switch (offset)
- {
- case 9:
- return 0;
- case 10: // Text X/Y scroll
- case 11:
- case 12: // Graphic layer 0 scroll
- case 13:
- return m_reg[offset] & 0x3ff;
- case 14: // Graphic layer 1 scroll
- case 15:
- case 16: // Graphic layer 2 scroll
- case 17:
- case 18: // Graphic layer 3 scroll
- case 19:
- return m_reg[offset] & 0x1ff;
- default:
- return m_reg[offset];
- }
- }
- if (offset == 576) // operation port, operation bits are set to 0 when operation is complete
- return m_operation;
-// LOG("CRTC: [%08x] Read from unknown CRTC register %i\n",activecpu_get_pc(),offset);
- return 0xffff;
-}
-
-void x68k_crtc_device::gvram_w(offs_t offset, u16 data, u16 mem_mask)
-{
-// int xloc,yloc,pageoffset;
- /*
- G-VRAM usage is determined by colour depth and "real" screen size.
-
- For screen size of 1024x1024, all G-VRAM space is used, in one big page.
- At 1024x1024 real screen size, colour depth is always 4bpp, and ranges from
- 0xc00000-0xdfffff.
-
- For screen size of 512x512, the colour depth determines the page usage.
- 16 colours = 4 pages
- 256 colours = 2 pages
- 65,536 colours = 1 page
- Page 1 - 0xc00000-0xc7ffff Page 2 - 0xc80000-0xcfffff
- Page 3 - 0xd00000-0xd7ffff Page 4 - 0xd80000-0xdfffff
- */
-
- // handle different G-VRAM page setups
- if (m_reg[20] & 0x0800) // G-VRAM set to buffer
- {
- if (offset < 0x40000)
- m_gvram_write_callback(offset, data, mem_mask);
- }
- else
- {
- switch (m_reg[20] & 0x0300)
- {
- case 0x0300:
- if (offset < 0x40000)
- m_gvram_write_callback(offset, data, mem_mask);
- break;
- case 0x0100:
- if (offset < 0x40000)
- {
- m_gvram_write_callback(offset, data & 0x00ff, 0x00ff);
- }
- else if (offset >= 0x40000 && offset < 0x80000)
- {
- m_gvram_write_callback(offset - 0x40000, (data & 0x00ff) << 8, 0xff00);
- }
- break;
- case 0x0000:
- if (offset < 0x40000)
- {
- m_gvram_write_callback(offset, data & 0x000f, 0x000f);
- }
- else if (offset >= 0x40000 && offset < 0x80000)
- {
- m_gvram_write_callback(offset - 0x40000, (data & 0x000f) << 4, 0x00f0);
- }
- else if (offset >= 0x80000 && offset < 0xc0000)
- {
- m_gvram_write_callback(offset - 0x80000, (data & 0x000f) << 8, 0x0f00);
- }
- else if (offset >= 0xc0000 && offset < 0x100000)
- {
- m_gvram_write_callback(offset - 0xc0000, (data & 0x000f) << 12, 0xf000);
- }
- break;
- default:
- logerror("G-VRAM written while layer setup is undefined.\n");
- }
- }
-}
-
-void x68k_crtc_device::tvram_w(offs_t offset, u16 data, u16 mem_mask)
-{
- u16 text_mask = ~(m_reg[23]) & mem_mask;
-
- if (!(m_reg[21] & 0x0200)) // text access mask enable
- text_mask = 0xffff & mem_mask;
-
- mem_mask = text_mask;
-
- if (m_reg[21] & 0x0100)
- {
- // simultaneous T-VRAM plane access (I think ;))
- offset &= 0x00ffff;
- u8 wr = (m_reg[21] & 0x00f0) >> 4;
- for (int plane = 0; plane < 4; plane++)
- {
- if (BIT(wr, plane))
- {
- m_tvram_write_callback(offset + 0x10000 * plane, data, mem_mask);
- }
- }
- }
- else
- {
- m_tvram_write_callback(offset, data, mem_mask);
- }
-}
-
-u16 x68k_crtc_device::gvram_r(offs_t offset)
-{
- u16 ret = 0;
-
- if (m_reg[20] & 0x0800) // G-VRAM set to buffer
- return m_gvram_read_callback(offset);
-
- switch (m_reg[20] & 0x0300) // colour setup determines G-VRAM use
- {
- case 0x0300: // 65,536 colour (RGB) - 16-bits per word
- if (offset < 0x40000)
- ret = m_gvram_read_callback(offset);
- else
- ret = 0xffff;
- break;
- case 0x0100: // 256 colour (paletted) - 8 bits per word
- if (offset < 0x40000)
- ret = m_gvram_read_callback(offset) & 0x00ff;
- else if (offset >= 0x40000 && offset < 0x80000)
- ret = (m_gvram_read_callback(offset - 0x40000) & 0xff00) >> 8;
- else if (offset >= 0x80000)
- ret = 0xffff;
- break;
- case 0x0000: // 16 colour (paletted) - 4 bits per word
- if (offset < 0x40000)
- ret = m_gvram_read_callback(offset) & 0x000f;
- else if (offset >= 0x40000 && offset < 0x80000)
- ret = (m_gvram_read_callback(offset - 0x40000) & 0x00f0) >> 4;
- else if (offset >= 0x80000 && offset < 0xc0000)
- ret = (m_gvram_read_callback(offset - 0x80000) & 0x0f00) >> 8;
- else if (offset >= 0xc0000 && offset < 0x100000)
- ret = (m_gvram_read_callback(offset - 0xc0000) & 0xf000) >> 12;
- break;
- default:
- logerror("G-VRAM read while layer setup is undefined.\n");
- ret = 0xffff;
- }
-
- return ret;
-}
-
-u16 x68k_crtc_device::tvram_r(offs_t offset)
-{
- return m_tvram_read_callback(offset);
-}