summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2018-04-03 17:34:35 -0400
committer AJR <ajrhacker@users.noreply.github.com>2018-04-03 17:34:54 -0400
commitbc2acfcb76b3a69ff48f48cb70cbc257b5c75a07 (patch)
tree49bc3af4b7dc032dd49c423a963962e96f738327
parent00286343c14cb3d70930c76668d9364cc29a2c0e (diff)
atarivad: Separate source files from atarigen (nw)
-rw-r--r--scripts/target/mame/arcade.lua2
-rw-r--r--src/mame/includes/batman.h3
-rw-r--r--src/mame/includes/cybstorm.h3
-rw-r--r--src/mame/includes/offtwall.h3
-rw-r--r--src/mame/includes/relief.h4
-rw-r--r--src/mame/includes/shuuz.h1
-rw-r--r--src/mame/includes/thunderj.h2
-rw-r--r--src/mame/machine/atarigen.cpp478
-rw-r--r--src/mame/machine/atarigen.h130
-rw-r--r--src/mame/video/atarivad.cpp490
-rw-r--r--src/mame/video/atarivad.h146
11 files changed, 653 insertions, 609 deletions
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 1c2af45b3bf..44f7d00c977 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -1271,6 +1271,8 @@ files {
MAME_DIR .. "src/mame/video/atarimo.h",
MAME_DIR .. "src/mame/video/atarirle.cpp",
MAME_DIR .. "src/mame/video/atarirle.h",
+ MAME_DIR .. "src/mame/video/atarivad.cpp",
+ MAME_DIR .. "src/mame/video/atarivad.h",
}
createMAMEProjects(_target, _subtarget, "atlus")
diff --git a/src/mame/includes/batman.h b/src/mame/includes/batman.h
index 91cc513dca7..1f542365e26 100644
--- a/src/mame/includes/batman.h
+++ b/src/mame/includes/batman.h
@@ -10,9 +10,10 @@
#pragma once
-#include "machine/atarigen.h"
#include "audio/atarijsa.h"
#include "video/atarimo.h"
+#include "video/atarivad.h"
+#include "screen.h"
class batman_state : public driver_device
{
diff --git a/src/mame/includes/cybstorm.h b/src/mame/includes/cybstorm.h
index 0fc5c2012e1..62c25657d76 100644
--- a/src/mame/includes/cybstorm.h
+++ b/src/mame/includes/cybstorm.h
@@ -11,8 +11,9 @@
#pragma once
#include "audio/atarijsa.h"
-#include "machine/atarigen.h"
#include "machine/bankdev.h"
+#include "video/atarivad.h"
+#include "screen.h"
class cybstorm_state : public driver_device
diff --git a/src/mame/includes/offtwall.h b/src/mame/includes/offtwall.h
index d229e835ca7..d0a7f3f64ed 100644
--- a/src/mame/includes/offtwall.h
+++ b/src/mame/includes/offtwall.h
@@ -10,9 +10,10 @@
#pragma once
-#include "machine/atarigen.h"
#include "audio/atarijsa.h"
#include "video/atarimo.h"
+#include "video/atarivad.h"
+#include "screen.h"
class offtwall_state : public driver_device
{
diff --git a/src/mame/includes/relief.h b/src/mame/includes/relief.h
index 5baff3d6c97..ecab9ca111e 100644
--- a/src/mame/includes/relief.h
+++ b/src/mame/includes/relief.h
@@ -11,9 +11,11 @@
#pragma once
#include "machine/atarigen.h"
-#include "video/atarimo.h"
#include "sound/okim6295.h"
#include "sound/ym2413.h"
+#include "video/atarimo.h"
+#include "video/atarivad.h"
+#include "screen.h"
class relief_state : public atarigen_state
{
diff --git a/src/mame/includes/shuuz.h b/src/mame/includes/shuuz.h
index ec68e364145..5764e245f21 100644
--- a/src/mame/includes/shuuz.h
+++ b/src/mame/includes/shuuz.h
@@ -12,6 +12,7 @@
#include "machine/atarigen.h"
#include "video/atarimo.h"
+#include "video/atarivad.h"
class shuuz_state : public atarigen_state
{
diff --git a/src/mame/includes/thunderj.h b/src/mame/includes/thunderj.h
index 1c871e076c2..c83096e38f0 100644
--- a/src/mame/includes/thunderj.h
+++ b/src/mame/includes/thunderj.h
@@ -13,6 +13,8 @@
#include "machine/atarigen.h"
#include "audio/atarijsa.h"
#include "video/atarimo.h"
+#include "video/atarivad.h"
+#include "screen.h"
class thunderj_state : public atarigen_state
{
diff --git a/src/mame/machine/atarigen.cpp b/src/mame/machine/atarigen.cpp
index a4c337dba07..fb804be3507 100644
--- a/src/mame/machine/atarigen.cpp
+++ b/src/mame/machine/atarigen.cpp
@@ -10,7 +10,6 @@
#include "emu.h"
#include "cpu/m6502/m6502.h"
-#include "video/atarimo.h"
#include "atarigen.h"
@@ -326,483 +325,6 @@ void atari_sound_comm_device::delayed_6502_write(int data)
-//**************************************************************************
-// VAD VIDEO CONTROLLER DEVICE
-//**************************************************************************
-
-// device type definition
-DEFINE_DEVICE_TYPE(ATARI_VAD, atari_vad_device, "atarivad", "Atari VAD")
-
-//-------------------------------------------------
-// atari_vad_device - constructor
-//-------------------------------------------------
-
-atari_vad_device::atari_vad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ATARI_VAD, tag, owner, clock),
- device_video_interface(mconfig, *this),
- m_scanline_int_cb(*this),
- m_alpha_tilemap(*this, "alpha"),
- m_playfield_tilemap(*this, "playfield"),
- m_playfield2_tilemap(*this, "playfield2"),
- m_mob(*this, "mob"),
- m_eof_data(*this, "eof"),
- m_scanline_int_timer(nullptr),
- m_tilerow_update_timer(nullptr),
- m_eof_timer(nullptr),
- m_palette_bank(0),
- m_pf0_xscroll_raw(0),
- m_pf0_yscroll(0),
- m_pf1_xscroll_raw(0),
- m_pf1_yscroll(0),
- m_mo_xscroll(0),
- m_mo_yscroll(0)
-{
-}
-
-
-//-------------------------------------------------
-// control_write: Does the bulk of the word for an I/O
-// write.
-//-------------------------------------------------
-
-WRITE16_MEMBER(atari_vad_device::control_write)
-{
- uint16_t newword = m_control[offset];
- COMBINE_DATA(&newword);
- internal_control_write(offset, newword);
-}
-
-
-//-------------------------------------------------
-// control_read: Handles an I/O read from the video controller.
-//-------------------------------------------------
-
-READ16_MEMBER(atari_vad_device::control_read)
-{
- logerror("vc_r(%02X)\n", offset);
-
- // a read from offset 0 returns the current scanline
- // also sets bit 0x4000 if we're in VBLANK
- if (offset == 0)
- {
- int result = screen().vpos();
- if (result > 255)
- result = 255;
- if (result > screen().visible_area().max_y)
- result |= 0x4000;
- return result;
- }
- else
- return m_control[offset];
-}
-
-
-//-------------------------------------------------
-// alpha_w: Generic write handler for alpha RAM.
-//-------------------------------------------------
-
-WRITE16_MEMBER(atari_vad_device::alpha_w)
-{
- m_alpha_tilemap->write16(space, offset, data, mem_mask);
-}
-
-
-//-------------------------------------------------
-// playfield_upper_w: Generic write handler for
-// upper word of split playfield RAM.
-//-------------------------------------------------
-
-WRITE16_MEMBER(atari_vad_device::playfield_upper_w)
-{
- m_playfield_tilemap->write16_ext(space, offset, data, mem_mask);
- if (m_playfield2_tilemap != nullptr)
- m_playfield2_tilemap->write16_ext(space, offset, data, mem_mask);
-}
-
-
-//-------------------------------------------------
-// playfield_latched_lsb_w: Generic write handler for
-// lower word of playfield RAM with a latch in the LSB of the
-// upper word.
-//-------------------------------------------------
-
-WRITE16_MEMBER(atari_vad_device::playfield_latched_lsb_w)
-{
- m_playfield_tilemap->write16(space, offset, data, mem_mask);
- if ((m_control[0x0a] & 0x80) != 0)
- m_playfield_tilemap->write16_ext(space, offset, m_control[0x1d], uint16_t(0x00ff));
-}
-
-
-//-------------------------------------------------
-// playfield_latched_msb_w: Generic write handler for
-// lower word of playfield RAM with a latch in the MSB of the
-// upper word.
-//-------------------------------------------------
-
-WRITE16_MEMBER(atari_vad_device::playfield_latched_msb_w)
-{
- m_playfield_tilemap->write16(space, offset, data, mem_mask);
- if ((m_control[0x0a] & 0x80) != 0)
- m_playfield_tilemap->write16_ext(space, offset, m_control[0x1c], uint16_t(0xff00));
-}
-
-
-//-------------------------------------------------
-// playfield2_latched_msb_w: Generic write handler for
-// lower word of second playfield RAM with a latch in the MSB
-// of the upper word.
-//-------------------------------------------------
-
-WRITE16_MEMBER(atari_vad_device::playfield2_latched_msb_w)
-{
- m_playfield2_tilemap->write16(space, offset, data, mem_mask);
- if ((m_control[0x0a] & 0x80) != 0)
- m_playfield2_tilemap->write16_ext(space, offset, m_control[0x1c], uint16_t(0xff00));
-}
-
-
-//-------------------------------------------------
-// device_start: Start up the device
-//-------------------------------------------------
-
-void atari_vad_device::device_start()
-{
- // verify configuration
- if (m_playfield_tilemap == nullptr)
- throw emu_fatalerror("Playfield tilemap not found!");
- if (m_eof_data == nullptr)
- throw emu_fatalerror("EOF data not found!");
-
- // resolve callbacks
- m_scanline_int_cb.resolve_safe();
-
- // allocate timers
- m_scanline_int_timer = timer_alloc(TID_SCANLINE_INT);
- m_tilerow_update_timer = timer_alloc(TID_TILEROW_UPDATE);
- m_eof_timer = timer_alloc(TID_EOF);
-
- // register for save states
- save_item(NAME(m_palette_bank)); // which palette bank is enabled
- save_item(NAME(m_pf0_xscroll_raw)); // playfield 1 xscroll raw value
- save_item(NAME(m_pf0_yscroll)); // playfield 1 yscroll
- save_item(NAME(m_pf1_xscroll_raw)); // playfield 2 xscroll raw value
- save_item(NAME(m_pf1_yscroll)); // playfield 2 yscroll
- save_item(NAME(m_mo_xscroll)); // sprite xscroll
- save_item(NAME(m_mo_yscroll)); // sprite xscroll
-}
-
-
-//-------------------------------------------------
-// device_reset: Handle a device reset by
-// clearing the interrupt lines and states
-//-------------------------------------------------
-
-void atari_vad_device::device_reset()
-{
- // share extended memory between the two tilemaps
- if (m_playfield2_tilemap != nullptr)
- m_playfield2_tilemap->extmem().set(m_playfield_tilemap->extmem());
-
- // reset the state
- m_palette_bank = 0;
- m_pf0_xscroll_raw = m_pf1_xscroll_raw = 0;
- m_pf0_yscroll = m_pf1_yscroll = 0;
- m_mo_xscroll = m_mo_yscroll = 0;
- memset(m_control, 0, sizeof(m_control));
-
- // start the timers
- m_tilerow_update_timer->adjust(screen().time_until_pos(0));
- m_eof_timer->adjust(screen().time_until_pos(0));
-}
-
-
-//-------------------------------------------------
-// device_timer: Handle device-specific timer
-// calbacks
-//-------------------------------------------------
-
-void atari_vad_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TID_SCANLINE_INT:
- m_scanline_int_cb(ASSERT_LINE);
- break;
-
- case TID_TILEROW_UPDATE:
- update_tilerow(timer, param);
- break;
-
- case TID_EOF:
- eof_update(timer);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// internal_control_write: Handle writes to the
-// control registers and EOF updates
-//-------------------------------------------------
-
-void atari_vad_device::internal_control_write(offs_t offset, uint16_t newword)
-{
- // switch off the offset
- uint16_t oldword = m_control[offset];
- m_control[offset] = newword;
- switch (offset)
- {
- //
- // VAD register map:
- //
- // 00 = HDW_ENABLE
- // A000 = enable other VAD params
- // E000 = enable other VAD params but disable update from ALPHA RAM
- // 01 = HDW_VSY_LD (standard = 0x795)
- // 0FF8 = V_SY_S
- // 0007 = V_SY_E
- // 02 = HDW_VBL_LD (standard = 0xAEF)
- // FE00 = VLAST
- // 01FF = V_BL_S
- // 03 = HDW_VINT
- // 04 = HDW_HSY_LD (standard = 0x5EEF)
- // FC00 = H_SY_E/2
- // 03FF = H_SY_S
- // 05 = HDW_HBL_LD (relief = 0x72AC, batman/thunderj = 0xBEB1, shuuz/offtwall = 0xCEB1)
- // F000 = LB_CLR
- // 0800 = H_BL_E/16
- // 0400 = H_BL_E/1
- // 03FF = H_BL_S
- // 06 = HDW_SLIP_LD (relief/batman/shuuz = 0x6F05, shuuz/offtwall = 0x0F05)
- // 7F00 = SLIP_S
- // 0080 = SLIP_E_SE1
- // 007F = SLIP_E
- // 07 = HDW_APDMA_LD (relief/batman/shuuz = 0xBE84, shuuz = 0xB90E, offtwall = 0xB90D)
- // C000 = OPFPIC
- // 3800 = PF_HRESET/16
- // 0780 = PFAT
- // 0070 = AL_HRESET (depending on ALHSIZ)
- // 000F = ALPHA_DMA
- // 08 = HDW_PMBASE_LD (relief/batman/shuuz = 0x0519, shuuz/offtwall = 0x49B4)
- // E000 = P1BASE/0x2000
- // 1C00 = P2BASE/0x2000
- // 0380 = PABASE/0x2000
- // 0040 = PMASK
- // 003E = MOBASE/0x800
- // 0001 = MOMASK
- // 09 = HDW_ALBASE_LD (relief/batman/shuuz = 0x061F, shuuz/offtwall = 0x017F)
- // 0400 = OPMINUS1
- // 03C0 = ALBASE/0x1000
- // 003F = SLIPBASE/0x80
- // 0A = HDW_OPT_LD (relief/batman/shuuz = 0x4410, shuuz = 0x0250, offtwall = 0x0A10)
- // 8000 = OPFHSIZ - subtract 1 from PF2 attribute horizontal stamp address
- // 4000 = OPIUM - playfield 2 enable
- // 2000 = OLS_EN - linescroll enable
- // 1000 = OSLPINK - split links enable
- // 0800 = OSLORAM - slow MO DMA cycles
- // 0400 = O_DCDMA - enable double time color RAM DMA cycles
- // 0200 = O_DVDMA - enable double time video RAM DMA cycles
- // 0100 = OADROEN - tristate address bus
- // 0080 = OAS_EN - enable autostore of playfield attributes
- // 0040 = OCRDWE - enable 8-bit color RAM
- // 0020 = OVRDTACK - wait for VRAM DMA on writes
- // 0010 = OCRDTACK - wait for CRAM DMA on writes
- // 0008 = OALHSIZ - alpha horiz stamp size (0=8)
- // 0004 = OPFHSIZ - PF horiz stamp size (0=8)
- // 0002 = OPFVSIZ - PF vertical stamp size (0=8)
- // 0001 = OMOVSIZ - MO vertical stamp size (0=8)
- // 10 = HDW_MOCON (MOB chip MOB code)
- // 11 = HDW_PCON (MOB chip PF code)
- // 12 = HDW_GRCON (MOB chip GR code)
- // 13 = MO_hscroll (9)
- // 14 = PF1_hscroll (A)
- // 15 = PF2_hscroll (B)
- // 16 = MO_vscroll (D)
- // 17 = PF1_vscroll (E)
- // 18 = PF2_vscroll (F)
- //
- // 3efffe = reset to wrong configuration?
- //
-
- case 0:
-//if (oldword != newword) printf("Word 0 = %04X\n", newword);
- break;
-
- // set the scanline interrupt here
- case 0x03:
- if (oldword != newword || !m_scanline_int_timer->enabled())
- m_scanline_int_timer->adjust(screen().time_until_pos(newword & 0x1ff));
- break;
-
- // latch enable
- case 0x0a:
- // check for palette banking
- if (m_palette_bank != (((newword & 0x0400) >> 10) ^ 1))
- {
- screen().update_partial(screen().vpos());
- m_palette_bank = ((newword & 0x0400) >> 10) ^ 1;
- }
-//if ((oldword & ~0x0080) != (newword & ~0x0080)) printf("Latch control = %04X\n", newword);
- break;
-
- // indexed parameters
- case 0x10: case 0x11: case 0x12: case 0x13:
- case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b:
- update_parameter(newword);
- break;
-
- // scanline IRQ ack here
- case 0x1e:
- m_scanline_int_cb(CLEAR_LINE);
- break;
-
- // log anything else
- default:
- if (oldword != newword)
- logerror("vc_w(%02X, %04X) ** [prev=%04X]\n", offset, newword, oldword);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// update_pf_xscrolls: Update the playfield
-// scroll values.
-//-------------------------------------------------
-
-inline void atari_vad_device::update_pf_xscrolls()
-{
- m_playfield_tilemap->set_scrollx(0, m_pf0_xscroll_raw + ((m_pf1_xscroll_raw) & 7));
- if (m_playfield2_tilemap != nullptr)
- m_playfield2_tilemap->set_scrollx(0, m_pf1_xscroll_raw + 4);
-}
-
-
-//-------------------------------------------------
-// update_parameter: Update parameters, shared
-// between end-of-frame, tilerow updates, and
-// direct control writes.
-//-------------------------------------------------
-
-void atari_vad_device::update_parameter(uint16_t newword)
-{
- switch (newword & 15)
- {
- case 9:
- m_mo_xscroll = (newword >> 7) & 0x1ff;
- if (m_mob != nullptr)
- m_mob->set_xscroll(m_mo_xscroll);
- break;
-
- case 10:
- m_pf1_xscroll_raw = (newword >> 7) & 0x1ff;
- update_pf_xscrolls();
- break;
-
- case 11:
- m_pf0_xscroll_raw = (newword >> 7) & 0x1ff;
- update_pf_xscrolls();
- break;
-
- case 13:
- m_mo_yscroll = (newword >> 7) & 0x1ff;
- if (m_mob != nullptr)
- m_mob->set_yscroll(m_mo_yscroll);
- break;
-
- case 14:
- m_pf1_yscroll = (newword >> 7) & 0x1ff;
- if (m_playfield2_tilemap != nullptr)
- m_playfield2_tilemap->set_scrolly(0, m_pf1_yscroll);
- break;
-
- case 15:
- m_pf0_yscroll = (newword >> 7) & 0x1ff;
- m_playfield_tilemap->set_scrolly(0, m_pf0_yscroll);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// update_tilerow: Fetch parameters stored at
-// the end of the current tilerow, which affect
-// rowscrolling.
-//-------------------------------------------------
-
-void atari_vad_device::update_tilerow(emu_timer &timer, int scanline)
-{
- // skip if out of bounds, or not enabled
- if (scanline <= screen().visible_area().max_y && (m_control[0x0a] & 0x2000) != 0 && m_alpha_tilemap != nullptr)
- {
- // iterate over non-visible alpha tiles in this row
- int offset = scanline / 8 * 64 + 48 + 2 * (scanline % 8);
- int data0 = m_alpha_tilemap->basemem_read(offset++);
- int data1 = m_alpha_tilemap->basemem_read(offset++);
-
- // force an update if we have data
- if (scanline > 0 && ((data0 | data1) & 15) != 0)
- screen().update_partial(scanline - 1);
-
- // write the data
- if ((data0 & 15) != 0)
- update_parameter(data0);
- if ((data1 & 15) != 0)
- update_parameter(data1);
- }
-
- // update the timer to go off at the start of the next row
- scanline += ((m_control[0x0a] & 0x2000) != 0) ? 1 : 8;
- if (scanline >= screen().height())
- scanline = 0;
- timer.adjust(screen().time_until_pos(scanline), scanline);
-}
-
-
-//-------------------------------------------------
-// eof_update: Callback that slurps up data and
-// feeds it into the video controller registers
-// every refresh.
-//-------------------------------------------------
-
-void atari_vad_device::eof_update(emu_timer &timer)
-{
- // echo all the commands to the video controller
- for (int i = 0; i < 0x1c; i++)
- if (m_eof_data[i] != 0)
- internal_control_write(i, m_eof_data[i]);
-
- // update the scroll positions
-/* atarimo_set_xscroll(0, m_mo_xscroll);
- atarimo_set_yscroll(0, m_mo_yscroll);
-
- update_pf_xscrolls();
-
- m_playfield_tilemap->set_scrolly(0, m_pf0_yscroll);
- if (m_playfield2_tilemap != nullptr)
- m_playfield2_tilemap->set_scrolly(0, m_pf1_yscroll);*/
- timer.adjust(screen().time_until_pos(0));
-
- // use this for debugging the video controller values
-#if 0
- if (machine().input().code_pressed(KEYCODE_8))
- {
- static FILE *out;
- if (!out) out = fopen("scroll.log", "w");
- if (out)
- {
- for (i = 0; i < 64; i++)
- fprintf(out, "%04X ", data[i]);
- fprintf(out, "\n");
- }
- }
-#endif
-}
-
-
-
/***************************************************************************
OVERALL INIT
***************************************************************************/
diff --git a/src/mame/machine/atarigen.h b/src/mame/machine/atarigen.h
index 8d0985aa3a9..8201d01ad03 100644
--- a/src/mame/machine/atarigen.h
+++ b/src/mame/machine/atarigen.h
@@ -13,7 +13,6 @@
#include "includes/slapstic.h"
#include "cpu/m6502/m6502.h"
-#include "video/atarimo.h"
#include "screen.h"
@@ -39,50 +38,9 @@
-#define MCFG_ATARI_VAD_ADD(_tag, _screen, _intcb) \
- MCFG_DEVICE_ADD(_tag, ATARI_VAD, 0) \
- MCFG_VIDEO_SET_SCREEN(_screen) \
- devcb = &downcast<atari_vad_device &>(*device).set_scanline_int_cb(DEVCB_##_intcb);
-
-#define MCFG_ATARI_VAD_PLAYFIELD(_class, _gfxtag, _getinfo) \
- { std::string fulltag(device->tag()); fulltag.append(":playfield"); device_t *device; \
- MCFG_TILEMAP_ADD(fulltag.c_str()) \
- MCFG_TILEMAP_GFXDECODE("^" _gfxtag) \
- MCFG_TILEMAP_BYTES_PER_ENTRY(2) \
- MCFG_TILEMAP_INFO_CB_DEVICE(DEVICE_SELF_OWNER, _class, _getinfo) \
- MCFG_TILEMAP_TILE_SIZE(8,8) \
- MCFG_TILEMAP_LAYOUT_STANDARD(SCAN_COLS, 64,64) }
-
-#define MCFG_ATARI_VAD_PLAYFIELD2(_class, _gfxtag, _getinfo) \
- { std::string fulltag(device->tag()); fulltag.append(":playfield2"); device_t *device; \
- MCFG_TILEMAP_ADD(fulltag.c_str()) \
- MCFG_TILEMAP_GFXDECODE("^" _gfxtag) \
- MCFG_TILEMAP_BYTES_PER_ENTRY(2) \
- MCFG_TILEMAP_INFO_CB_DEVICE(DEVICE_SELF_OWNER, _class, _getinfo) \
- MCFG_TILEMAP_TILE_SIZE(8,8) \
- MCFG_TILEMAP_LAYOUT_STANDARD(SCAN_COLS, 64,64) \
- MCFG_TILEMAP_TRANSPARENT_PEN(0) }
-
-#define MCFG_ATARI_VAD_ALPHA(_class, _gfxtag, _getinfo) \
- { std::string fulltag(device->tag()); fulltag.append(":alpha"); device_t *device; \
- MCFG_TILEMAP_ADD(fulltag.c_str()) \
- MCFG_TILEMAP_GFXDECODE("^" _gfxtag) \
- MCFG_TILEMAP_BYTES_PER_ENTRY(2) \
- MCFG_TILEMAP_INFO_CB_DEVICE(DEVICE_SELF_OWNER, _class, _getinfo) \
- MCFG_TILEMAP_TILE_SIZE(8,8) \
- MCFG_TILEMAP_LAYOUT_STANDARD(SCAN_ROWS, 64,32) \
- MCFG_TILEMAP_TRANSPARENT_PEN(0) }
-
-#define MCFG_ATARI_VAD_MOB(_config, _gfxtag) \
- { std::string fulltag(device->tag()); fulltag.append(":mob"); device_t *device; \
- MCFG_ATARI_MOTION_OBJECTS_ADD(fulltag.c_str(), "^^screen", _config) \
- MCFG_ATARI_MOTION_OBJECTS_GFXDECODE("^" _gfxtag) }
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
#define PORT_ATARI_COMM_SOUND_TO_MAIN_READY(_tag) \
PORT_READ_LINE_DEVICE_MEMBER(_tag, atari_sound_comm_device, sound_to_main_ready)
@@ -162,88 +120,6 @@ private:
};
-
-// ======================> atari_vad_device
-
-// device type definition
-DECLARE_DEVICE_TYPE(ATARI_VAD, atari_vad_device)
-
-class atari_vad_device : public device_t,
- public device_video_interface
-{
-public:
- // construction/destruction
- atari_vad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // configuration helpers
- template<class Object> devcb_base &set_scanline_int_cb(Object &&cb) { return m_scanline_int_cb.set_callback(std::forward<Object>(cb)); }
-
- // getters
- tilemap_device &alpha() const { return *m_alpha_tilemap; }
- tilemap_device &playfield() const { return *m_playfield_tilemap; }
- tilemap_device &playfield2() const { return *m_playfield2_tilemap; }
- atari_motion_objects_device &mob() const { return *m_mob; }
-
- // read/write handlers
- DECLARE_READ16_MEMBER(control_read);
- DECLARE_WRITE16_MEMBER(control_write);
-
- // playfield/alpha tilemap helpers
- DECLARE_WRITE16_MEMBER(alpha_w);
- DECLARE_WRITE16_MEMBER(playfield_upper_w);
- DECLARE_WRITE16_MEMBER(playfield_latched_lsb_w);
- DECLARE_WRITE16_MEMBER(playfield_latched_msb_w);
- DECLARE_WRITE16_MEMBER(playfield2_latched_msb_w);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- // timer IDs
- enum
- {
- TID_SCANLINE_INT,
- TID_TILEROW_UPDATE,
- TID_EOF
- };
-
- // internal helpers
- void internal_control_write(offs_t offset, uint16_t newword);
- void update_pf_xscrolls();
- void update_parameter(uint16_t newword);
- void update_tilerow(emu_timer &timer, int scanline);
- void eof_update(emu_timer &timer);
-
- // configuration state
- devcb_write_line m_scanline_int_cb;
-
- // internal state
- optional_device<tilemap_device> m_alpha_tilemap;
- required_device<tilemap_device> m_playfield_tilemap;
- optional_device<tilemap_device> m_playfield2_tilemap;
- optional_device<atari_motion_objects_device> m_mob;
- optional_shared_ptr<uint16_t> m_eof_data;
-
- emu_timer * m_scanline_int_timer;
- emu_timer * m_tilerow_update_timer;
- emu_timer * m_eof_timer;
-
- uint32_t m_palette_bank; // which palette bank is enabled
- //uint32_t m_pf0_xscroll; // playfield 1 xscroll
- uint32_t m_pf0_xscroll_raw; // playfield 1 xscroll raw value
- uint32_t m_pf0_yscroll; // playfield 1 yscroll
- uint32_t m_pf1_xscroll_raw; // playfield 2 xscroll raw value
- uint32_t m_pf1_yscroll; // playfield 2 yscroll
- uint32_t m_mo_xscroll; // sprite xscroll
- uint32_t m_mo_yscroll; // sprite xscroll
-
- uint16_t m_control[0x40/2]; // control data
-};
-
-
/***************************************************************************
TYPES & STRUCTURES
***************************************************************************/
diff --git a/src/mame/video/atarivad.cpp b/src/mame/video/atarivad.cpp
new file mode 100644
index 00000000000..85a80776954
--- /dev/null
+++ b/src/mame/video/atarivad.cpp
@@ -0,0 +1,490 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ atarivad.h
+
+ Atari VAD video controller device.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "video/atarivad.h"
+#include "video/atarimo.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// VAD VIDEO CONTROLLER DEVICE
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(ATARI_VAD, atari_vad_device, "atarivad", "Atari VAD")
+
+//-------------------------------------------------
+// atari_vad_device - constructor
+//-------------------------------------------------
+
+atari_vad_device::atari_vad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ATARI_VAD, tag, owner, clock),
+ device_video_interface(mconfig, *this),
+ m_scanline_int_cb(*this),
+ m_alpha_tilemap(*this, "alpha"),
+ m_playfield_tilemap(*this, "playfield"),
+ m_playfield2_tilemap(*this, "playfield2"),
+ m_mob(*this, "mob"),
+ m_eof_data(*this, "eof"),
+ m_scanline_int_timer(nullptr),
+ m_tilerow_update_timer(nullptr),
+ m_eof_timer(nullptr),
+ m_palette_bank(0),
+ m_pf0_xscroll_raw(0),
+ m_pf0_yscroll(0),
+ m_pf1_xscroll_raw(0),
+ m_pf1_yscroll(0),
+ m_mo_xscroll(0),
+ m_mo_yscroll(0)
+{
+}
+
+
+//-------------------------------------------------
+// control_write: Does the bulk of the word for an I/O
+// write.
+//-------------------------------------------------
+
+WRITE16_MEMBER(atari_vad_device::control_write)
+{
+ uint16_t newword = m_control[offset];
+ COMBINE_DATA(&newword);
+ internal_control_write(offset, newword);
+}
+
+
+//-------------------------------------------------
+// control_read: Handles an I/O read from the video controller.
+//-------------------------------------------------
+
+READ16_MEMBER(atari_vad_device::control_read)
+{
+ logerror("vc_r(%02X)\n", offset);
+
+ // a read from offset 0 returns the current scanline
+ // also sets bit 0x4000 if we're in VBLANK
+ if (offset == 0)
+ {
+ int result = screen().vpos();
+ if (result > 255)
+ result = 255;
+ if (result > screen().visible_area().max_y)
+ result |= 0x4000;
+ return result;
+ }
+ else
+ return m_control[offset];
+}
+
+
+//-------------------------------------------------
+// alpha_w: Generic write handler for alpha RAM.
+//-------------------------------------------------
+
+WRITE16_MEMBER(atari_vad_device::alpha_w)
+{
+ m_alpha_tilemap->write16(space, offset, data, mem_mask);
+}
+
+
+//-------------------------------------------------
+// playfield_upper_w: Generic write handler for
+// upper word of split playfield RAM.
+//-------------------------------------------------
+
+WRITE16_MEMBER(atari_vad_device::playfield_upper_w)
+{
+ m_playfield_tilemap->write16_ext(space, offset, data, mem_mask);
+ if (m_playfield2_tilemap != nullptr)
+ m_playfield2_tilemap->write16_ext(space, offset, data, mem_mask);
+}
+
+
+//-------------------------------------------------
+// playfield_latched_lsb_w: Generic write handler for
+// lower word of playfield RAM with a latch in the LSB of the
+// upper word.
+//-------------------------------------------------
+
+WRITE16_MEMBER(atari_vad_device::playfield_latched_lsb_w)
+{
+ m_playfield_tilemap->write16(space, offset, data, mem_mask);
+ if ((m_control[0x0a] & 0x80) != 0)
+ m_playfield_tilemap->write16_ext(space, offset, m_control[0x1d], uint16_t(0x00ff));
+}
+
+
+//-------------------------------------------------
+// playfield_latched_msb_w: Generic write handler for
+// lower word of playfield RAM with a latch in the MSB of the
+// upper word.
+//-------------------------------------------------
+
+WRITE16_MEMBER(atari_vad_device::playfield_latched_msb_w)
+{
+ m_playfield_tilemap->write16(space, offset, data, mem_mask);
+ if ((m_control[0x0a] & 0x80) != 0)
+ m_playfield_tilemap->write16_ext(space, offset, m_control[0x1c], uint16_t(0xff00));
+}
+
+
+//-------------------------------------------------
+// playfield2_latched_msb_w: Generic write handler for
+// lower word of second playfield RAM with a latch in the MSB
+// of the upper word.
+//-------------------------------------------------
+
+WRITE16_MEMBER(atari_vad_device::playfield2_latched_msb_w)
+{
+ m_playfield2_tilemap->write16(space, offset, data, mem_mask);
+ if ((m_control[0x0a] & 0x80) != 0)
+ m_playfield2_tilemap->write16_ext(space, offset, m_control[0x1c], uint16_t(0xff00));
+}
+
+
+//-------------------------------------------------
+// device_start: Start up the device
+//-------------------------------------------------
+
+void atari_vad_device::device_start()
+{
+ // verify configuration
+ if (m_playfield_tilemap == nullptr)
+ throw emu_fatalerror("Playfield tilemap not found!");
+ if (m_eof_data == nullptr)
+ throw emu_fatalerror("EOF data not found!");
+
+ // resolve callbacks
+ m_scanline_int_cb.resolve_safe();
+
+ // allocate timers
+ m_scanline_int_timer = timer_alloc(TID_SCANLINE_INT);
+ m_tilerow_update_timer = timer_alloc(TID_TILEROW_UPDATE);
+ m_eof_timer = timer_alloc(TID_EOF);
+
+ // register for save states
+ save_item(NAME(m_palette_bank)); // which palette bank is enabled
+ save_item(NAME(m_pf0_xscroll_raw)); // playfield 1 xscroll raw value
+ save_item(NAME(m_pf0_yscroll)); // playfield 1 yscroll
+ save_item(NAME(m_pf1_xscroll_raw)); // playfield 2 xscroll raw value
+ save_item(NAME(m_pf1_yscroll)); // playfield 2 yscroll
+ save_item(NAME(m_mo_xscroll)); // sprite xscroll
+ save_item(NAME(m_mo_yscroll)); // sprite xscroll
+}
+
+
+//-------------------------------------------------
+// device_reset: Handle a device reset by
+// clearing the interrupt lines and states
+//-------------------------------------------------
+
+void atari_vad_device::device_reset()
+{
+ // share extended memory between the two tilemaps
+ if (m_playfield2_tilemap != nullptr)
+ m_playfield2_tilemap->extmem().set(m_playfield_tilemap->extmem());
+
+ // reset the state
+ m_palette_bank = 0;
+ m_pf0_xscroll_raw = m_pf1_xscroll_raw = 0;
+ m_pf0_yscroll = m_pf1_yscroll = 0;
+ m_mo_xscroll = m_mo_yscroll = 0;
+ memset(m_control, 0, sizeof(m_control));
+
+ // start the timers
+ m_tilerow_update_timer->adjust(screen().time_until_pos(0));
+ m_eof_timer->adjust(screen().time_until_pos(0));
+}
+
+
+//-------------------------------------------------
+// device_timer: Handle device-specific timer
+// calbacks
+//-------------------------------------------------
+
+void atari_vad_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TID_SCANLINE_INT:
+ m_scanline_int_cb(ASSERT_LINE);
+ break;
+
+ case TID_TILEROW_UPDATE:
+ update_tilerow(timer, param);
+ break;
+
+ case TID_EOF:
+ eof_update(timer);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// internal_control_write: Handle writes to the
+// control registers and EOF updates
+//-------------------------------------------------
+
+void atari_vad_device::internal_control_write(offs_t offset, uint16_t newword)
+{
+ // switch off the offset
+ uint16_t oldword = m_control[offset];
+ m_control[offset] = newword;
+ switch (offset)
+ {
+ //
+ // VAD register map:
+ //
+ // 00 = HDW_ENABLE
+ // A000 = enable other VAD params
+ // E000 = enable other VAD params but disable update from ALPHA RAM
+ // 01 = HDW_VSY_LD (standard = 0x795)
+ // 0FF8 = V_SY_S
+ // 0007 = V_SY_E
+ // 02 = HDW_VBL_LD (standard = 0xAEF)
+ // FE00 = VLAST
+ // 01FF = V_BL_S
+ // 03 = HDW_VINT
+ // 04 = HDW_HSY_LD (standard = 0x5EEF)
+ // FC00 = H_SY_E/2
+ // 03FF = H_SY_S
+ // 05 = HDW_HBL_LD (relief = 0x72AC, batman/thunderj = 0xBEB1, shuuz/offtwall = 0xCEB1)
+ // F000 = LB_CLR
+ // 0800 = H_BL_E/16
+ // 0400 = H_BL_E/1
+ // 03FF = H_BL_S
+ // 06 = HDW_SLIP_LD (relief/batman/shuuz = 0x6F05, shuuz/offtwall = 0x0F05)
+ // 7F00 = SLIP_S
+ // 0080 = SLIP_E_SE1
+ // 007F = SLIP_E
+ // 07 = HDW_APDMA_LD (relief/batman/shuuz = 0xBE84, shuuz = 0xB90E, offtwall = 0xB90D)
+ // C000 = OPFPIC
+ // 3800 = PF_HRESET/16
+ // 0780 = PFAT
+ // 0070 = AL_HRESET (depending on ALHSIZ)
+ // 000F = ALPHA_DMA
+ // 08 = HDW_PMBASE_LD (relief/batman/shuuz = 0x0519, shuuz/offtwall = 0x49B4)
+ // E000 = P1BASE/0x2000
+ // 1C00 = P2BASE/0x2000
+ // 0380 = PABASE/0x2000
+ // 0040 = PMASK
+ // 003E = MOBASE/0x800
+ // 0001 = MOMASK
+ // 09 = HDW_ALBASE_LD (relief/batman/shuuz = 0x061F, shuuz/offtwall = 0x017F)
+ // 0400 = OPMINUS1
+ // 03C0 = ALBASE/0x1000
+ // 003F = SLIPBASE/0x80
+ // 0A = HDW_OPT_LD (relief/batman/shuuz = 0x4410, shuuz = 0x0250, offtwall = 0x0A10)
+ // 8000 = OPFHSIZ - subtract 1 from PF2 attribute horizontal stamp address
+ // 4000 = OPIUM - playfield 2 enable
+ // 2000 = OLS_EN - linescroll enable
+ // 1000 = OSLPINK - split links enable
+ // 0800 = OSLORAM - slow MO DMA cycles
+ // 0400 = O_DCDMA - enable double time color RAM DMA cycles
+ // 0200 = O_DVDMA - enable double time video RAM DMA cycles
+ // 0100 = OADROEN - tristate address bus
+ // 0080 = OAS_EN - enable autostore of playfield attributes
+ // 0040 = OCRDWE - enable 8-bit color RAM
+ // 0020 = OVRDTACK - wait for VRAM DMA on writes
+ // 0010 = OCRDTACK - wait for CRAM DMA on writes
+ // 0008 = OALHSIZ - alpha horiz stamp size (0=8)
+ // 0004 = OPFHSIZ - PF horiz stamp size (0=8)
+ // 0002 = OPFVSIZ - PF vertical stamp size (0=8)
+ // 0001 = OMOVSIZ - MO vertical stamp size (0=8)
+ // 10 = HDW_MOCON (MOB chip MOB code)
+ // 11 = HDW_PCON (MOB chip PF code)
+ // 12 = HDW_GRCON (MOB chip GR code)
+ // 13 = MO_hscroll (9)
+ // 14 = PF1_hscroll (A)
+ // 15 = PF2_hscroll (B)
+ // 16 = MO_vscroll (D)
+ // 17 = PF1_vscroll (E)
+ // 18 = PF2_vscroll (F)
+ //
+ // 3efffe = reset to wrong configuration?
+ //
+
+ case 0:
+//if (oldword != newword) printf("Word 0 = %04X\n", newword);
+ break;
+
+ // set the scanline interrupt here
+ case 0x03:
+ if (oldword != newword || !m_scanline_int_timer->enabled())
+ m_scanline_int_timer->adjust(screen().time_until_pos(newword & 0x1ff));
+ break;
+
+ // latch enable
+ case 0x0a:
+ // check for palette banking
+ if (m_palette_bank != (((newword & 0x0400) >> 10) ^ 1))
+ {
+ screen().update_partial(screen().vpos());
+ m_palette_bank = ((newword & 0x0400) >> 10) ^ 1;
+ }
+//if ((oldword & ~0x0080) != (newword & ~0x0080)) printf("Latch control = %04X\n", newword);
+ break;
+
+ // indexed parameters
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ update_parameter(newword);
+ break;
+
+ // scanline IRQ ack here
+ case 0x1e:
+ m_scanline_int_cb(CLEAR_LINE);
+ break;
+
+ // log anything else
+ default:
+ if (oldword != newword)
+ logerror("vc_w(%02X, %04X) ** [prev=%04X]\n", offset, newword, oldword);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// update_pf_xscrolls: Update the playfield
+// scroll values.
+//-------------------------------------------------
+
+inline void atari_vad_device::update_pf_xscrolls()
+{
+ m_playfield_tilemap->set_scrollx(0, m_pf0_xscroll_raw + ((m_pf1_xscroll_raw) & 7));
+ if (m_playfield2_tilemap != nullptr)
+ m_playfield2_tilemap->set_scrollx(0, m_pf1_xscroll_raw + 4);
+}
+
+
+//-------------------------------------------------
+// update_parameter: Update parameters, shared
+// between end-of-frame, tilerow updates, and
+// direct control writes.
+//-------------------------------------------------
+
+void atari_vad_device::update_parameter(uint16_t newword)
+{
+ switch (newword & 15)
+ {
+ case 9:
+ m_mo_xscroll = (newword >> 7) & 0x1ff;
+ if (m_mob != nullptr)
+ m_mob->set_xscroll(m_mo_xscroll);
+ break;
+
+ case 10:
+ m_pf1_xscroll_raw = (newword >> 7) & 0x1ff;
+ update_pf_xscrolls();
+ break;
+
+ case 11:
+ m_pf0_xscroll_raw = (newword >> 7) & 0x1ff;
+ update_pf_xscrolls();
+ break;
+
+ case 13:
+ m_mo_yscroll = (newword >> 7) & 0x1ff;
+ if (m_mob != nullptr)
+ m_mob->set_yscroll(m_mo_yscroll);
+ break;
+
+ case 14:
+ m_pf1_yscroll = (newword >> 7) & 0x1ff;
+ if (m_playfield2_tilemap != nullptr)
+ m_playfield2_tilemap->set_scrolly(0, m_pf1_yscroll);
+ break;
+
+ case 15:
+ m_pf0_yscroll = (newword >> 7) & 0x1ff;
+ m_playfield_tilemap->set_scrolly(0, m_pf0_yscroll);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// update_tilerow: Fetch parameters stored at
+// the end of the current tilerow, which affect
+// rowscrolling.
+//-------------------------------------------------
+
+void atari_vad_device::update_tilerow(emu_timer &timer, int scanline)
+{
+ // skip if out of bounds, or not enabled
+ if (scanline <= screen().visible_area().max_y && (m_control[0x0a] & 0x2000) != 0 && m_alpha_tilemap != nullptr)
+ {
+ // iterate over non-visible alpha tiles in this row
+ int offset = scanline / 8 * 64 + 48 + 2 * (scanline % 8);
+ int data0 = m_alpha_tilemap->basemem_read(offset++);
+ int data1 = m_alpha_tilemap->basemem_read(offset++);
+
+ // force an update if we have data
+ if (scanline > 0 && ((data0 | data1) & 15) != 0)
+ screen().update_partial(scanline - 1);
+
+ // write the data
+ if ((data0 & 15) != 0)
+ update_parameter(data0);
+ if ((data1 & 15) != 0)
+ update_parameter(data1);
+ }
+
+ // update the timer to go off at the start of the next row
+ scanline += ((m_control[0x0a] & 0x2000) != 0) ? 1 : 8;
+ if (scanline >= screen().height())
+ scanline = 0;
+ timer.adjust(screen().time_until_pos(scanline), scanline);
+}
+
+
+//-------------------------------------------------
+// eof_update: Callback that slurps up data and
+// feeds it into the video controller registers
+// every refresh.
+//-------------------------------------------------
+
+void atari_vad_device::eof_update(emu_timer &timer)
+{
+ // echo all the commands to the video controller
+ for (int i = 0; i < 0x1c; i++)
+ if (m_eof_data[i] != 0)
+ internal_control_write(i, m_eof_data[i]);
+
+ // update the scroll positions
+/* atarimo_set_xscroll(0, m_mo_xscroll);
+ atarimo_set_yscroll(0, m_mo_yscroll);
+
+ update_pf_xscrolls();
+
+ m_playfield_tilemap->set_scrolly(0, m_pf0_yscroll);
+ if (m_playfield2_tilemap != nullptr)
+ m_playfield2_tilemap->set_scrolly(0, m_pf1_yscroll);*/
+ timer.adjust(screen().time_until_pos(0));
+
+ // use this for debugging the video controller values
+#if 0
+ if (machine().input().code_pressed(KEYCODE_8))
+ {
+ static FILE *out;
+ if (!out) out = fopen("scroll.log", "w");
+ if (out)
+ {
+ for (i = 0; i < 64; i++)
+ fprintf(out, "%04X ", data[i]);
+ fprintf(out, "\n");
+ }
+ }
+#endif
+}
diff --git a/src/mame/video/atarivad.h b/src/mame/video/atarivad.h
new file mode 100644
index 00000000000..1bdc95cc444
--- /dev/null
+++ b/src/mame/video/atarivad.h
@@ -0,0 +1,146 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ atarivad.h
+
+ Atari VAD video controller device.
+
+***************************************************************************/
+
+#ifndef MAME_VIDEO_ATARIVAD_H
+#define MAME_VIDEO_ATARIVAD_H
+
+#include "video/atarimo.h"
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ATARI_VAD_ADD(_tag, _screen, _intcb) \
+ MCFG_DEVICE_ADD(_tag, ATARI_VAD, 0) \
+ MCFG_VIDEO_SET_SCREEN(_screen) \
+ devcb = &downcast<atari_vad_device &>(*device).set_scanline_int_cb(DEVCB_##_intcb);
+
+#define MCFG_ATARI_VAD_PLAYFIELD(_class, _gfxtag, _getinfo) \
+ { std::string fulltag(device->tag()); fulltag.append(":playfield"); device_t *device; \
+ MCFG_TILEMAP_ADD(fulltag.c_str()) \
+ MCFG_TILEMAP_GFXDECODE("^" _gfxtag) \
+ MCFG_TILEMAP_BYTES_PER_ENTRY(2) \
+ MCFG_TILEMAP_INFO_CB_DEVICE(DEVICE_SELF_OWNER, _class, _getinfo) \
+ MCFG_TILEMAP_TILE_SIZE(8,8) \
+ MCFG_TILEMAP_LAYOUT_STANDARD(SCAN_COLS, 64,64) }
+
+#define MCFG_ATARI_VAD_PLAYFIELD2(_class, _gfxtag, _getinfo) \
+ { std::string fulltag(device->tag()); fulltag.append(":playfield2"); device_t *device; \
+ MCFG_TILEMAP_ADD(fulltag.c_str()) \
+ MCFG_TILEMAP_GFXDECODE("^" _gfxtag) \
+ MCFG_TILEMAP_BYTES_PER_ENTRY(2) \
+ MCFG_TILEMAP_INFO_CB_DEVICE(DEVICE_SELF_OWNER, _class, _getinfo) \
+ MCFG_TILEMAP_TILE_SIZE(8,8) \
+ MCFG_TILEMAP_LAYOUT_STANDARD(SCAN_COLS, 64,64) \
+ MCFG_TILEMAP_TRANSPARENT_PEN(0) }
+
+#define MCFG_ATARI_VAD_ALPHA(_class, _gfxtag, _getinfo) \
+ { std::string fulltag(device->tag()); fulltag.append(":alpha"); device_t *device; \
+ MCFG_TILEMAP_ADD(fulltag.c_str()) \
+ MCFG_TILEMAP_GFXDECODE("^" _gfxtag) \
+ MCFG_TILEMAP_BYTES_PER_ENTRY(2) \
+ MCFG_TILEMAP_INFO_CB_DEVICE(DEVICE_SELF_OWNER, _class, _getinfo) \
+ MCFG_TILEMAP_TILE_SIZE(8,8) \
+ MCFG_TILEMAP_LAYOUT_STANDARD(SCAN_ROWS, 64,32) \
+ MCFG_TILEMAP_TRANSPARENT_PEN(0) }
+
+#define MCFG_ATARI_VAD_MOB(_config, _gfxtag) \
+ { std::string fulltag(device->tag()); fulltag.append(":mob"); device_t *device; \
+ MCFG_ATARI_MOTION_OBJECTS_ADD(fulltag.c_str(), "^^screen", _config) \
+ MCFG_ATARI_MOTION_OBJECTS_GFXDECODE("^" _gfxtag) }
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> atari_vad_device
+
+// device type definition
+DECLARE_DEVICE_TYPE(ATARI_VAD, atari_vad_device)
+
+class atari_vad_device : public device_t, public device_video_interface
+{
+public:
+ // construction/destruction
+ atari_vad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // configuration helpers
+ template<class Object> devcb_base &set_scanline_int_cb(Object &&cb) { return m_scanline_int_cb.set_callback(std::forward<Object>(cb)); }
+
+ // getters
+ tilemap_device &alpha() const { return *m_alpha_tilemap; }
+ tilemap_device &playfield() const { return *m_playfield_tilemap; }
+ tilemap_device &playfield2() const { return *m_playfield2_tilemap; }
+ atari_motion_objects_device &mob() const { return *m_mob; }
+
+ // read/write handlers
+ DECLARE_READ16_MEMBER(control_read);
+ DECLARE_WRITE16_MEMBER(control_write);
+
+ // playfield/alpha tilemap helpers
+ DECLARE_WRITE16_MEMBER(alpha_w);
+ DECLARE_WRITE16_MEMBER(playfield_upper_w);
+ DECLARE_WRITE16_MEMBER(playfield_latched_lsb_w);
+ DECLARE_WRITE16_MEMBER(playfield_latched_msb_w);
+ DECLARE_WRITE16_MEMBER(playfield2_latched_msb_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+ // timer IDs
+ enum
+ {
+ TID_SCANLINE_INT,
+ TID_TILEROW_UPDATE,
+ TID_EOF
+ };
+
+ // internal helpers
+ void internal_control_write(offs_t offset, uint16_t newword);
+ void update_pf_xscrolls();
+ void update_parameter(uint16_t newword);
+ void update_tilerow(emu_timer &timer, int scanline);
+ void eof_update(emu_timer &timer);
+
+ // configuration state
+ devcb_write_line m_scanline_int_cb;
+
+ // internal state
+ optional_device<tilemap_device> m_alpha_tilemap;
+ required_device<tilemap_device> m_playfield_tilemap;
+ optional_device<tilemap_device> m_playfield2_tilemap;
+ optional_device<atari_motion_objects_device> m_mob;
+ optional_shared_ptr<uint16_t> m_eof_data;
+
+ emu_timer * m_scanline_int_timer;
+ emu_timer * m_tilerow_update_timer;
+ emu_timer * m_eof_timer;
+
+ uint32_t m_palette_bank; // which palette bank is enabled
+ //uint32_t m_pf0_xscroll; // playfield 1 xscroll
+ uint32_t m_pf0_xscroll_raw; // playfield 1 xscroll raw value
+ uint32_t m_pf0_yscroll; // playfield 1 yscroll
+ uint32_t m_pf1_xscroll_raw; // playfield 2 xscroll raw value
+ uint32_t m_pf1_yscroll; // playfield 2 yscroll
+ uint32_t m_mo_xscroll; // sprite xscroll
+ uint32_t m_mo_yscroll; // sprite xscroll
+
+ uint16_t m_control[0x40/2]; // control data
+};
+
+
+#endif // MAME_VIDEO_ATARIVAD_H