new NOT WORKING Space Invaders (Radica, Arcade Legends TV Game) [Team Europe, Sean Riddle] (#3036)

* new NOT WORKING
Space Invaders (Radica, Arcade Legends TV Game) [Team Europe, Sean Riddle]

(not sure what this is really called, it's a 5-in-1, it probably contains a customized 6502 core, or there should be an internal bootstrap rom)

* typo (nw)

* based on a jump to e092 which looks like it should maybe skip an opcode this seems a more possible mapping (nw)

* actually vectors are right there (nw)

* memory map improvements (nw)

* various notes etc. (nw)

* various banking bits (nw)

* actually remember to hook up the read (nw)

* clearly inputs (nw)

* show that the game is actually running, even if we don't understand the video format, there's clearly some kind of tilemap structure in ram (nw)

* this is bitmap ram on qix (nw)

* didn't mean to change this (nw)

* gfx are stored more like texture pages?! (nw)
This commit is contained in:
David Haywood 2018-01-11 04:27:59 +00:00 committed by R. Belmont
parent da0f38a64d
commit eb7894d126
3 changed files with 298 additions and 0 deletions

View File

@ -3611,6 +3611,7 @@ files {
MAME_DIR .. "src/mame/drivers/qtsbc.cpp",
MAME_DIR .. "src/mame/drivers/qvt6800.cpp",
MAME_DIR .. "src/mame/drivers/rd100.cpp",
MAME_DIR .. "src/mame/drivers/radicasi.cpp",
MAME_DIR .. "src/mame/drivers/rvoice.cpp",
MAME_DIR .. "src/mame/drivers/sacstate.cpp",
MAME_DIR .. "src/mame/drivers/sbrain.cpp",

View File

@ -0,0 +1,294 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood, R.Belmont
#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "screen.h"
#include "speaker.h"
#include "machine/bankdev.h"
//#include "cpu/m6502/r65c02.h"
class radicasi_state : public driver_device
{
public:
radicasi_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_ram(*this, "ram"),
m_pixram(*this, "pixram"),
m_bank(*this, "bank"),
m_gfxdecode(*this, "gfxdecode")
{ }
// screen updates
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE8_MEMBER(radicasi_500c_w);
DECLARE_WRITE8_MEMBER(radicasi_500d_w);
DECLARE_READ8_MEMBER(radicasi_500d_r);
DECLARE_READ8_MEMBER(radicasi_50a8_r);
protected:
// driver_device overrides
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
private:
required_device<cpu_device> m_maincpu;
required_shared_ptr<uint8_t> m_ram;
required_shared_ptr<uint8_t> m_pixram;
required_device<address_map_bank_device> m_bank;
required_device<gfxdecode_device> m_gfxdecode;
uint8_t m_500d_data;
int m_hackmode;
};
void radicasi_state::video_start()
{
m_hackmode = 0;
}
uint32_t radicasi_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
bitmap.fill(0, cliprect);
if (machine().input().code_pressed_once(KEYCODE_Q))
{
m_hackmode++;
m_hackmode &= 3;
}
// it is unclear if the tilemap is an internal structure or something actually used by the video rendering
int offs = 0x600;
if (m_hackmode == 0) // 16x16 tiles (menu)
{
gfx_element *gfx = m_gfxdecode->gfx(1);
for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
int tile = m_ram[offs];
gfx->transpen(bitmap, cliprect, tile, 0, 0, 0, x * 16, y * 16, 0);
offs += 4;
}
}
}
else if (m_hackmode == 1) // 8x8 tiles (games?)
{
gfx_element *gfx = m_gfxdecode->gfx(0);
for (int y = 0; y < 32; y++)
{
for (int x = 0; x < 32; x++)
{
int tile = m_ram[offs];
gfx->transpen(bitmap, cliprect, tile, 0, 0, 0, x * 8, y * 8, 0);
offs += 4;
}
}
}
else if (m_hackmode == 2) // qix
{
for (int y = 0; y < 224; y++)
{
uint16_t* row = &bitmap.pix16(y);
for (int x = 0; x < 256; x++)
{
int pixel = m_pixram[offs];
if (pixel) row[x] = pixel;
offs++;
}
}
}
return 0;
}
WRITE8_MEMBER(radicasi_state::radicasi_500c_w)
{
// written with the banking?
logerror("%s: radicasi_500c_w %02x\n", machine().describe_context().c_str(), data);
m_bank->set_bank(m_500d_data);
}
READ8_MEMBER(radicasi_state::radicasi_500d_r)
{
return m_500d_data;
}
WRITE8_MEMBER(radicasi_state::radicasi_500d_w)
{
logerror("%s: radicasi_500d_w %02x\n", machine().describe_context().c_str(), data);
m_500d_data = data;
}
READ8_MEMBER(radicasi_state::radicasi_50a8_r)
{
logerror("%s: radicasi_50a8_r\n", machine().describe_context().c_str());
return 0x3f;
}
static ADDRESS_MAP_START( radicasi_map, AS_PROGRAM, 8, radicasi_state )
AM_RANGE(0x0000, 0x3fff) AM_RAM AM_SHARE("ram") // ends up copying code to ram, but could be due to banking issues
AM_RANGE(0x4800, 0x49ff) AM_RAM
AM_RANGE(0x500c, 0x500c) AM_WRITE(radicasi_500c_w)
AM_RANGE(0x500d, 0x500d) AM_READWRITE(radicasi_500d_r, radicasi_500d_w)
AM_RANGE(0x5041, 0x5041) AM_READ_PORT("IN0") // AM_READ(radicasi_5041_r)
AM_RANGE(0x50a8, 0x50a8) AM_READ(radicasi_50a8_r)
AM_RANGE(0x6000, 0xdfff) AM_DEVICE("bank", address_map_bank_device, amap8)
AM_RANGE(0xe000, 0xffff) AM_ROM AM_REGION("maincpu", 0xf8000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( radicasi_bank_map, AS_PROGRAM, 8, radicasi_state )
AM_RANGE(0x000000, 0x00ffff) AM_RAM AM_SHARE("pixram") // qix accesses here when 500c is 01 (which could be an additional bank bit)
AM_RANGE(0x300000, 0x3fffff) AM_ROM AM_REGION("maincpu", 0)
AM_RANGE(0x400000, 0x40ffff) AM_RAM // could be tileram? or spriteram? only cleared tho, so would be populated with DMA?
ADDRESS_MAP_END
static INPUT_PORTS_START( radicasi )
PORT_START("IN0")
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_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 )
INPUT_PORTS_END
void radicasi_state::machine_start()
{
uint8_t *rom = memregion("maincpu")->base();
/* both NMI and IRQ vectors just point to RTI
there is a table of jumps just before that, those appear to be the real interrupt functions?
patch the main IRQ to be the one that decreases an address the code is waiting for
the others look like they might be timer service routines
*/
rom[0xf9ffe] = 0xd4;
rom[0xf9fff] = 0xff;
/*
d8000-dffff maps to 6000-dfff
e0000-e7fff maps to 6000-dfff
e8000-effff maps to 6000-dfff
f0000-f7fff maps to 6000-dfff
f8000-fffff maps to 6000-dfff (but f8000-f9fff mapping to 6000-7fff isn't used, because it's the fixed area below - make sure nothing else gets mapped there instead)
-- fixed
f8000-f9fff maps to e000-ffff
*/
m_bank->set_bank(0x7f);
}
void radicasi_state::machine_reset()
{
}
// these are fake, should be decoded from RAM, or not tile based (although game does seem to have 'tilemap' structures in RAM
static const gfx_layout helper_layout =
{
8,8,
RGN_FRAC(1,1),
4,
{ 0,1,2,3 },
{ STEP8(0,4) },
{ STEP8(0,32) },
8 * 32
};
static const gfx_layout helper2_layout =
{
16,16,
RGN_FRAC(1,1),
4,
{ 0,1,2,3 },
{ STEP16(0,4) },
{ STEP16(0,64) },
16 * 64
};
static const uint32_t texlayout_xoffset[256] = { STEP256(0,8) };
static const uint32_t texlayout_yoffset[256] = { STEP256(0,256*8) };
static const gfx_layout helper3_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,
texlayout_yoffset
};
static GFXDECODE_START( radicasi_fake )
GFXDECODE_ENTRY( "maincpu", 0, helper_layout, 0x0, 1 )
GFXDECODE_ENTRY( "maincpu", 0, helper2_layout, 0x0, 1 )
GFXDECODE_ENTRY( "maincpu", 0, helper3_layout, 0x0, 1 )
GFXDECODE_END
static MACHINE_CONFIG_START( radicasi )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu",M6502,8000000) // unknown frequency
MCFG_CPU_PROGRAM_MAP(radicasi_map)
MCFG_CPU_VBLANK_INT_DRIVER("screen", radicasi_state, irq0_line_hold)
MCFG_DEVICE_ADD("bank", ADDRESS_MAP_BANK, 0)
MCFG_DEVICE_PROGRAM_MAP(radicasi_bank_map)
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
MCFG_ADDRESS_MAP_BANK_DATA_WIDTH(8)
MCFG_ADDRESS_MAP_BANK_ADDR_WIDTH(32)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x8000)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500))
MCFG_SCREEN_UPDATE_DRIVER(radicasi_state, screen_update)
MCFG_SCREEN_SIZE(32*8, 32*8)
MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1)
MCFG_SCREEN_PALETTE("palette")
MCFG_PALETTE_ADD("palette", 256)
MCFG_GFXDECODE_ADD("gfxdecode", "palette", radicasi_fake)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MACHINE_CONFIG_END
ROM_START( radicasi )
ROM_REGION( 0x100000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD( "spaceinvadersrom.bin", 0x000000, 0x100000, CRC(5ffb2c8f) SHA1(9bde42ec5c65d9584a802de7d7c8b842ebf8cbd8) )
ROM_END
CONS( 200?, radicasi, 0, 0, radicasi, radicasi, radicasi_state, 0, "Radica (licensed from Taito)", "Space Invaders (Radica, Arcade Legends TV Game)", MACHINE_IS_SKELETON )

View File

@ -32402,6 +32402,9 @@ r9751 // ROLM 9751 phone system
@source:rabbit.cpp
rabbit // (c) 1997 Electronic Arts
@source:radicasi.cpp
radicasi
@source:radio86.cpp
impuls03 //
kr03 //