diff options
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 |
commit | bc2acfcb76b3a69ff48f48cb70cbc257b5c75a07 (patch) | |
tree | 49bc3af4b7dc032dd49c423a963962e96f738327 | |
parent | 00286343c14cb3d70930c76668d9364cc29a2c0e (diff) |
atarivad: Separate source files from atarigen (nw)
-rw-r--r-- | scripts/target/mame/arcade.lua | 2 | ||||
-rw-r--r-- | src/mame/includes/batman.h | 3 | ||||
-rw-r--r-- | src/mame/includes/cybstorm.h | 3 | ||||
-rw-r--r-- | src/mame/includes/offtwall.h | 3 | ||||
-rw-r--r-- | src/mame/includes/relief.h | 4 | ||||
-rw-r--r-- | src/mame/includes/shuuz.h | 1 | ||||
-rw-r--r-- | src/mame/includes/thunderj.h | 2 | ||||
-rw-r--r-- | src/mame/machine/atarigen.cpp | 478 | ||||
-rw-r--r-- | src/mame/machine/atarigen.h | 130 | ||||
-rw-r--r-- | src/mame/video/atarivad.cpp | 490 | ||||
-rw-r--r-- | src/mame/video/atarivad.h | 146 |
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 |