mirror of
https://github.com/holub/mame
synced 2025-06-05 12:26:35 +03:00
x68000: Separate VINAS/VICON CRTC device
- Fix the dot clock divider calculation yet again (nw)
This commit is contained in:
parent
aca2fcf01c
commit
0a6538f9d9
@ -2972,6 +2972,8 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/x68k_hdc.h",
|
||||
MAME_DIR .. "src/mame/machine/x68k_kbd.cpp",
|
||||
MAME_DIR .. "src/mame/machine/x68k_kbd.h",
|
||||
MAME_DIR .. "src/mame/video/x68k_crtc.cpp",
|
||||
MAME_DIR .. "src/mame/video/x68k_crtc.h",
|
||||
MAME_DIR .. "src/mame/drivers/mz80.cpp",
|
||||
MAME_DIR .. "src/mame/includes/mz80.h",
|
||||
MAME_DIR .. "src/mame/video/mz80.cpp",
|
||||
|
@ -170,21 +170,6 @@ void x68k_state::device_timer(emu_timer &timer, device_timer_id id, int param, v
|
||||
case TIMER_X68K_NET_IRQ:
|
||||
x68k_net_irq(ptr, param);
|
||||
break;
|
||||
case TIMER_X68K_CRTC_OPERATION_END:
|
||||
x68k_crtc_operation_end(ptr, param);
|
||||
break;
|
||||
case TIMER_X68K_HSYNC:
|
||||
x68k_hsync(ptr, param);
|
||||
break;
|
||||
case TIMER_X68K_CRTC_RASTER_END:
|
||||
x68k_crtc_raster_end(ptr, param);
|
||||
break;
|
||||
case TIMER_X68K_CRTC_RASTER_IRQ:
|
||||
x68k_crtc_raster_irq(ptr, param);
|
||||
break;
|
||||
case TIMER_X68K_CRTC_VBLANK_IRQ:
|
||||
x68k_crtc_vblank_irq(ptr, param);
|
||||
break;
|
||||
case TIMER_X68K_FDC_TC:
|
||||
m_upd72065->tc_w(ASSERT_LINE);
|
||||
m_upd72065->tc_w(CLEAR_LINE);
|
||||
@ -1129,9 +1114,9 @@ void x68k_state::x68k_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0xbffffb).rw(FUNC(x68k_state::x68k_emptyram_r), FUNC(x68k_state::x68k_emptyram_w));
|
||||
map(0xbffffc, 0xbfffff).rw(FUNC(x68k_state::x68k_rom0_r), FUNC(x68k_state::x68k_rom0_w));
|
||||
map(0xc00000, 0xdfffff).rw(FUNC(x68k_state::x68k_gvram_r), FUNC(x68k_state::x68k_gvram_w));
|
||||
map(0xe00000, 0xe7ffff).rw(FUNC(x68k_state::x68k_tvram_r), FUNC(x68k_state::x68k_tvram_w));
|
||||
map(0xe80000, 0xe81fff).rw(FUNC(x68k_state::x68k_crtc_r), FUNC(x68k_state::x68k_crtc_w));
|
||||
map(0xc00000, 0xdfffff).rw(m_crtc, FUNC(x68k_crtc_device::gvram_r), FUNC(x68k_crtc_device::gvram_w));
|
||||
map(0xe00000, 0xe7ffff).rw(m_crtc, FUNC(x68k_crtc_device::tvram_r), FUNC(x68k_crtc_device::tvram_w));
|
||||
map(0xe80000, 0xe81fff).rw(m_crtc, FUNC(x68k_crtc_device::crtc_r), FUNC(x68k_crtc_device::crtc_w));
|
||||
map(0xe82000, 0xe821ff).rw(m_gfxpalette, FUNC(palette_device::read16), FUNC(palette_device::write16)).share("gfxpalette");
|
||||
map(0xe82200, 0xe823ff).rw(m_pcgpalette, FUNC(palette_device::read16), FUNC(palette_device::write16)).share("pcgpalette");
|
||||
map(0xe82400, 0xe83fff).rw(FUNC(x68k_state::x68k_vid_r), FUNC(x68k_state::x68k_vid_w));
|
||||
@ -1168,9 +1153,9 @@ void x68k_state::x68kxvi_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0xbffffb).rw(FUNC(x68k_state::x68k_emptyram_r), FUNC(x68k_state::x68k_emptyram_w));
|
||||
map(0xbffffc, 0xbfffff).rw(FUNC(x68k_state::x68k_rom0_r), FUNC(x68k_state::x68k_rom0_w));
|
||||
map(0xc00000, 0xdfffff).rw(FUNC(x68k_state::x68k_gvram_r), FUNC(x68k_state::x68k_gvram_w));
|
||||
map(0xe00000, 0xe7ffff).rw(FUNC(x68k_state::x68k_tvram_r), FUNC(x68k_state::x68k_tvram_w));
|
||||
map(0xe80000, 0xe81fff).rw(FUNC(x68k_state::x68k_crtc_r), FUNC(x68k_state::x68k_crtc_w));
|
||||
map(0xc00000, 0xdfffff).rw(m_crtc, FUNC(x68k_crtc_device::gvram_r), FUNC(x68k_crtc_device::gvram_w));
|
||||
map(0xe00000, 0xe7ffff).rw(m_crtc, FUNC(x68k_crtc_device::tvram_r), FUNC(x68k_crtc_device::tvram_w));
|
||||
map(0xe80000, 0xe81fff).rw(m_crtc, FUNC(x68k_crtc_device::crtc_r), FUNC(x68k_crtc_device::crtc_w));
|
||||
map(0xe82000, 0xe821ff).rw(m_gfxpalette, FUNC(palette_device::read16), FUNC(palette_device::write16)).share("gfxpalette");
|
||||
map(0xe82200, 0xe823ff).rw(m_pcgpalette, FUNC(palette_device::read16), FUNC(palette_device::write16)).share("pcgpalette");
|
||||
map(0xe82400, 0xe83fff).rw(FUNC(x68k_state::x68k_vid_r), FUNC(x68k_state::x68k_vid_w));
|
||||
@ -1209,9 +1194,9 @@ void x68k_state::x68030_map(address_map &map)
|
||||
map.global_mask(0x00ffffff); // Still only has 24-bit address space
|
||||
map(0x000000, 0xbffffb).rw(FUNC(x68k_state::x68k_emptyram_r), FUNC(x68k_state::x68k_emptyram_w));
|
||||
map(0xbffffc, 0xbfffff).rw(FUNC(x68k_state::x68k_rom0_r), FUNC(x68k_state::x68k_rom0_w));
|
||||
map(0xc00000, 0xdfffff).rw(FUNC(x68k_state::x68k_gvram_r), FUNC(x68k_state::x68k_gvram_w));
|
||||
map(0xe00000, 0xe7ffff).rw(FUNC(x68k_state::x68k_tvram_r), FUNC(x68k_state::x68k_tvram_w));
|
||||
map(0xe80000, 0xe81fff).rw(FUNC(x68k_state::x68k_crtc_r), FUNC(x68k_state::x68k_crtc_w));
|
||||
map(0xc00000, 0xdfffff).rw(m_crtc, FUNC(x68k_crtc_device::gvram_r), FUNC(x68k_crtc_device::gvram_w));
|
||||
map(0xe00000, 0xe7ffff).rw(m_crtc, FUNC(x68k_crtc_device::tvram_r), FUNC(x68k_crtc_device::tvram_w));
|
||||
map(0xe80000, 0xe81fff).rw(m_crtc, FUNC(x68k_crtc_device::crtc_r), FUNC(x68k_crtc_device::crtc_w));
|
||||
map(0xe82000, 0xe821ff).rw(m_gfxpalette, FUNC(palette_device::read32), FUNC(palette_device::write32)).share("gfxpalette");
|
||||
map(0xe82200, 0xe823ff).rw(m_pcgpalette, FUNC(palette_device::read32), FUNC(palette_device::write32)).share("pcgpalette");
|
||||
map(0xe82400, 0xe83fff).rw(FUNC(x68k_state::x68k_vid_r), FUNC(x68k_state::x68k_vid_w));
|
||||
@ -1282,9 +1267,6 @@ static INPUT_PORTS_START( x68000 )
|
||||
PORT_CONFNAME( 0x02, 0x02, "Enable fake bus errors")
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
||||
PORT_CONFSETTING( 0x02, DEF_STR( On ))
|
||||
PORT_CONFNAME( 0x04, 0x04, "Enable partial updates on each HSync")
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
||||
PORT_CONFSETTING( 0x04, DEF_STR( On ))
|
||||
|
||||
PORT_START("mouse1") // mouse buttons
|
||||
PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON9) PORT_NAME("Left mouse button") PORT_CODE(MOUSECODE_BUTTON1)
|
||||
@ -1492,36 +1474,15 @@ void x68k_state::machine_reset()
|
||||
memset(m_ram->pointer(),0,m_ram->size());
|
||||
memcpy(m_ram->pointer(),romdata,8);
|
||||
|
||||
// initialise CRTC, set registers to defaults for the standard text mode (768x512)
|
||||
m_crtc.reg[0] = 137; // Horizontal total (in characters)
|
||||
m_crtc.reg[1] = 14; // Horizontal sync end
|
||||
m_crtc.reg[2] = 28; // Horizontal start
|
||||
m_crtc.reg[3] = 124; // Horizontal end
|
||||
m_crtc.reg[4] = 567; // Vertical total
|
||||
m_crtc.reg[5] = 5; // Vertical sync end
|
||||
m_crtc.reg[6] = 40; // Vertical start
|
||||
m_crtc.reg[7] = 552; // Vertical end
|
||||
m_crtc.reg[8] = 27; // Horizontal adjust
|
||||
|
||||
m_scanline = m_screen->vpos();// = m_crtc.reg[6]; // Vertical start
|
||||
|
||||
// start VBlank timer
|
||||
m_crtc.vblank = 1;
|
||||
attotime const irq_time = m_screen->time_until_pos(m_crtc.reg[6],2);
|
||||
m_vblank_irq->adjust(irq_time);
|
||||
|
||||
// start HBlank timer
|
||||
m_scanline_timer->adjust(m_screen->scan_period(), 1);
|
||||
|
||||
/// TODO: get callbacks to trigger these
|
||||
m_mfpdev->i0_w(1); // alarm
|
||||
m_mfpdev->i1_w(1); // expon
|
||||
m_mfpdev->i2_w(0); // pow sw
|
||||
m_mfpdev->i3_w(1); // fmirq
|
||||
m_mfpdev->i4_w(1); // v-disp
|
||||
//m_mfpdev->i4_w(1); // v-disp
|
||||
m_mfpdev->i5_w(1); // unused (always set)
|
||||
m_mfpdev->i6_w(1); // cirq
|
||||
m_mfpdev->i7_w(1); // h-sync
|
||||
//m_mfpdev->i6_w(1); // cirq
|
||||
//m_mfpdev->i7_w(1); // h-sync
|
||||
|
||||
// reset output values
|
||||
output().set_value("key_led_kana",1);
|
||||
@ -1591,9 +1552,6 @@ void x68k_state::init_x68000()
|
||||
// copy last half of BIOS to a user region, to use for initial startup
|
||||
memcpy(user2,(rom+0xff0000),0x10000);
|
||||
|
||||
m_scanline_timer = timer_alloc(TIMER_X68K_HSYNC);
|
||||
m_raster_irq = timer_alloc(TIMER_X68K_CRTC_RASTER_IRQ);
|
||||
m_vblank_irq = timer_alloc(TIMER_X68K_CRTC_VBLANK_IRQ);
|
||||
m_mouse_timer = timer_alloc(TIMER_X68K_SCC_ACK);
|
||||
m_led_timer = timer_alloc(TIMER_X68K_LED);
|
||||
m_net_timer = timer_alloc(TIMER_X68K_NET_IRQ);
|
||||
@ -1650,16 +1608,16 @@ MACHINE_CONFIG_START(x68k_state::x68000)
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(60))
|
||||
|
||||
/* device hardware */
|
||||
MCFG_DEVICE_ADD(MC68901_TAG, MC68901, 16_MHz_XTAL / 4)
|
||||
MCFG_DEVICE_ADD("mc68901", MC68901, 16_MHz_XTAL / 4)
|
||||
MCFG_MC68901_TIMER_CLOCK(16_MHz_XTAL / 4)
|
||||
MCFG_MC68901_RX_CLOCK(0)
|
||||
MCFG_MC68901_TX_CLOCK(0)
|
||||
MCFG_MC68901_OUT_IRQ_CB(WRITELINE(*this, x68k_state, mfp_irq_callback))
|
||||
MCFG_MC68901_OUT_TBO_CB(WRITELINE(MC68901_TAG, mc68901_device, clock_w))
|
||||
MCFG_MC68901_OUT_TBO_CB(WRITELINE("mc68901", mc68901_device, clock_w))
|
||||
MCFG_MC68901_OUT_SO_CB(WRITELINE("keyboard", rs232_port_device, write_txd))
|
||||
|
||||
MCFG_DEVICE_ADD("keyboard", RS232_PORT, keyboard, "x68k")
|
||||
MCFG_RS232_RXD_HANDLER(WRITELINE(MC68901_TAG, mc68901_device, write_rx))
|
||||
MCFG_RS232_RXD_HANDLER(WRITELINE("mc68901", mc68901_device, write_rx))
|
||||
|
||||
MCFG_DEVICE_ADD("ppi8255", I8255A, 0)
|
||||
MCFG_I8255_IN_PORTA_CB(READ8(*this, x68k_state, ppi_port_a_r))
|
||||
@ -1678,14 +1636,25 @@ MACHINE_CONFIG_START(x68k_state::x68000)
|
||||
|
||||
MCFG_DEVICE_ADD("scc", SCC8530, 40_MHz_XTAL / 8)
|
||||
|
||||
MCFG_DEVICE_ADD(RP5C15_TAG, RP5C15, 32.768_kHz_XTAL)
|
||||
MCFG_RP5C15_OUT_ALARM_CB(WRITELINE(MC68901_TAG, mc68901_device, i0_w))
|
||||
MCFG_DEVICE_ADD("rp5c15", RP5C15, 32.768_kHz_XTAL)
|
||||
MCFG_RP5C15_OUT_ALARM_CB(WRITELINE("mc68901", mc68901_device, i0_w))
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_RAW_PARAMS(69.55199_MHz_XTAL / 2, 1096, 0, 768, 568, 0, 512) // initial setting
|
||||
MCFG_SCREEN_UPDATE_DRIVER(x68k_state, screen_update_x68000)
|
||||
|
||||
VINAS(config, m_crtc, 38.86363_MHz_XTAL);
|
||||
m_crtc->set_screen("screen");
|
||||
m_crtc->vdisp_cb().set("mc68901", FUNC(mc68901_device::i4_w));
|
||||
m_crtc->vdisp_cb().append("mc68901", FUNC(mc68901_device::tai_w));
|
||||
m_crtc->rint_cb().set("mc68901", FUNC(mc68901_device::i6_w));
|
||||
m_crtc->hsync_cb().set("mc68901", FUNC(mc68901_device::i7_w));
|
||||
m_crtc->tvram_read_cb().set(FUNC(x68k_state::tvram_read));
|
||||
m_crtc->tvram_write_cb().set(FUNC(x68k_state::tvram_write));
|
||||
m_crtc->gvram_read_cb().set(FUNC(x68k_state::gvram_read));
|
||||
m_crtc->gvram_write_cb().set(FUNC(x68k_state::gvram_write));
|
||||
|
||||
MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "pcgpalette", gfxdecode_device::empty)
|
||||
|
||||
MCFG_PALETTE_ADD("gfxpalette", 256)
|
||||
@ -1762,6 +1731,17 @@ MACHINE_CONFIG_START(x68k_state::x68ksupr)
|
||||
MCFG_LEGACY_SCSI_PORT("scsi")
|
||||
MCFG_MB89352A_IRQ_CB(WRITELINE(*this, x68k_state, x68k_scsi_irq))
|
||||
MCFG_MB89352A_DRQ_CB(WRITELINE(*this, x68k_state, x68k_scsi_drq))
|
||||
|
||||
VICON(config.replace(), m_crtc, 38.86363_MHz_XTAL);
|
||||
m_crtc->set_screen("screen");
|
||||
m_crtc->vdisp_cb().set("mc68901", FUNC(mc68901_device::i4_w));
|
||||
m_crtc->vdisp_cb().append("mc68901", FUNC(mc68901_device::tai_w));
|
||||
m_crtc->rint_cb().set("mc68901", FUNC(mc68901_device::i6_w));
|
||||
m_crtc->hsync_cb().set("mc68901", FUNC(mc68901_device::i7_w));
|
||||
m_crtc->tvram_read_cb().set(FUNC(x68k_state::tvram_read));
|
||||
m_crtc->tvram_write_cb().set(FUNC(x68k_state::tvram_write));
|
||||
m_crtc->gvram_read_cb().set(FUNC(x68k_state::gvram_read));
|
||||
m_crtc->gvram_write_cb().set(FUNC(x68k_state::gvram_write));
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(x68k_state::x68kxvi)
|
||||
|
@ -22,14 +22,12 @@
|
||||
#include "sound/flt_vol.h"
|
||||
#include "sound/okim6258.h"
|
||||
#include "sound/ym2151.h"
|
||||
#include "video/x68k_crtc.h"
|
||||
#include "bus/x68k/x68kexp.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define MC68901_TAG "mc68901"
|
||||
#define RP5C15_TAG "rp5c15"
|
||||
|
||||
#define GFX16 0
|
||||
#define GFX256 1
|
||||
#define GFX65536 2
|
||||
@ -43,11 +41,12 @@ public:
|
||||
, m_okim6258(*this, "okim6258")
|
||||
, m_hd63450(*this, "hd63450")
|
||||
, m_ram(*this, RAM_TAG)
|
||||
, m_crtc(*this, "crtc")
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_gfxpalette(*this, "gfxpalette")
|
||||
, m_pcgpalette(*this, "pcgpalette")
|
||||
, m_mfpdev(*this, MC68901_TAG)
|
||||
, m_rtc(*this, RP5C15_TAG)
|
||||
, m_mfpdev(*this, "mc68901")
|
||||
, m_rtc(*this, "rp5c15")
|
||||
, m_scc(*this, "scc")
|
||||
, m_ym2151(*this, "ym2151")
|
||||
, m_ppi(*this, "ppi8255")
|
||||
@ -93,11 +92,6 @@ private:
|
||||
TIMER_MD_6BUTTON_PORT2_TIMEOUT,
|
||||
TIMER_X68K_BUS_ERROR,
|
||||
TIMER_X68K_NET_IRQ,
|
||||
TIMER_X68K_CRTC_OPERATION_END,
|
||||
TIMER_X68K_HSYNC,
|
||||
TIMER_X68K_CRTC_RASTER_END,
|
||||
TIMER_X68K_CRTC_RASTER_IRQ,
|
||||
TIMER_X68K_CRTC_VBLANK_IRQ,
|
||||
TIMER_X68K_FDC_TC,
|
||||
TIMER_X68K_ADPCM
|
||||
};
|
||||
@ -106,6 +100,7 @@ private:
|
||||
required_device<okim6258_device> m_okim6258;
|
||||
required_device<hd63450_device> m_hd63450;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<x68k_crtc_device> m_crtc;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_gfxpalette;
|
||||
required_device<palette_device> m_pcgpalette;
|
||||
@ -182,39 +177,6 @@ private:
|
||||
int clock; // ADPCM clock speed
|
||||
} m_adpcm;
|
||||
struct
|
||||
{
|
||||
unsigned short reg[24]; // registers
|
||||
int operation; // operation port (0xe80481)
|
||||
int vblank; // 1 if in VBlank
|
||||
int hblank; // 1 if in HBlank
|
||||
int htotal; // Horizontal Total (in characters)
|
||||
int vtotal; // Vertical Total
|
||||
int hbegin; // Horizontal Begin
|
||||
int vbegin; // Vertical Begin
|
||||
int hend; // Horizontal End
|
||||
int vend; // Vertical End
|
||||
int hsync_end; // Horizontal Sync End
|
||||
int vsync_end; // Vertical Sync End
|
||||
int hsyncadjust; // Horizontal Sync Adjustment
|
||||
float hmultiple; // Horizontal pixel multiplier
|
||||
float vmultiple; // Vertical scanline multiplier (x2 for doublescan modes)
|
||||
int height;
|
||||
int width;
|
||||
int visible_height;
|
||||
int visible_width;
|
||||
int hshift;
|
||||
int vshift;
|
||||
int video_width; // horizontal total (in pixels)
|
||||
int video_height; // vertical total
|
||||
int bg_visible_height;
|
||||
int bg_visible_width;
|
||||
int bg_hshift;
|
||||
int bg_vshift;
|
||||
int bg_hvres; // bits 0,1 = H-Res, bits 2,3 = V-Res, bit 4 = L/H Freq (0=15.98kHz, 1=31.5kHz)
|
||||
int bg_double; // 1 if PCG is to be doubled.
|
||||
int interlace; // 1024 vertical resolution is interlaced
|
||||
} m_crtc; // CRTC
|
||||
struct
|
||||
{ // video controller at 0xe82000
|
||||
unsigned short reg[3];
|
||||
int text_pri;
|
||||
@ -223,6 +185,12 @@ private:
|
||||
int gfxlayer_pri[4]; // block displayed for each priority level
|
||||
int tile8_dirty[1024];
|
||||
int tile16_dirty[256];
|
||||
int bg_visible_height;
|
||||
int bg_visible_width;
|
||||
int bg_hshift;
|
||||
int bg_vshift;
|
||||
int bg_hvres; // bits 0,1 = H-Res, bits 2,3 = V-Res, bit 4 = L/H Freq (0=15.98kHz, 1=31.5kHz)
|
||||
int bg_double; // 1 if PCG is to be doubled.
|
||||
} m_video;
|
||||
struct
|
||||
{
|
||||
@ -254,7 +222,6 @@ private:
|
||||
uint8_t m_ppi_port[3];
|
||||
int m_current_vector[8];
|
||||
uint8_t m_current_irq_line;
|
||||
unsigned int m_scanline;
|
||||
int m_led_state;
|
||||
emu_timer* m_mouse_timer;
|
||||
emu_timer* m_led_timer;
|
||||
@ -262,9 +229,6 @@ private:
|
||||
unsigned char m_scc_prev;
|
||||
uint16_t m_ppi_prev;
|
||||
int m_mfp_prev;
|
||||
emu_timer* m_scanline_timer;
|
||||
emu_timer* m_raster_irq;
|
||||
emu_timer* m_vblank_irq;
|
||||
emu_timer* m_fdc_tc;
|
||||
emu_timer* m_adpcm_timer;
|
||||
emu_timer* m_bus_error_timer;
|
||||
@ -274,7 +238,6 @@ private:
|
||||
tilemap_t* m_bg0_16;
|
||||
tilemap_t* m_bg1_16;
|
||||
int m_sprite_shift;
|
||||
int m_oddscanline;
|
||||
bool m_is_32bit;
|
||||
|
||||
TILE_GET_INFO_MEMBER(x68k_get_bg0_tile);
|
||||
@ -290,11 +253,6 @@ private:
|
||||
TIMER_CALLBACK_MEMBER(md_6button_port2_timeout);
|
||||
TIMER_CALLBACK_MEMBER(x68k_bus_error);
|
||||
TIMER_CALLBACK_MEMBER(x68k_net_irq);
|
||||
TIMER_CALLBACK_MEMBER(x68k_crtc_operation_end);
|
||||
TIMER_CALLBACK_MEMBER(x68k_hsync);
|
||||
TIMER_CALLBACK_MEMBER(x68k_crtc_raster_end);
|
||||
TIMER_CALLBACK_MEMBER(x68k_crtc_raster_irq);
|
||||
TIMER_CALLBACK_MEMBER(x68k_crtc_vblank_irq);
|
||||
DECLARE_READ8_MEMBER(ppi_port_a_r);
|
||||
DECLARE_READ8_MEMBER(ppi_port_b_r);
|
||||
DECLARE_READ8_MEMBER(ppi_port_c_r);
|
||||
@ -350,22 +308,17 @@ private:
|
||||
DECLARE_WRITE16_MEMBER(x68k_spritereg_w);
|
||||
DECLARE_READ16_MEMBER(x68k_spriteram_r);
|
||||
DECLARE_WRITE16_MEMBER(x68k_spriteram_w);
|
||||
DECLARE_WRITE16_MEMBER(x68k_crtc_w);
|
||||
DECLARE_READ16_MEMBER(x68k_crtc_r);
|
||||
DECLARE_WRITE16_MEMBER(x68k_gvram_w);
|
||||
DECLARE_READ16_MEMBER(x68k_gvram_r);
|
||||
DECLARE_WRITE16_MEMBER(x68k_tvram_w);
|
||||
DECLARE_READ16_MEMBER(x68k_tvram_r);
|
||||
DECLARE_READ16_MEMBER(tvram_read);
|
||||
DECLARE_WRITE16_MEMBER(tvram_write);
|
||||
DECLARE_READ16_MEMBER(gvram_read);
|
||||
DECLARE_WRITE16_MEMBER(gvram_write);
|
||||
IRQ_CALLBACK_MEMBER(x68k_int_ack);
|
||||
|
||||
void x68030_map(address_map &map);
|
||||
void x68k_map(address_map &map);
|
||||
void x68kxvi_map(address_map &map);
|
||||
|
||||
private:
|
||||
inline void x68k_plot_pixel(bitmap_rgb32 &bitmap, int x, int y, uint32_t color);
|
||||
void x68k_crtc_text_copy(int src, int dest, uint8_t planes);
|
||||
void x68k_crtc_refresh_mode();
|
||||
void x68k_draw_text(bitmap_rgb32 &bitmap, int xscr, int yscr, rectangle rect);
|
||||
bool x68k_draw_gfx_scanline(bitmap_ind16 &bitmap, rectangle cliprect, uint8_t priority);
|
||||
void x68k_draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect);
|
||||
|
@ -92,588 +92,71 @@ bitmap_rgb32* ::x68k_get_gfx_page(int pri,int type)
|
||||
return nullptr; // should never reach here either.
|
||||
}
|
||||
*/
|
||||
void x68k_state::x68k_crtc_text_copy(int src, int dest, uint8_t planes)
|
||||
{
|
||||
// copys one raster in T-VRAM to another raster
|
||||
int src_ram = src * 256; // 128 bytes per scanline
|
||||
int dest_ram = dest * 256;
|
||||
|
||||
// update RAM in each plane
|
||||
if(planes & 1)
|
||||
memcpy(&m_tvram[dest_ram],&m_tvram[src_ram],512);
|
||||
if(planes & 2)
|
||||
memcpy(&m_tvram[dest_ram+0x10000],&m_tvram[src_ram+0x10000],512);
|
||||
if(planes & 4)
|
||||
memcpy(&m_tvram[dest_ram+0x20000],&m_tvram[src_ram+0x20000],512);
|
||||
if(planes & 8)
|
||||
memcpy(&m_tvram[dest_ram+0x30000],&m_tvram[src_ram+0x30000],512);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(x68k_state::x68k_crtc_operation_end)
|
||||
{
|
||||
int bit = param;
|
||||
m_crtc.operation &= ~bit;
|
||||
}
|
||||
|
||||
void x68k_state::x68k_crtc_refresh_mode()
|
||||
{
|
||||
// rectangle rect;
|
||||
// double scantime;
|
||||
rectangle scr,visiblescr;
|
||||
int length;
|
||||
|
||||
// Calculate data from register values
|
||||
m_crtc.vmultiple = 1;
|
||||
if((m_crtc.reg[20] & 0x10) != 0 && (m_crtc.reg[20] & 0x0c) == 0)
|
||||
m_crtc.vmultiple = 2; // 31.5kHz + 256 lines = doublescan
|
||||
if(m_crtc.interlace != 0)
|
||||
m_crtc.vmultiple = 0.5f; // 31.5kHz + 1024 lines or 15kHz + 512 lines = interlaced
|
||||
m_crtc.htotal = (m_crtc.reg[0] + 1) * 8;
|
||||
m_crtc.vtotal = (m_crtc.reg[4] + 1) / m_crtc.vmultiple; // default is 567 (568 scanlines)
|
||||
m_crtc.hbegin = (m_crtc.reg[2] * 8) + 1;
|
||||
m_crtc.hend = (m_crtc.reg[3] * 8);
|
||||
m_crtc.vbegin = (m_crtc.reg[6]) / m_crtc.vmultiple;
|
||||
m_crtc.vend = (m_crtc.reg[7] - 1) / m_crtc.vmultiple;
|
||||
if((m_crtc.vmultiple == 2) && !(m_crtc.reg[7] & 1)) // otherwise if the raster irq line == vblank line, the raster irq fires too late
|
||||
m_crtc.vend++;
|
||||
m_crtc.hsync_end = (m_crtc.reg[1]) * 8;
|
||||
m_crtc.vsync_end = (m_crtc.reg[5]) / m_crtc.vmultiple;
|
||||
m_crtc.hsyncadjust = m_crtc.reg[8];
|
||||
scr.set(0, m_crtc.htotal - 8, 0, m_crtc.vtotal);
|
||||
if(scr.max_y <= m_crtc.vend)
|
||||
scr.max_y = m_crtc.vend + 2;
|
||||
if(scr.max_x <= m_crtc.hend)
|
||||
scr.max_x = m_crtc.hend + 2;
|
||||
visiblescr.set(m_crtc.hbegin, m_crtc.hend, m_crtc.vbegin, m_crtc.vend);
|
||||
|
||||
// expand visible area to the size indicated by CRTC reg 20
|
||||
length = m_crtc.hend - m_crtc.hbegin;
|
||||
if (length < m_crtc.width)
|
||||
{
|
||||
visiblescr.min_x = m_crtc.hbegin - ((m_crtc.width - length)/2);
|
||||
visiblescr.max_x = m_crtc.hend + ((m_crtc.width - length)/2);
|
||||
}
|
||||
length = m_crtc.vend - m_crtc.vbegin;
|
||||
if (length < m_crtc.height)
|
||||
{
|
||||
visiblescr.min_y = m_crtc.vbegin - ((m_crtc.height - length)/2);
|
||||
visiblescr.max_y = m_crtc.vend + ((m_crtc.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_crtc.reg[0],m_crtc.reg[1],m_crtc.reg[2],m_crtc.reg[3],
|
||||
// m_crtc.reg[4],m_crtc.reg[5],m_crtc.reg[6],m_crtc.reg[7],m_crtc.reg[8],m_crtc.reg[9]);
|
||||
unsigned div = (m_crtc.reg[20] & 0x03) == 0 ? 4 : 2;
|
||||
if ((m_crtc.reg[20] & 0x0c) == 0)
|
||||
div *= BIT(m_crtc.reg[20], 4) ? 3 : 2;
|
||||
attotime refresh = attotime::from_ticks(scr.max_x * scr.max_y, (BIT(m_crtc.reg[20], 4) ? 69.55199_MHz_XTAL : 38.86363_MHz_XTAL) / div);
|
||||
LOG("m_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, ATTOSECONDS_TO_HZ(refresh.as_attoseconds()));
|
||||
m_screen->configure(scr.max_x, scr.max_y, visiblescr, refresh.as_attoseconds());
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(x68k_state::x68k_hsync)
|
||||
{
|
||||
int hstate = param;
|
||||
attotime hsync_time;
|
||||
|
||||
m_crtc.hblank = hstate;
|
||||
m_mfpdev->i7_w(!m_crtc.hblank);
|
||||
|
||||
if(m_crtc.operation & 8)
|
||||
x68k_crtc_text_copy((m_crtc.reg[22] & 0xff00) >> 8,(m_crtc.reg[22] & 0x00ff),(m_crtc.reg[21] & 0xf));
|
||||
|
||||
if(m_crtc.vmultiple == 2) // 256-line (doublescan)
|
||||
{
|
||||
if(hstate == 1)
|
||||
{
|
||||
if(m_oddscanline == 1)
|
||||
{
|
||||
int scan = m_screen->vpos();
|
||||
if(scan > m_crtc.vend)
|
||||
scan = m_crtc.vbegin;
|
||||
hsync_time = m_screen->time_until_pos(scan,(m_crtc.htotal + m_crtc.hend) / 2);
|
||||
m_scanline_timer->adjust(hsync_time);
|
||||
if(scan != 0)
|
||||
{
|
||||
if((ioport("options")->read() & 0x04))
|
||||
{
|
||||
m_screen->update_partial(scan);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int scan = m_screen->vpos();
|
||||
if(scan > m_crtc.vend)
|
||||
scan = m_crtc.vbegin;
|
||||
hsync_time = m_screen->time_until_pos(scan,m_crtc.hend / 2);
|
||||
m_scanline_timer->adjust(hsync_time);
|
||||
if(scan != 0)
|
||||
{
|
||||
if((ioport("options")->read() & 0x04))
|
||||
{
|
||||
m_screen->update_partial(scan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(hstate == 0)
|
||||
{
|
||||
if(m_oddscanline == 1)
|
||||
{
|
||||
int scan = m_screen->vpos();
|
||||
if(scan > m_crtc.vend)
|
||||
scan = m_crtc.vbegin;
|
||||
else
|
||||
scan++;
|
||||
hsync_time = m_screen->time_until_pos(scan,m_crtc.hbegin / 2);
|
||||
m_scanline_timer->adjust(hsync_time, 1);
|
||||
m_oddscanline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsync_time = m_screen->time_until_pos(m_screen->vpos(),(m_crtc.htotal + m_crtc.hbegin) / 2);
|
||||
m_scanline_timer->adjust(hsync_time, 1);
|
||||
m_oddscanline = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 512-line
|
||||
{
|
||||
if(hstate == 1)
|
||||
{
|
||||
int scan = m_screen->vpos();
|
||||
if(scan > m_crtc.vend)
|
||||
scan = 0;
|
||||
hsync_time = m_screen->time_until_pos(scan,m_crtc.hend);
|
||||
m_scanline_timer->adjust(hsync_time);
|
||||
if(scan != 0)
|
||||
{
|
||||
if((ioport("options")->read() & 0x04))
|
||||
{
|
||||
m_screen->update_partial(scan);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(hstate == 0)
|
||||
{
|
||||
hsync_time = m_screen->time_until_pos(m_screen->vpos()+1,m_crtc.hbegin);
|
||||
m_scanline_timer->adjust(hsync_time, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(x68k_state::x68k_crtc_raster_end)
|
||||
{
|
||||
m_mfpdev->i6_w(1);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(x68k_state::x68k_crtc_raster_irq)
|
||||
{
|
||||
int scan = param;
|
||||
attotime irq_time;
|
||||
attotime end_time;
|
||||
|
||||
if(scan <= m_crtc.vtotal)
|
||||
{
|
||||
m_mfpdev->i6_w(0);
|
||||
m_screen->update_partial(scan);
|
||||
irq_time = m_screen->time_until_pos(scan,m_crtc.hbegin);
|
||||
// end of HBlank period clears GPIP6 also?
|
||||
end_time = m_screen->time_until_pos(scan,m_crtc.hend);
|
||||
m_raster_irq->adjust(irq_time, scan);
|
||||
timer_set(end_time, TIMER_X68K_CRTC_RASTER_END);
|
||||
LOG("GPIP6: Raster triggered at line %i (%i)\n",scan,m_screen->vpos());
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(x68k_state::x68k_crtc_vblank_irq)
|
||||
{
|
||||
int val = param;
|
||||
attotime irq_time;
|
||||
int vblank_line;
|
||||
|
||||
if(val == 1) // V-DISP on
|
||||
{
|
||||
m_crtc.vblank = 1;
|
||||
vblank_line = m_crtc.vbegin;
|
||||
irq_time = m_screen->time_until_pos(vblank_line,2);
|
||||
m_vblank_irq->adjust(irq_time);
|
||||
LOG("CRTC: VBlank on\n");
|
||||
}
|
||||
if(val == 0) // V-DISP off
|
||||
{
|
||||
m_crtc.vblank = 0;
|
||||
vblank_line = m_crtc.vend;
|
||||
if(vblank_line > m_crtc.vtotal)
|
||||
vblank_line = m_crtc.vtotal;
|
||||
irq_time = m_screen->time_until_pos(vblank_line,2);
|
||||
m_vblank_irq->adjust(irq_time, 1);
|
||||
LOG("CRTC: VBlank off\n");
|
||||
}
|
||||
|
||||
m_mfpdev->tai_w(!m_crtc.vblank);
|
||||
m_mfpdev->i4_w(!m_crtc.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.
|
||||
*/
|
||||
WRITE16_MEMBER(x68k_state::x68k_crtc_w )
|
||||
{
|
||||
if (offset < 0x24)
|
||||
COMBINE_DATA(m_crtc.reg+offset);
|
||||
switch(offset)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
x68k_crtc_refresh_mode();
|
||||
break;
|
||||
case 9: // CRTC raster IRQ (GPIP6)
|
||||
{
|
||||
attotime irq_time;
|
||||
data = m_crtc.reg[9];
|
||||
irq_time = m_screen->time_until_pos((data) / m_crtc.vmultiple,2);
|
||||
|
||||
if(data != m_screen->vpos())
|
||||
m_mfpdev->i6_w(1);
|
||||
if(irq_time.as_double() > 0)
|
||||
m_raster_irq->adjust(irq_time, (data) / m_crtc.vmultiple);
|
||||
}
|
||||
LOG("CRTC: Write to raster IRQ register - %i\n",data);
|
||||
break;
|
||||
case 20:
|
||||
if(ACCESSING_BITS_0_7)
|
||||
{
|
||||
m_crtc.interlace = 0;
|
||||
switch(data & 0x0c)
|
||||
{
|
||||
case 0x00:
|
||||
m_crtc.height = 256;
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x0c: // TODO: 1024 vertical, if horizontal freq = 31kHz
|
||||
m_crtc.height = 512;
|
||||
m_crtc.interlace = 1; // if 31kHz, 1024 lines = interlaced
|
||||
break;
|
||||
case 0x04:
|
||||
m_crtc.height = 512;
|
||||
if(!(m_crtc.reg[20] & 0x0010)) // if 15kHz, 512 lines = interlaced
|
||||
m_crtc.interlace = 1;
|
||||
break;
|
||||
}
|
||||
switch(data & 0x03)
|
||||
{
|
||||
case 0x00:
|
||||
m_crtc.width = 256;
|
||||
break;
|
||||
case 0x01:
|
||||
m_crtc.width = 512;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03: // 0x03 = 50MHz clock mode (XVI only)
|
||||
m_crtc.width = 768;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* if(ACCESSING_BITS_8_15)
|
||||
{
|
||||
m_crtc.interlace = 0;
|
||||
if(data & 0x0400)
|
||||
m_crtc.interlace = 1;
|
||||
}*/
|
||||
logerror("CRTC: Register 20 = %04x\n", m_crtc.reg[20]);
|
||||
x68k_crtc_refresh_mode();
|
||||
break;
|
||||
case 576: // operation register
|
||||
m_crtc.operation = data;
|
||||
if(data & 0x02) // high-speed graphic screen clear
|
||||
{
|
||||
memset(&m_gvram[0],0,0x40000);
|
||||
timer_set(attotime::from_msec(10), TIMER_X68K_CRTC_OPERATION_END, 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);
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_state::x68k_crtc_r )
|
||||
{
|
||||
if(offset < 24)
|
||||
{
|
||||
// LOG("%s CRTC: Read %04x from CRTC register %i\n",machine().describe_context(),m_crtc.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_crtc.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_crtc.reg[offset] & 0x1ff;
|
||||
default:
|
||||
return m_crtc.reg[offset];
|
||||
}
|
||||
}
|
||||
if(offset == 576) // operation port, operation bits are set to 0 when operation is complete
|
||||
return m_crtc.operation;
|
||||
// LOG("CRTC: [%08x] Read from unknown CRTC register %i\n",activecpu_get_pc(),offset);
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_state::x68k_gvram_w )
|
||||
{
|
||||
// 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_crtc.reg[20] & 0x0800) // G-VRAM set to buffer
|
||||
{
|
||||
if(offset < 0x40000)
|
||||
COMBINE_DATA(&m_gvram[offset]);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_crtc.reg[20] & 0x0300)
|
||||
{
|
||||
case 0x0300:
|
||||
if(offset < 0x40000)
|
||||
COMBINE_DATA(&m_gvram[offset]);
|
||||
break;
|
||||
case 0x0100:
|
||||
if(offset < 0x40000)
|
||||
{
|
||||
m_gvram[offset] = (m_gvram[offset] & 0xff00) | (data & 0x00ff);
|
||||
}
|
||||
if(offset >= 0x40000 && offset < 0x80000)
|
||||
{
|
||||
m_gvram[offset-0x40000] = (m_gvram[offset-0x40000] & 0x00ff) | ((data & 0x00ff) << 8);
|
||||
}
|
||||
break;
|
||||
case 0x0000:
|
||||
if(offset < 0x40000)
|
||||
{
|
||||
m_gvram[offset] = (m_gvram[offset] & 0xfff0) | (data & 0x000f);
|
||||
}
|
||||
if(offset >= 0x40000 && offset < 0x80000)
|
||||
{
|
||||
m_gvram[offset-0x40000] = (m_gvram[offset-0x40000] & 0xff0f) | ((data & 0x000f) << 4);
|
||||
}
|
||||
if(offset >= 0x80000 && offset < 0xc0000)
|
||||
{
|
||||
m_gvram[offset-0x80000] = (m_gvram[offset-0x80000] & 0xf0ff) | ((data & 0x000f) << 8);
|
||||
}
|
||||
if(offset >= 0xc0000 && offset < 0x100000)
|
||||
{
|
||||
m_gvram[offset-0xc0000] = (m_gvram[offset-0xc0000] & 0x0fff) | ((data & 0x000f) << 12);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logerror("G-VRAM written while layer setup is undefined.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_state::x68k_tvram_w )
|
||||
{
|
||||
uint16_t text_mask;
|
||||
|
||||
text_mask = ~(m_crtc.reg[23]) & mem_mask;
|
||||
|
||||
if(!(m_crtc.reg[21] & 0x0200)) // text access mask enable
|
||||
text_mask = 0xffff & mem_mask;
|
||||
|
||||
mem_mask = text_mask;
|
||||
|
||||
if(m_crtc.reg[21] & 0x0100)
|
||||
{ // simultaneous T-VRAM plane access (I think ;))
|
||||
int plane,wr;
|
||||
offset = offset & 0x00ffff;
|
||||
wr = (m_crtc.reg[21] & 0x00f0) >> 4;
|
||||
for(plane=0;plane<4;plane++)
|
||||
{
|
||||
if(wr & (1 << plane))
|
||||
{
|
||||
COMBINE_DATA(&m_tvram[offset+0x10000*plane]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMBINE_DATA(&m_tvram[offset]);
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_state::x68k_gvram_r )
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
|
||||
if(m_crtc.reg[20] & 0x0800) // G-VRAM set to buffer
|
||||
return m_gvram[offset];
|
||||
|
||||
switch(m_crtc.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[offset];
|
||||
else
|
||||
ret = 0xffff;
|
||||
break;
|
||||
case 0x0100: // 256 colour (paletted) - 8 bits per word
|
||||
if(offset < 0x40000)
|
||||
ret = m_gvram[offset] & 0x00ff;
|
||||
if(offset >= 0x40000 && offset < 0x80000)
|
||||
ret = (m_gvram[offset-0x40000] & 0xff00) >> 8;
|
||||
if(offset >= 0x80000)
|
||||
ret = 0xffff;
|
||||
break;
|
||||
case 0x0000: // 16 colour (paletted) - 4 bits per word
|
||||
if(offset < 0x40000)
|
||||
ret = m_gvram[offset] & 0x000f;
|
||||
if(offset >= 0x40000 && offset < 0x80000)
|
||||
ret = (m_gvram[offset-0x40000] & 0x00f0) >> 4;
|
||||
if(offset >= 0x80000 && offset < 0xc0000)
|
||||
ret = (m_gvram[offset-0x80000] & 0x0f00) >> 8;
|
||||
if(offset >= 0xc0000 && offset < 0x100000)
|
||||
ret = (m_gvram[offset-0xc0000] & 0xf000) >> 12;
|
||||
break;
|
||||
default:
|
||||
logerror("G-VRAM read while layer setup is undefined.\n");
|
||||
ret = 0xffff;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_state::x68k_tvram_r )
|
||||
READ16_MEMBER(x68k_state::tvram_read)
|
||||
{
|
||||
return m_tvram[offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_state::tvram_write)
|
||||
{
|
||||
COMBINE_DATA(&m_tvram[offset]);
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_state::gvram_read)
|
||||
{
|
||||
return m_gvram[offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_state::gvram_write)
|
||||
{
|
||||
COMBINE_DATA(&m_gvram[offset]);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_state::x68k_spritereg_w )
|
||||
{
|
||||
COMBINE_DATA(&m_spritereg[offset]);
|
||||
switch(offset)
|
||||
{
|
||||
case 0x400:
|
||||
m_bg0_8->set_scrollx(0,(data - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
m_bg0_16->set_scrollx(0,(data - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
m_bg0_8->set_scrollx(0,(data - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
m_bg0_16->set_scrollx(0,(data - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
break;
|
||||
case 0x401:
|
||||
m_bg0_8->set_scrolly(0,(data - m_crtc.vbegin) & 0x3ff);
|
||||
m_bg0_16->set_scrolly(0,(data - m_crtc.vbegin) & 0x3ff);
|
||||
m_bg0_8->set_scrolly(0,(data - m_crtc->vbegin()) & 0x3ff);
|
||||
m_bg0_16->set_scrolly(0,(data - m_crtc->vbegin()) & 0x3ff);
|
||||
break;
|
||||
case 0x402:
|
||||
m_bg1_8->set_scrollx(0,(data - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
m_bg1_16->set_scrollx(0,(data - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
m_bg1_8->set_scrollx(0,(data - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
m_bg1_16->set_scrollx(0,(data - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
break;
|
||||
case 0x403:
|
||||
m_bg1_8->set_scrolly(0,(data - m_crtc.vbegin) & 0x3ff);
|
||||
m_bg1_16->set_scrolly(0,(data - m_crtc.vbegin) & 0x3ff);
|
||||
m_bg1_8->set_scrolly(0,(data - m_crtc->vbegin()) & 0x3ff);
|
||||
m_bg1_16->set_scrolly(0,(data - m_crtc->vbegin()) & 0x3ff);
|
||||
break;
|
||||
case 0x406: // BG H-DISP (normally equals CRTC reg 2 value + 4)
|
||||
if(data != 0x00ff)
|
||||
{
|
||||
m_crtc.bg_visible_width = (m_crtc.reg[3] - ((data & 0x003f) - 4)) * 8;
|
||||
m_crtc.bg_hshift = ((data - (m_crtc.reg[2]+4)) * 8);
|
||||
if(m_crtc.bg_hshift > 0)
|
||||
m_crtc.bg_hshift = 0;
|
||||
m_video.bg_visible_width = m_crtc->hend() - ((data & 0x003f) - 4) * 8;
|
||||
m_video.bg_hshift = ((data - 4) * 8) - (m_crtc->hbegin() - 1);
|
||||
if(m_video.bg_hshift > 0)
|
||||
m_video.bg_hshift = 0;
|
||||
}
|
||||
break;
|
||||
case 0x407: // BG V-DISP (like CRTC reg 6)
|
||||
m_crtc.bg_vshift = m_crtc.vshift;
|
||||
m_video.bg_vshift = m_crtc->vshift();
|
||||
break;
|
||||
case 0x408: // BG H/V-Res
|
||||
m_crtc.bg_hvres = data & 0x1f;
|
||||
m_video.bg_hvres = data & 0x1f;
|
||||
if(data != 0xff)
|
||||
{ // Handle when the PCG is using 256 and the CRTC is using 512
|
||||
if((m_crtc.bg_hvres & 0x0c) == 0x00 && (m_crtc.reg[20] & 0x0c) == 0x04)
|
||||
m_crtc.bg_double = 2;
|
||||
if((m_video.bg_hvres & 0x0c) == 0x00 && m_crtc->vfactor() == 1)
|
||||
m_video.bg_double = 2;
|
||||
else
|
||||
m_crtc.bg_double = 1;
|
||||
m_video.bg_double = 1;
|
||||
}
|
||||
else
|
||||
m_crtc.bg_double = 1;
|
||||
m_video.bg_double = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -724,7 +207,7 @@ void x68k_state::x68k_draw_text(bitmap_rgb32 &bitmap, int xscr, int yscr, rectan
|
||||
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()) + yscr) & 0x3ff) * 64;
|
||||
loc += (xscr / 16) & 0x7f;
|
||||
loc &= 0xffff;
|
||||
bit = 15 - (xscr & 0x0f);
|
||||
@ -763,16 +246,16 @@ bool x68k_state::x68k_draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprec
|
||||
|
||||
for(scanline=cliprect.min_y;scanline<=cliprect.max_y;scanline++) // per scanline
|
||||
{
|
||||
if(m_crtc.reg[20] & 0x0400) // 1024x1024 "real" screen size - use 1024x1024 16-colour gfx layer
|
||||
if(m_crtc->is_1024x1024()) // 1024x1024 "real" screen size - use 1024x1024 16-colour gfx layer
|
||||
{
|
||||
// adjust for scroll registers
|
||||
if(m_video.reg[2] & 0x0010 && priority == m_video.gfxlayer_pri[0])
|
||||
{
|
||||
xscr = (m_crtc.reg[12] & 0x3ff);
|
||||
yscr = (m_crtc.reg[13] & 0x3ff);
|
||||
lineoffset = (((scanline - m_crtc.vbegin) + yscr) & 0x3ff) * 1024;
|
||||
xscr = (m_crtc->xscr_gfx(0) & 0x3ff);
|
||||
yscr = (m_crtc->yscr_gfx(0) & 0x3ff);
|
||||
lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x3ff) * 1024;
|
||||
loc = xscr & 0x3ff;
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
switch(lineoffset & 0xc0000)
|
||||
{
|
||||
@ -810,14 +293,14 @@ bool x68k_state::x68k_draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprec
|
||||
switch(m_video.reg[0] & 0x03)
|
||||
{
|
||||
case 0x00: // 16 colours
|
||||
xscr = ((m_crtc.reg[12+(page*2)])) & 0x1ff;
|
||||
yscr = ((m_crtc.reg[13+(page*2)])) & 0x1ff;
|
||||
lineoffset = (((scanline - m_crtc.vbegin) + yscr) & 0x1ff) * 512;
|
||||
xscr = m_crtc->xscr_gfx(page) & 0x1ff;
|
||||
yscr = m_crtc->yscr_gfx(page) & 0x1ff;
|
||||
lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x1ff) * 512;
|
||||
loc = xscr & 0x1ff;
|
||||
shift = 4;
|
||||
if((m_video.reg[2] & 0x1a00) == 0x1a00)
|
||||
ret = true;
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
colour = ((m_gvram[lineoffset + loc] >> page*shift) & 0x000f);
|
||||
if(ret && (colour & 1))
|
||||
@ -848,14 +331,14 @@ bool x68k_state::x68k_draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprec
|
||||
case 0x01: // 256 colours
|
||||
if(page == 0 || page == 2)
|
||||
{
|
||||
xscr = ((m_crtc.reg[12+(page*2)])) & 0x1ff;
|
||||
yscr = ((m_crtc.reg[13+(page*2)])) & 0x1ff;
|
||||
lineoffset = (((scanline - m_crtc.vbegin) + yscr) & 0x1ff) * 512;
|
||||
xscr = m_crtc->xscr_gfx(page) & 0x1ff;
|
||||
yscr = m_crtc->yscr_gfx(page) & 0x1ff;
|
||||
lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x1ff) * 512;
|
||||
loc = xscr & 0x1ff;
|
||||
shift = 4;
|
||||
if((m_video.reg[2] & 0x1a00) == 0x1a00)
|
||||
ret = true;
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
colour = ((m_gvram[lineoffset + loc] >> page*shift) & 0x00ff);
|
||||
if(ret && (colour & 1))
|
||||
@ -885,11 +368,11 @@ bool x68k_state::x68k_draw_gfx_scanline( bitmap_ind16 &bitmap, rectangle cliprec
|
||||
}
|
||||
break;
|
||||
case 0x03: // 65536 colours
|
||||
xscr = ((m_crtc.reg[12])) & 0x1ff;
|
||||
yscr = ((m_crtc.reg[13])) & 0x1ff;
|
||||
lineoffset = (((scanline - m_crtc.vbegin) + yscr) & 0x1ff) * 512;
|
||||
xscr = m_crtc->xscr_gfx(0) & 0x1ff;
|
||||
yscr = m_crtc->yscr_gfx(0) & 0x1ff;
|
||||
lineoffset = (((scanline - m_crtc->vbegin()) + yscr) & 0x1ff) * 512;
|
||||
loc = xscr & 0x1ff;
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
colour = m_gvram[lineoffset + loc];
|
||||
if(colour || (priority == 3))
|
||||
@ -913,7 +396,7 @@ void x68k_state::x68k_draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect)
|
||||
//int xscr,yscr;
|
||||
//int gpage;
|
||||
|
||||
if(m_crtc.reg[20] & 0x0800) // if graphic layers are set to buffer, then they aren't visible
|
||||
if(m_crtc->gfx_layer_buffer()) // if graphic layers are set to buffer, then they aren't visible
|
||||
return;
|
||||
|
||||
m_gfxbitmap.fill(0, cliprect);
|
||||
@ -929,7 +412,7 @@ void x68k_state::x68k_draw_gfx(bitmap_rgb32 &bitmap,rectangle cliprect)
|
||||
{
|
||||
uint16_t colour;
|
||||
bool blend = false;
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
if((m_video.reg[0] & 0x03) == 3)
|
||||
{
|
||||
@ -1024,15 +507,15 @@ void x68k_state::x68k_draw_sprites(bitmap_ind16 &bitmap, int priority, rectangle
|
||||
int sx = (m_spritereg[ptr+0] & 0x3ff) - 16;
|
||||
int sy = (m_spritereg[ptr+1] & 0x3ff) - 16;
|
||||
|
||||
rect.min_x=m_crtc.hshift;
|
||||
rect.min_y=m_crtc.vshift;
|
||||
rect.max_x=rect.min_x + m_crtc.visible_width-1;
|
||||
rect.max_y=rect.min_y + m_crtc.visible_height-1;
|
||||
rect.min_x=m_crtc->hshift();
|
||||
rect.min_y=m_crtc->vshift();
|
||||
rect.max_x=rect.min_x + m_crtc->visible_width()-1;
|
||||
rect.max_y=rect.min_y + m_crtc->visible_height()-1;
|
||||
|
||||
sx += m_crtc.bg_hshift;
|
||||
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_crtc.bg_double),0x10000,0x10000*m_crtc.bg_double,0x00);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1147,19 +630,19 @@ uint32_t x68k_state::screen_update_x68000(screen_device &screen, bitmap_rgb32 &b
|
||||
x68k_bg0 = m_bg0_16;
|
||||
x68k_bg1 = m_bg1_16;
|
||||
}
|
||||
// rect.max_x=m_crtc.width;
|
||||
// rect.max_y=m_crtc.height;
|
||||
// rect.max_x=m_crtc->width();
|
||||
// rect.max_y=m_crtc->height();
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
if(m_sysport.contrast == 0) // if monitor contrast is 0, then don't bother displaying anything
|
||||
return 0;
|
||||
|
||||
rect.min_x=m_crtc.hbegin;
|
||||
rect.min_y=m_crtc.vbegin;
|
||||
// rect.max_x=rect.min_x + m_crtc.visible_width-1;
|
||||
// rect.max_y=rect.min_y + m_crtc.visible_height-1;
|
||||
rect.max_x=m_crtc.hend;
|
||||
rect.max_y=m_crtc.vend;
|
||||
rect.min_x=m_crtc->hbegin();
|
||||
rect.min_y=m_crtc->vbegin();
|
||||
// rect.max_x=rect.min_x + m_crtc->visible_width()-1;
|
||||
// rect.max_y=rect.min_y + m_crtc->visible_height()-1;
|
||||
rect.max_x=m_crtc->hend();
|
||||
rect.max_y=m_crtc->vend();
|
||||
|
||||
if(rect.min_y < cliprect.min_y)
|
||||
rect.min_y = cliprect.min_y;
|
||||
@ -1198,14 +681,14 @@ uint32_t x68k_state::screen_update_x68000(screen_device &screen, bitmap_rgb32 &b
|
||||
{
|
||||
if((m_spritereg[0x404] & 0x0030) == 0x10) // BG1 TXSEL
|
||||
{
|
||||
x68k_bg0->set_scrollx(0,(m_spritereg[0x402] - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
x68k_bg0->set_scrolly(0,(m_spritereg[0x403] - m_crtc.vbegin) & 0x3ff);
|
||||
x68k_bg0->set_scrollx(0,(m_spritereg[0x402] - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
x68k_bg0->set_scrolly(0,(m_spritereg[0x403] - m_crtc->vbegin()) & 0x3ff);
|
||||
x68k_bg0->draw(screen, m_pcgbitmap,rect,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
x68k_bg1->set_scrollx(0,(m_spritereg[0x402] - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
x68k_bg1->set_scrolly(0,(m_spritereg[0x403] - m_crtc.vbegin) & 0x3ff);
|
||||
x68k_bg1->set_scrollx(0,(m_spritereg[0x402] - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
x68k_bg1->set_scrolly(0,(m_spritereg[0x403] - m_crtc->vbegin()) & 0x3ff);
|
||||
x68k_bg1->draw(screen, m_pcgbitmap,rect,0,0);
|
||||
}
|
||||
}
|
||||
@ -1214,14 +697,14 @@ uint32_t x68k_state::screen_update_x68000(screen_device &screen, bitmap_rgb32 &b
|
||||
{
|
||||
if((m_spritereg[0x404] & 0x0006) == 0x02) // BG0 TXSEL
|
||||
{
|
||||
x68k_bg0->set_scrollx(0,(m_spritereg[0x400] - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
x68k_bg0->set_scrolly(0,(m_spritereg[0x401] - m_crtc.vbegin) & 0x3ff);
|
||||
x68k_bg0->set_scrollx(0,(m_spritereg[0x400] - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
x68k_bg0->set_scrolly(0,(m_spritereg[0x401] - m_crtc->vbegin()) & 0x3ff);
|
||||
x68k_bg0->draw(screen, m_pcgbitmap,rect,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
x68k_bg1->set_scrollx(0,(m_spritereg[0x400] - m_crtc.hbegin - m_crtc.bg_hshift) & 0x3ff);
|
||||
x68k_bg1->set_scrolly(0,(m_spritereg[0x401] - m_crtc.vbegin) & 0x3ff);
|
||||
x68k_bg1->set_scrollx(0,(m_spritereg[0x400] - m_crtc->hbegin() - m_video.bg_hshift) & 0x3ff);
|
||||
x68k_bg1->set_scrolly(0,(m_spritereg[0x401] - m_crtc->vbegin()) & 0x3ff);
|
||||
x68k_bg1->draw(screen, m_pcgbitmap,rect,0,0);
|
||||
}
|
||||
}
|
||||
@ -1229,7 +712,7 @@ uint32_t x68k_state::screen_update_x68000(screen_device &screen, bitmap_rgb32 &b
|
||||
|
||||
for(scanline=rect.min_y;scanline<=rect.max_y;scanline++)
|
||||
{
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
uint8_t colour = m_pcgbitmap.pix16(scanline, pixel) & 0xff;
|
||||
if((colour && (m_pcgpalette->pen(colour) & 0xffffff)) || ((m_video.reg[1] & 0x3000) == 0x2000))
|
||||
@ -1241,9 +724,9 @@ uint32_t x68k_state::screen_update_x68000(screen_device &screen, bitmap_rgb32 &b
|
||||
// Text screen
|
||||
if(m_video.reg[2] & 0x0020 && priority == m_video.text_pri)
|
||||
{
|
||||
xscr = (m_crtc.reg[10] & 0x3ff);
|
||||
yscr = (m_crtc.reg[11] & 0x3ff);
|
||||
if(!(m_crtc.reg[20] & 0x1000)) // if text layer is set to buffer, then it's not visible
|
||||
xscr = (m_crtc->xscr_text() & 0x3ff);
|
||||
yscr = (m_crtc->yscr_text() & 0x3ff);
|
||||
if(!m_crtc->text_layer_buffer()) // if text layer is set to buffer, then it's not visible
|
||||
x68k_draw_text(bitmap,xscr,yscr,rect);
|
||||
}
|
||||
}
|
||||
@ -1253,7 +736,7 @@ uint32_t x68k_state::screen_update_x68000(screen_device &screen, bitmap_rgb32 &b
|
||||
uint16_t colour;
|
||||
for(scanline=rect.min_y;scanline<=rect.max_y;scanline++)
|
||||
{
|
||||
for(pixel=m_crtc.hbegin;pixel<=m_crtc.hend;pixel++)
|
||||
for(pixel=m_crtc->hbegin();pixel<=m_crtc->hend();pixel++)
|
||||
{
|
||||
colour = m_special.pix16(scanline, pixel) & 0xff;
|
||||
if(colour)
|
||||
|
642
src/mame/video/x68k_crtc.cpp
Normal file
642
src/mame/video/x68k_crtc.cpp
Normal file
@ -0,0 +1,642 @@
|
||||
// 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_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_ticks(scr.max_x * scr.max_y, (BIT(m_reg[20], 4) ? 69.55199_MHz_XTAL : 38.86363_MHz_XTAL) / div);
|
||||
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, ATTOSECONDS_TO_HZ(refresh.as_attoseconds()));
|
||||
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.
|
||||
*/
|
||||
WRITE16_MEMBER(x68k_crtc_device::crtc_w)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_crtc_device::crtc_r)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_crtc_device::gvram_w)
|
||||
{
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(x68k_crtc_device::tvram_w)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_crtc_device::gvram_r)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
READ16_MEMBER(x68k_crtc_device::tvram_r)
|
||||
{
|
||||
return m_tvram_read_callback(offset, mem_mask);
|
||||
}
|
124
src/mame/video/x68k_crtc.h
Normal file
124
src/mame/video/x68k_crtc.h
Normal file
@ -0,0 +1,124 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Barry Rodewald,Carl
|
||||
|
||||
#ifndef MAME_VIDEO_X68K_CRTC_H
|
||||
#define MAME_VIDEO_X68K_CRTC_H
|
||||
|
||||
class x68k_crtc_device : public device_t, public device_video_interface
|
||||
{
|
||||
public:
|
||||
// device configuration
|
||||
auto vdisp_cb() { return m_vdisp_callback.bind(); }
|
||||
auto rint_cb() { return m_rint_callback.bind(); }
|
||||
auto hsync_cb() { return m_hsync_callback.bind(); }
|
||||
auto tvram_read_cb() { return m_tvram_read_callback.bind(); }
|
||||
auto tvram_write_cb() { return m_tvram_write_callback.bind(); }
|
||||
auto gvram_read_cb() { return m_gvram_read_callback.bind(); }
|
||||
auto gvram_write_cb() { return m_gvram_write_callback.bind(); }
|
||||
// TODO: XTAL clocks
|
||||
|
||||
DECLARE_WRITE16_MEMBER(crtc_w);
|
||||
DECLARE_READ16_MEMBER(crtc_r);
|
||||
DECLARE_WRITE16_MEMBER(gvram_w);
|
||||
DECLARE_READ16_MEMBER(gvram_r);
|
||||
DECLARE_WRITE16_MEMBER(tvram_w);
|
||||
DECLARE_READ16_MEMBER(tvram_r);
|
||||
|
||||
// getters
|
||||
u16 xscr_text() const { return m_reg[10]; }
|
||||
u16 yscr_text() const { return m_reg[11]; }
|
||||
u16 xscr_gfx(int page) const { return m_reg[12 + page * 2]; }
|
||||
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_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; }
|
||||
u16 vbegin() const { return m_vbegin; }
|
||||
u16 hend() const { return m_hend; }
|
||||
u16 vend() const { return m_vend; }
|
||||
u16 visible_height() const { return m_visible_height; }
|
||||
u16 visible_width() const { return m_visible_width; }
|
||||
u16 hshift() const { return m_hshift; }
|
||||
u16 vshift() const { return m_vshift; }
|
||||
|
||||
protected:
|
||||
// base constructor
|
||||
x68k_crtc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// device-specific overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
void text_copy(unsigned src, unsigned dest, u8 planes);
|
||||
TIMER_CALLBACK_MEMBER(operation_end);
|
||||
void refresh_mode();
|
||||
TIMER_CALLBACK_MEMBER(hsync);
|
||||
TIMER_CALLBACK_MEMBER(raster_end);
|
||||
TIMER_CALLBACK_MEMBER(raster_irq);
|
||||
TIMER_CALLBACK_MEMBER(vblank_irq);
|
||||
|
||||
// device callbacks
|
||||
devcb_write_line m_vdisp_callback;
|
||||
devcb_write_line m_rint_callback;
|
||||
devcb_write_line m_hsync_callback;
|
||||
devcb_read16 m_tvram_read_callback;
|
||||
devcb_read16 m_gvram_read_callback;
|
||||
devcb_write16 m_tvram_write_callback;
|
||||
devcb_write16 m_gvram_write_callback;
|
||||
|
||||
// internal state
|
||||
u16 m_reg[24]; // registers
|
||||
u8 m_operation; // operation port (0xe80481)
|
||||
bool m_vblank; // true if in VBlank
|
||||
bool m_hblank; // true if in HBlank
|
||||
u16 m_htotal; // Horizontal Total (in characters)
|
||||
u16 m_vtotal; // Vertical Total
|
||||
u16 m_hbegin; // Horizontal Begin
|
||||
u16 m_vbegin; // Vertical Begin
|
||||
u16 m_hend; // Horizontal End
|
||||
u16 m_vend; // Vertical End
|
||||
u16 m_hsync_end; // Horizontal Sync End
|
||||
u16 m_vsync_end; // Vertical Sync End
|
||||
u16 m_hsyncadjust; // Horizontal Sync Adjustment
|
||||
//float m_hmultiple; // Horizontal pixel multiplier
|
||||
float m_vmultiple; // Vertical scanline multiplier (x2 for doublescan modes)
|
||||
u16 m_height;
|
||||
u16 m_width;
|
||||
u16 m_visible_height;
|
||||
u16 m_visible_width;
|
||||
u16 m_hshift;
|
||||
u16 m_vshift;
|
||||
//u16 m_video_width; // horizontal total (in pixels)
|
||||
//u16 m_video_height; // vertical total
|
||||
bool m_interlace; // 1024 vertical resolution is interlaced
|
||||
//u16 m_scanline;
|
||||
bool m_oddscanline;
|
||||
|
||||
emu_timer *m_scanline_timer;
|
||||
emu_timer *m_raster_irq_timer;
|
||||
emu_timer *m_vblank_irq_timer;
|
||||
emu_timer *m_raster_end_timer;
|
||||
emu_timer *m_operation_end_timer;
|
||||
};
|
||||
|
||||
class vinas_device : public x68k_crtc_device
|
||||
{
|
||||
public:
|
||||
vinas_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
};
|
||||
|
||||
class vicon_device : public x68k_crtc_device
|
||||
{
|
||||
public:
|
||||
vicon_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
};
|
||||
|
||||
// device type definitions
|
||||
DECLARE_DEVICE_TYPE(VINAS, vinas_device)
|
||||
DECLARE_DEVICE_TYPE(VICON, vicon_device)
|
||||
|
||||
#endif // MAME_VIDEO_X68K_CRTC_H
|
Loading…
Reference in New Issue
Block a user