From eb7894d1267a695587ff97ee3e29cb32a9a64863 Mon Sep 17 00:00:00 2001 From: David Haywood Date: Thu, 11 Jan 2018 04:27:59 +0000 Subject: [PATCH] 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) --- scripts/target/mame/mess.lua | 1 + src/mame/drivers/radicasi.cpp | 294 ++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + 3 files changed, 298 insertions(+) create mode 100644 src/mame/drivers/radicasi.cpp diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 3a2d48845b8..1a3f5cd9ce4 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -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", diff --git a/src/mame/drivers/radicasi.cpp b/src/mame/drivers/radicasi.cpp new file mode 100644 index 00000000000..a96e70ed5ec --- /dev/null +++ b/src/mame/drivers/radicasi.cpp @@ -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 m_maincpu; + required_shared_ptr m_ram; + required_shared_ptr m_pixram; + required_device m_bank; + required_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 ) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 6cda74d780a..b60ad3cb88b 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -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 //