new WORKING machines (TV Board Games 6-in-1) (#7824)

new WORKING machines
-------
TV Board Games 6-in-1: Silly 6 Pins, Candy Land, Hungry Hungry Hippos, Match 'em, Mixin' Pics, Checkers [Sean Riddle, David Haywood]
TV Board Games 6-in-1: Simon, Battleship, Mouse Trap, Checkers, Link-a-Line, Roll Over [Sean Riddle, David Haywood]
This commit is contained in:
David Haywood 2021-03-02 18:53:31 +00:00 committed by GitHub
parent 323250bbee
commit 2746058dcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 825 additions and 172 deletions

View File

@ -4066,6 +4066,7 @@ files {
createMESSProjects(_target, _subtarget, "tvgames")
files {
MAME_DIR .. "src/mame/drivers/elan_ep3a19a.cpp",
MAME_DIR .. "src/mame/drivers/elan_eu3a14.cpp",
MAME_DIR .. "src/mame/drivers/elan_eu3a05.cpp",
MAME_DIR .. "src/mame/audio/elan_eu3a05.cpp",
@ -4074,6 +4075,8 @@ files {
MAME_DIR .. "src/mame/machine/elan_eu3a05gpio.h",
MAME_DIR .. "src/mame/machine/elan_eu3a05commonsys.cpp",
MAME_DIR .. "src/mame/machine/elan_eu3a05commonsys.h",
MAME_DIR .. "src/mame/machine/elan_ep3a19asys.cpp",
MAME_DIR .. "src/mame/machine/elan_ep3a19asys.h",
MAME_DIR .. "src/mame/machine/elan_eu3a05sys.cpp",
MAME_DIR .. "src/mame/machine/elan_eu3a05sys.h",
MAME_DIR .. "src/mame/machine/elan_eu3a14sys.cpp",

View File

@ -0,0 +1,372 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
#include "emu.h"
#include "cpu/m6502/m6502.h"
//#include "cpu/m6502/m65c02.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "machine/bankdev.h"
#include "audio/elan_eu3a05.h"
#include "machine/elan_eu3a05gpio.h"
#include "machine/elan_ep3a19asys.h"
#include "video/elan_eu3a05vid.h"
class elan_ep3a19a_state : public driver_device
{
public:
elan_ep3a19a_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_sys(*this, "sys"),
m_gpio(*this, "gpio"),
m_maincpu(*this, "maincpu"),
m_screen(*this, "screen"),
m_ram(*this, "ram"),
m_sound(*this, "eu3a05sound"),
m_vid(*this, "vid"),
m_bank(*this, "bank"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette")
{ }
void elan_ep3a19a(machine_config &config);
void init_tvbg();
protected:
// driver_device overrides
virtual void machine_start() override;
virtual void machine_reset() override;
required_device<elan_ep3a19asys_device> m_sys;
required_device<elan_eu3a05gpio_device> m_gpio;
required_device<cpu_device> m_maincpu;
required_device<screen_device> m_screen;
private:
// screen updates
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(interrupt);
// for callback
uint8_t read_full_space(offs_t offset);
void elan_ep3a19a_bank_map(address_map &map);
void elan_ep3a19a_map(address_map &map);
virtual void video_start() override;
required_shared_ptr<uint8_t> m_ram;
required_device<elan_eu3a05_sound_device> m_sound;
required_device<elan_eu3a05vid_device> m_vid;
required_device<address_map_bank_device> m_bank;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
//DECLARE_WRITE_LINE_MEMBER(sound_end0) { m_sys->generate_custom_interrupt(2); }
//DECLARE_WRITE_LINE_MEMBER(sound_end1) { m_sys->generate_custom_interrupt(3); }
//DECLARE_WRITE_LINE_MEMBER(sound_end2) { m_sys->generate_custom_interrupt(4); }
//DECLARE_WRITE_LINE_MEMBER(sound_end3) { m_sys->generate_custom_interrupt(5); }
//DECLARE_WRITE_LINE_MEMBER(sound_end4) { m_sys->generate_custom_interrupt(6); }
//DECLARE_WRITE_LINE_MEMBER(sound_end5) { m_sys->generate_custom_interrupt(7); }
uint8_t nmi_vector_r(offs_t offset)
{
return 0xffd4 >> (offset * 8);
}
};
void elan_ep3a19a_state::video_start()
{
}
uint32_t elan_ep3a19a_state::screen_update(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect)
{
return m_vid->screen_update(screen, bitmap, cliprect);
}
// sound callback
uint8_t elan_ep3a19a_state::read_full_space(offs_t offset)
{
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
return fullbankspace.read_byte(offset);
}
void elan_ep3a19a_state::elan_ep3a19a_map(address_map &map)
{
// can the addresses move around?
map(0x0000, 0x3fff).ram().share("ram");
map(0x4800, 0x49ff).rw(m_vid, FUNC(elan_eu3a05commonvid_device::palette_r), FUNC(elan_eu3a05commonvid_device::palette_w));
map(0x5000, 0x5014).m(m_sys, FUNC(elan_ep3a19asys_device::map)); // including DMA controller
map(0x5020, 0x503f).m(m_vid, FUNC(elan_eu3a05vid_device::map));
// 504x GPIO area?
map(0x5040, 0x5046).rw(m_gpio, FUNC(elan_eu3a05gpio_device::gpio_r), FUNC(elan_eu3a05gpio_device::gpio_w));
// 5047
//map(0x5048, 0x504a).w(m_gpio, FUNC(elan_eu3a05gpio_device::gpio_unk_w));
// 506x unknown
//map(0x5060, 0x506d).ram(); // read/written by tetris (ADC?)
// 508x sound
map(0x5080, 0x50bf).m(m_sound, FUNC(elan_eu3a05_sound_device::map));
//map(0x5000, 0x50ff).ram();
map(0x6000, 0xdfff).m(m_bank, FUNC(address_map_bank_device::amap8));
map(0xe000, 0xffff).rom().region("maincpu", 0x0000);
// not sure how these work, might be a modified 6502 core instead.
//map(0xfffa, 0xfffb).r(m_sys, FUNC(elan_eu3a05commonsys_device::nmi_vector_r)); // custom vectors handled with NMI for now
map(0xfffa, 0xfffb).r(FUNC(elan_ep3a19a_state::nmi_vector_r)); // custom vectors handled with NMI for now
//map(0xfffe, 0xffff).r(m_sys, FUNC(elan_eu3a05commonsys_device::irq_vector_r)); // allow normal IRQ for brk
}
void elan_ep3a19a_state::elan_ep3a19a_bank_map(address_map &map)
{
map(0x000000, 0x3fffff).mirror(0xc00000).noprw();
map(0x000000, 0x3fffff).mirror(0xc00000).rom().region("maincpu", 0);
}
static INPUT_PORTS_START( elan_ep3a19a )
PORT_START("IN0")
PORT_DIPNAME( 0x0001, 0x0001, "IN0" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_START("IN1")
PORT_DIPNAME( 0x0001, 0x0001, "IN1" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_START("IN2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_DIPNAME( 0x0020, 0x0020, "IN2" )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END
void elan_ep3a19a_state::machine_start()
{
}
void elan_ep3a19a_state::machine_reset()
{
m_maincpu->set_state_int(M6502_S, 0x1ff);
}
static const gfx_layout helper_4bpp_8_layout =
{
8,1,
RGN_FRAC(1,1),
4,
{ 0,1,2,3 },
{ STEP8(0,4) },
{ 0 },
8 * 4
};
static const gfx_layout helper_8bpp_8_layout =
{
8,1,
RGN_FRAC(1,1),
8,
{ 0,1,2,3,4,5,6,7 },
{ STEP8(0,8) },
{ 0 },
8 * 8
};
// these are fake just to make looking at the texture pages easier
static const uint32_t texlayout_xoffset_8bpp[256] = { STEP256(0,8) };
static const uint32_t texlayout_yoffset_8bpp[256] = { STEP256(0,256*8) };
static const gfx_layout texture_helper_8bpp_layout =
{
256, 256,
RGN_FRAC(1,1),
8,
{ 0,1,2,3,4,5,6,7 },
EXTENDED_XOFFS,
EXTENDED_YOFFS,
256*256*8,
texlayout_xoffset_8bpp,
texlayout_yoffset_8bpp
};
static const uint32_t texlayout_xoffset_4bpp[256] = { STEP256(0,4) };
static const uint32_t texlayout_yoffset_4bpp[256] = { STEP256(0,256*4) };
static const gfx_layout texture_helper_4bpp_layout =
{
256, 256,
RGN_FRAC(1,1),
4,
{ 0,1,2,3 },
EXTENDED_XOFFS,
EXTENDED_YOFFS,
256*256*4,
texlayout_xoffset_4bpp,
texlayout_yoffset_4bpp
};
static GFXDECODE_START( gfx_elan_eu3a05_fake )
GFXDECODE_ENTRY( "maincpu", 0, helper_4bpp_8_layout, 0x0, 1 )
GFXDECODE_ENTRY( "maincpu", 0, texture_helper_4bpp_layout, 0x0, 1 )
GFXDECODE_ENTRY( "maincpu", 0, helper_8bpp_8_layout, 0x0, 1 )
GFXDECODE_ENTRY( "maincpu", 0, texture_helper_8bpp_layout, 0x0, 1 )
GFXDECODE_END
INTERRUPT_GEN_MEMBER(elan_ep3a19a_state::interrupt)
{
//m_sys->generate_custom_interrupt(9);
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
}
void elan_ep3a19a_state::elan_ep3a19a(machine_config &config)
{
/* basic machine hardware */
M6502(config, m_maincpu, XTAL(21'477'272)/8);
m_maincpu->set_addrmap(AS_PROGRAM, &elan_ep3a19a_state::elan_ep3a19a_map);
m_maincpu->set_vblank_int("screen", FUNC(elan_ep3a19a_state::interrupt));
ADDRESS_MAP_BANK(config, "bank").set_map(&elan_ep3a19a_state::elan_ep3a19a_bank_map).set_options(ENDIANNESS_LITTLE, 8, 24, 0x8000);
PALETTE(config, m_palette).set_entries(256);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
m_screen->set_screen_update(FUNC(elan_ep3a19a_state::screen_update));
m_screen->set_size(32*8, 32*8);
m_screen->set_visarea(0*8, 32*8-1, 0*8, 28*8-1);
m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_elan_eu3a05_fake);
ELAN_EU3A05_GPIO(config, m_gpio, 0);
m_gpio->read_0_callback().set_ioport("IN0");
m_gpio->read_1_callback().set_ioport("IN1");
m_gpio->read_2_callback().set_ioport("IN2");
ELAN_EP3A19A_SYS(config, m_sys, 0);
m_sys->set_cpu("maincpu");
m_sys->set_addrbank("bank");
ELAN_EU3A05_VID(config, m_vid, 0);
m_vid->set_cpu("maincpu");
m_vid->set_addrbank("bank");
m_vid->set_palette("palette");
m_vid->set_entries(256);
m_vid->set_is_pvmilfin();
m_vid->set_use_spritepages();
m_vid->set_force_transpen_ff();
m_vid->set_force_basic_scroll();
/* sound hardware */
SPEAKER(config, "mono").front_center();
ELAN_EU3A05_SOUND(config, m_sound, 8000);
m_sound->space_read_callback().set(FUNC(elan_ep3a19a_state::read_full_space));
m_sound->add_route(ALL_OUTPUTS, "mono", 1.0);
/*
m_sound->sound_end_cb<0>().set(FUNC(elan_ep3a19a_state::sound_end0));
m_sound->sound_end_cb<1>().set(FUNC(elan_ep3a19a_state::sound_end1));
m_sound->sound_end_cb<2>().set(FUNC(elan_ep3a19a_state::sound_end2));
m_sound->sound_end_cb<3>().set(FUNC(elan_ep3a19a_state::sound_end3));
m_sound->sound_end_cb<4>().set(FUNC(elan_ep3a19a_state::sound_end4));
m_sound->sound_end_cb<5>().set(FUNC(elan_ep3a19a_state::sound_end5));
*/
}
ROM_START( tvbg6a )
ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD( "candyland_hhh_silly6.bin", 0x00000, 0x200000, CRC(8b16d725) SHA1(06af509d03df0e5a2ca502743797af9f4a5dc6f1) )
ROM_RELOAD(0x200000,0x200000)
ROM_END
ROM_START( tvbg6b )
ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD( "bship_simon_mousetrap.bin", 0x00000, 0x200000, CRC(b0627a98) SHA1(6157e26916bb415037a4d122d3075cbfb8e61dcf) )
ROM_RELOAD(0x200000,0x200000)
ROM_END
void elan_ep3a19a_state::init_tvbg()
{
// is this swapping internal to the ep3a19a type ELAN, or external; ROM glob had standard TSOP pinout pads that were used for dumping.
uint8_t* ROM = memregion("maincpu")->base();
for (int i = 0; i < 0x400000; i++)
{
ROM[i] = bitswap<8>(ROM[i], 6, 5, 7, 0, 2, 3, 1, 4);
}
}
CONS( 2007, tvbg6a, 0, 0, elan_ep3a19a, elan_ep3a19a, elan_ep3a19a_state, init_tvbg, "NSI International / Mammoth Toys (Licensed by Hasbro)", "TV Board Games 6-in-1: Silly 6 Pins, Candy Land, Hungry Hungry Hippos, Match 'em, Mixin' Pics, Checkers", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // https://www.youtube.com/watch?v=zajzQo47YYA
CONS( 2007, tvbg6b, 0, 0, elan_ep3a19a, elan_ep3a19a, elan_ep3a19a_state, init_tvbg, "NSI International / Mammoth Toys (Licensed by Hasbro)", "TV Board Games 6-in-1: Simon, Battleship, Mouse Trap, Checkers, Link-a-Line, Roll Over", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // https://www.youtube.com/watch?v=JbrR67kY8MI
// TV Board Games 3-in-1: Silly 6 Pins, Hungry Hungry Hippos, Match 'em
// TV Board Games 3-in-1: Simon, Battleship, Checkers https://www.youtube.com/watch?v=Q7nwKJfVavU
// TV Board Games 3-in-1: Boggle, Connect 4, Roll Over https://www.youtube.com/watch?v=SoKKIKSDGhY
// The back of the Silly 6 Pins 3-in-1 packaging suggests a Monopoly TV Board Game device was planned, but this does not appear to have been released.

View File

@ -0,0 +1,117 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
#include "emu.h"
#include "elan_ep3a19asys.h"
// like EU3A05 but with the DMA at a lower address where the code bank register would usually be, and a single byte for bank register rather than 2 - any other changes?
DEFINE_DEVICE_TYPE(ELAN_EP3A19A_SYS, elan_ep3a19asys_device, "elan_ep3a19asys", "Elan EP3A19A System")
elan_ep3a19asys_device::elan_ep3a19asys_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
elan_eu3a05commonsys_device(mconfig, ELAN_EP3A19A_SYS, tag, owner, clock),
device_memory_interface(mconfig, *this),
m_space_config("regs", ENDIANNESS_NATIVE, 8, 5, 0, address_map_constructor(FUNC(elan_ep3a19asys_device::map), this))
{
}
device_memory_interface::space_config_vector elan_ep3a19asys_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(0, &m_space_config)
};
}
void elan_ep3a19asys_device::rombank_w(offs_t offset, uint8_t data)
{
m_rombank_lo = data;
m_bank->set_bank(m_rombank_lo);
}
uint8_t elan_ep3a19asys_device::rombank_r(offs_t offset)
{
return m_rombank_lo;
}
void elan_ep3a19asys_device::map(address_map& map)
{
// elan_eu3a05commonsys_device::map(map); // 00 - 0e
map(0x0c, 0x0c).rw(FUNC(elan_ep3a19asys_device::rombank_r), FUNC(elan_ep3a19asys_device::rombank_w));
map(0x0d, 0x13).rw(FUNC(elan_ep3a19asys_device::dma_param_r), FUNC(elan_ep3a19asys_device::dma_param_w));
map(0x14, 0x14).rw(FUNC(elan_ep3a19asys_device::elan_eu3a05_dmatrg_r), FUNC(elan_ep3a19asys_device::elan_eu3a05_dmatrg_w));
}
void elan_ep3a19asys_device::device_start()
{
elan_eu3a05commonsys_device::device_start();
save_item(NAME(m_dmaparams));
}
void elan_ep3a19asys_device::device_reset()
{
elan_eu3a05commonsys_device::device_reset();
for (int i = 0; i < 7; i++)
m_dmaparams[i] = 0x00;
}
uint8_t elan_ep3a19asys_device::dma_param_r(offs_t offset)
{
return m_dmaparams[offset];
}
void elan_ep3a19asys_device::dma_param_w(offs_t offset, uint8_t data)
{
m_dmaparams[offset] = data;
}
uint8_t elan_ep3a19asys_device::elan_eu3a05_dmatrg_r()
{
logerror("%s: elan_eu3a05_dmatrg_r (DMA operation state?)\n", machine().describe_context());
return 0x00;//m_dmatrg_data;
}
void elan_ep3a19asys_device::elan_eu3a05_dmatrg_w(uint8_t data)
{
logerror("%s: elan_eu3a05_dmatrg_w (trigger DMA operation) %02x\n", machine().describe_context(), data);
//m_dmatrg_data = data;
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
address_space& destspace = m_cpu->space(AS_PROGRAM);
if (data)
{
int src = (m_dmaparams[0]) | (m_dmaparams[1] << 8) | (m_dmaparams[2] << 16);
uint16_t dest = m_dmaparams[3] | (m_dmaparams[4] << 8);
uint16_t size = m_dmaparams[5] | (m_dmaparams[6] << 8);
logerror(" Doing %02x DMA %06x to %04x size %04x\n", data, src, dest, size);
for (int i = 0; i < size; i++)
{
uint8_t dat = fullbankspace.read_byte(src);
src++;
destspace.write_byte(dest, dat);
dest++;
}
m_dmaparams[0] = src & 0xff;
m_dmaparams[1] = (src >> 8) & 0xff;
m_dmaparams[2] = (src >> 16) & 0xff;
m_dmaparams[3] = dest & 0xff;
m_dmaparams[4] = (dest >> 8) & 0xff;
m_dmaparams[5] = 0;
m_dmaparams[6] = 0;
}
}

View File

@ -0,0 +1,38 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
#ifndef MAME_MACHINE_ELAN_EP3A19ASYS_H
#define MAME_MACHINE_ELAN_EP3A19ASYS_H
#include "elan_eu3a05commonsys.h"
class elan_ep3a19asys_device : public elan_eu3a05commonsys_device, public device_memory_interface
{
public:
elan_ep3a19asys_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
uint8_t elan_eu3a05_dmatrg_r();
void elan_eu3a05_dmatrg_w(uint8_t data);
uint8_t dma_param_r(offs_t offset);
void dma_param_w(offs_t offset, uint8_t data);
virtual void map(address_map& map) override;
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual space_config_vector memory_space_config() const override;
void rombank_w(offs_t offset, uint8_t data);
uint8_t rombank_r(offs_t offset);
private:
const address_space_config m_space_config;
uint8_t m_dmaparams[7];
};
DECLARE_DEVICE_TYPE(ELAN_EP3A19A_SYS, elan_ep3a19asys_device)
#endif // MAME_MACHINE_ELAN_EP3A19ASYS_H

View File

@ -13105,6 +13105,10 @@ egghunt // (c) 1995 Invi Image
einst256 //
einstein //
@source:elan_ep3a19a.cpp
tvbg6a
tvbg6b
@source:elan_eu3a14.cpp
rad_gtg
rad_rsg

View File

@ -259,6 +259,7 @@ ec65.cpp
ec7915.cpp
einstein.cpp
eispc.cpp
elan_ep3a19a.cpp
elan_eu3a05.cpp
elan_eu3a14.cpp
electron.cpp

View File

@ -17,7 +17,9 @@ elan_eu3a05vid_device::elan_eu3a05vid_device(const machine_config &mconfig, cons
m_bytes_per_tile_entry(4),
m_vrambase(0x600),
m_spritebase(0x3e00),
m_use_spritepages(false)
m_use_spritepages(false),
m_force_transpen_ff(false),
m_force_basic_scroll(false)
{
}
@ -126,7 +128,7 @@ uint8_t elan_eu3a05vid_device::read_vram(int offset)
that space (Tetris seems to rely on mirroring? as it sets all addresses up for the lower 1MB instead)
*/
void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, bitmap_ind8 &priority_bitmap, const rectangle &cliprect)
{
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
@ -139,11 +141,11 @@ void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bi
XX = texture x start
YY = texture y start
bb = sometimes set in invaders
AA = same as attr on tiles (colour / priority?)
AA = same as attr on tiles (cccc pppp) (c = colour / p = priority?)
aa = same as unk2 on tiles? ( --pp ---- )
p = page
p = page (some hardware types only? or selectable meaning)
FF = flags ( e-dD fFsS )
e = enable
@ -156,7 +158,10 @@ void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bi
*/
for (int i = 0; i < 512; i += 8)
// later in list with AA == 0f aa == 07 takes priority over earlier in the list with AA == 0f and aa == 07
// later in the list with AA == 0e and aa == 17 is under AA == 0f aa == and 07
for (int i = 512-8; i >=0; i -= 8)
{
uint8_t x = read_spriteram(i + 2);
uint8_t y = read_spriteram(i + 1);
@ -188,7 +193,8 @@ void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bi
const int doubleX = (flags & 0x10)>>4;
const int doubleY = (flags & 0x20)>>5;
//int priority = attr & 0x0f;
int priority = (attr & 0x0f)^0xf;
int colour = attr & 0xf0;
// ? game select has this set to 0xff, but clearly doesn't want the palette to change!
@ -204,7 +210,7 @@ void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bi
where the transpen needs to be 0x00 and Space Invaders has it set to 0x04
it could be a global register rather than something in the spritelist?
*/
if ((attr == 0xff) && (unk2 == 0xff))
if (((attr == 0xff) && (unk2 == 0xff)) || m_force_transpen_ff)
transpen = 0xff;
@ -242,14 +248,19 @@ void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bi
for (int yy = 0; yy < sizey; yy++)
{
uint16_t* row;
uint8_t* rowpri;
if (flags & 0x08) // guess flipy
{
row = &bitmap.pix((y + (sizey - 1 - yy)) & 0xff);
int drawypos = (y + (sizey - 1 - yy)) & 0xff;
row = &bitmap.pix(drawypos);
rowpri = &priority_bitmap.pix(drawypos);
}
else
{
row = &bitmap.pix((y + yy) & 0xff);
int drawypos = (y + yy) & 0xff;
row = &bitmap.pix(drawypos);
rowpri = &priority_bitmap.pix(drawypos);
}
for (int xx = 0; xx < sizex; xx++)
@ -272,11 +283,23 @@ void elan_eu3a05vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bi
{
if (flags & 0x04) // flipx
{
row[(x + (sizex - 1 - xx)) & 0xff] = (pix + ((colour & 0x70) << 1)) & 0xff;
int xdrawpos = (x + (sizex - 1 - xx)) & 0xff;
if (rowpri[xdrawpos] > priority)
{
rowpri[xdrawpos] = priority;
row[xdrawpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
}
}
else
{
row[(x + xx) & 0xff] = (pix + ((colour & 0x70) << 1)) & 0xff;
int xdrawpos = (x + xx) & 0xff;
if (rowpri[xdrawpos] > priority)
{
rowpri[xdrawpos] = priority;
row[xdrawpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
}
}
}
}
@ -317,119 +340,11 @@ bool elan_eu3a05vid_device::get_tile_data(int base, int drawpri, int& tile, int
return true;
}
void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect, int drawpri)
{
/*
this doesn't handle 8x8 4bpp (not used by anything yet)
*/
int scroll = get_scroll(1);
void elan_eu3a05vid_device::draw_tilemaps_tileline(int drawpri, int tile, int attr, int unk2, int tilexsize, int i, int xpos, uint16_t* row)
{
address_space& fullbankspace = m_bank->space(AS_PROGRAM);
// Phoenix scrolling actually skips a pixel, jumping from 0x001 to 0x1bf, scroll 0x000 isn't used, maybe it has other meanings?
int totalyrow;
int totalxcol;
int mapyrowsbase;
int tileysize;
int tilexsize;
int startrow;
if (m_vidctrl & 0x40) // 16x16 tiles
{
totalyrow = 16;
totalxcol = 16;
mapyrowsbase = 14;
tileysize = 16;
tilexsize = 16;
startrow = (scroll >> 4) & 0x1f;
}
else
{
totalyrow = 32;
totalxcol = 32;
mapyrowsbase = 28;
tileysize = 8;
tilexsize = 8;
startrow = (scroll >> 3) & 0x3f;
}
for (int y = 0; y < totalyrow; y++)
{
for (int x = 0; x < totalxcol * 2; x++)
{
int realstartrow = (startrow + y);
int yrows;
if (m_vidctrl & 0x01)
yrows = mapyrowsbase;
else
yrows = mapyrowsbase * 2;
if (realstartrow >= yrows)
realstartrow -= yrows;
// in double width & double height mode the page addressing needs adjusting
if (!(m_vidctrl & 0x02))
{
if (!(m_vidctrl & 0x01))
{
if (realstartrow >= (yrows / 2))
{
realstartrow += yrows / 2;
}
}
}
for (int i = 0; i < tileysize; i++)
{
int drawline = (y * tileysize) + i;
drawline -= scroll & (tileysize - 1);
if ((drawline >= 0) && (drawline < 256))
{
int scrollx;
// split can be probably configured in more ways than this
// exact enable conditions unclear
if (drawline < m_splitpos[0])
{
scrollx = get_scroll(0);
}
else if (drawline < m_splitpos[1])
{
scrollx = get_scroll(2);
}
else
{
scrollx = get_scroll(3);
}
int base;
if (m_vidctrl & 0x40) // 16x16 tiles
{
base = (((realstartrow + y) & 0x3f) * 8) + x;
}
else
{
base = (((realstartrow) & 0x7f) * totalxcol) + (x & (totalxcol - 1));
}
if (!(m_vidctrl & 0x02))
{
if (x & totalxcol)
{
base += totalxcol * mapyrowsbase;
}
}
int tile, attr, unk2;
if (!get_tile_data(base, drawpri, tile, attr, unk2))
continue;
int colour = attr & 0xf0;
/* 'tiles' are organized / extracted from 'texture' lines that form a 'page' the length of the rom
@ -457,7 +372,6 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
tile += ((m_tile_gfxbase_lo_data | m_tile_gfxbase_hi_data << 8) << 5);
uint16_t *const row = &bitmap.pix(drawline);
if (m_vidctrl & 0x20) // 4bpp
{
@ -468,13 +382,11 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
int drawxpos;
drawxpos = x * tilexsize + xx + 0 - scrollx;
drawxpos &= 0x1ff;
drawxpos = xpos + xx + 0;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = ((pix & 0xf0) >> 4) + colour;
drawxpos = x * tilexsize + xx + 1 - scrollx;
drawxpos &= 0x1ff;
drawxpos = xpos + xx + 1;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = ((pix & 0x0f) >> 0) + colour;
}
@ -486,14 +398,211 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
int realaddr = ((tile + i * 32) << 3) + xx;
uint8_t pix = fullbankspace.read_byte(realaddr);
int drawxpos = x * tilexsize + xx - scrollx;
drawxpos &= 0x1ff;
int drawxpos = xpos + xx;
if ((drawxpos >= 0) && (drawxpos < 256))
row[drawxpos] = (pix + ((colour & 0x70) << 1)) & 0xff;
}
}
}
uint16_t elan_eu3a05vid_device::get_tilemapindex_from_xy(uint16_t x, uint16_t y)
{
// for mousetrap and candyland the pages in RAM (16x16 tile mode, 4 pages) are
// top left
// top right
// bottom left
// bottom right
// for airblaster joystick 3d stagess the pages in RAM (8x8 tile mode, 2 pages) are
// left
// right
// for airblaster joystick scrolling stages (8x8 tile mode, 2 pages)
// top
// bottom
uint16_t tilemapsizey;
uint16_t tilemapsizex;
uint16_t pagesizey, pagesizex;
pagesizey = 14; pagesizex = 16;
switch (m_vidctrl & 0x03)
{
case 0x00: tilemapsizey = 14 * 2; tilemapsizex = 16 * 2; break; // double height & double width
case 0x02: tilemapsizey = 14 * 2; tilemapsizex = 16; break; // double height
case 0x01: tilemapsizey = 14; tilemapsizex = 16 * 2; break; // double width
case 0x03: tilemapsizey = 14; tilemapsizex = 16; break; // normal
}
if (!(m_vidctrl & 0x40)) // 16x16 tiles
{
pagesizey <<= 1;
pagesizex <<= 1;
tilemapsizey <<= 1;
tilemapsizex <<= 1;
}
while (y >= tilemapsizey)
y -= tilemapsizey;
while (x >= tilemapsizex)
x -= tilemapsizex;
int index = 0;
int page = 0;
switch (m_vidctrl & 0x03)
{
case 0x00: // double height & double width
if (y < pagesizey)
{
if (x < pagesizex)
{
page = 0;
}
else
{
page = 1;
}
}
else
{
if (x < pagesizex)
{
page = 2;
}
else
{
page = 3;
}
}
break;
case 0x02: // double height
if (y < pagesizey)
{
page = 0;
}
else
{
page = 1;
}
break;
case 0x01: // double width
if (x < pagesizex)
{
page = 0;
}
else
{
page = 1;
}
break;
case 0x03:
page = 0;
break;
}
while (y >= pagesizey)
y -= pagesizey;
while (x >= pagesizex)
x -= pagesizex;
index = x + y * pagesizex;
index += page * pagesizey * pagesizex;
return index;
}
void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect, int drawpri)
{
/*
this doesn't handle 8x8 4bpp (not used by anything yet)
*/
//popmessage("%02x: %04x %04x %04x %04x", m_vidctrl, get_scroll(0), get_scroll(1), get_scroll(2), get_scroll(3));
int scrolly = get_scroll(1);
for (int screenline = 0; screenline < 224; screenline++)
{
int scrollx;
int coursescrollx;
int finescrollx;
int realline = screenline + scrolly;
// split can be probably configured in more ways than this
// exact enable conditions unclear
// this logic is needed for Air Blaster Joystick
if (screenline < m_splitpos[0])
{
scrollx = get_scroll(0);
}
else if (screenline < m_splitpos[1])
{
scrollx = get_scroll(2);
}
else
{
scrollx = get_scroll(3);
}
// Candy Land and Mouse Trap in the TV Board Games units don't like the above logic, so force them to just use the
// first scroll register for now, there must be more complex enable conditions for the above
if (m_force_basic_scroll)
scrollx = get_scroll(0);
uint16_t* row = &bitmap.pix(screenline);
int xtiles;
int xtilesize;
if (m_vidctrl & 0x40) // 16x16 tiles
{
xtiles = 16; // number of tilemap entries per row
xtilesize = 16; // width of tile
coursescrollx = scrollx >> 4;
finescrollx = scrollx & 0xf;
}
else
{
xtiles = 32;
xtilesize = 8;
coursescrollx = scrollx >> 3;
finescrollx = scrollx & 0x7;
}
for (int xtile = 0; xtile <= xtiles; xtile++)
{
int realxtile = xtile + coursescrollx;
int tilemaprow;
int tileline;
if (m_vidctrl & 0x40) // 16x16 tiles
{
tilemaprow = realline >> 4;
tileline = realline & 0xf;
}
else
{
tilemaprow = realline >> 3;
tileline = realline & 0x7;
}
int tilemap_entry_index = get_tilemapindex_from_xy(realxtile, tilemaprow);
int tile, attr, unk2;
if (!get_tile_data(tilemap_entry_index, drawpri, tile, attr, unk2))
continue;
int xpos = xtile * xtilesize - finescrollx;
draw_tilemaps_tileline(drawpri, tile, attr, unk2, xtilesize, tileline, xpos, row);
}
}
}
@ -501,10 +610,11 @@ void elan_eu3a05vid_device::draw_tilemaps(screen_device& screen, bitmap_ind16& b
uint32_t elan_eu3a05vid_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
screen.priority().fill(0xff, cliprect);
draw_tilemaps(screen,bitmap,cliprect,0);
draw_sprites(screen,bitmap,cliprect);
draw_tilemaps(screen,bitmap,cliprect,1);
draw_tilemaps(screen,bitmap,cliprect,0); // 'low priority'
draw_sprites(screen,bitmap,screen.priority(),cliprect);
draw_tilemaps(screen,bitmap,cliprect,1); // 'high priority'
return 0;
}
@ -572,6 +682,7 @@ uint8_t elan_eu3a05vid_device::tile_scroll_r(offs_t offset)
void elan_eu3a05vid_device::tile_scroll_w(offs_t offset, uint8_t data)
{
//logerror("tile_scroll_w %02x %02x\n", offset, data);
m_tile_scroll[offset] = data;
}

View File

@ -7,6 +7,7 @@
#include "elan_eu3a05commonvid.h"
#include "cpu/m6502/m6502.h"
#include "machine/bankdev.h"
#include "screen.h"
class elan_eu3a05vid_device : public elan_eu3a05commonvid_device, public device_memory_interface
{
@ -23,6 +24,8 @@ public:
void set_is_sudoku();
void set_is_pvmilfin();
void set_use_spritepages() { m_use_spritepages = true; };
void set_force_transpen_ff() { m_force_transpen_ff = true; };
void set_force_basic_scroll() { m_force_basic_scroll = true; };
protected:
// device-level overrides
@ -51,7 +54,9 @@ private:
bool get_tile_data(int base, int drawpri, int& tile, int &attr, int &unk2);
void draw_tilemaps(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int drawpri);
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, bitmap_ind8 &priority_bitmap, const rectangle &cliprect);
void draw_tilemaps_tileline(int drawpri, int tile, int attr, int unk2, int tilexsize, int tileline, int xpos, uint16_t *row);
uint16_t get_tilemapindex_from_xy(uint16_t x, uint16_t y);
uint8_t read_spriteram(int offset);
uint8_t read_vram(int offset);
@ -84,6 +89,8 @@ private:
int m_vrambase;
int m_spritebase;
bool m_use_spritepages;
bool m_force_transpen_ff;
bool m_force_basic_scroll;
};
DECLARE_DEVICE_TYPE(ELAN_EU3A05_VID, elan_eu3a05vid_device)