summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/pengadvb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/pengadvb.cpp')
-rw-r--r--src/mame/drivers/pengadvb.cpp344
1 files changed, 344 insertions, 0 deletions
diff --git a/src/mame/drivers/pengadvb.cpp b/src/mame/drivers/pengadvb.cpp
new file mode 100644
index 00000000000..de6ca0e094a
--- /dev/null
+++ b/src/mame/drivers/pengadvb.cpp
@@ -0,0 +1,344 @@
+// license:BSD-3-Clause
+// copyright-holders:Mariusz Wojcieszek, hap
+/***************************************************************************
+
+Penguin Adventure bootleg (tagged 'Screen', 1988)
+Original release was on MSX, by Konami in 1986. There is no official arcade release of this game.
+
+Driver by Mariusz Wojcieszek
+
+This seems to be the MSX version hacked to run on cheap Korean(?) bootleg hardware.
+Bosses are at wrong stages when compared to the original, probably to make the game more
+difficult early on. This is also the cause of some gfx glitches when reaching a boss.
+
+Basic components include.....
+Z80 @ 3.579533MHz [10.7386/3]
+TMS9128 @ 10.7386MHz
+AY-3-8910 @ 1.789766MHz [10.7386/6]
+8255
+4416 RAM x2
+4164 RAM x8
+10.7386 XTAL
+10 position DIPSW
+NOTE! switches 1, 3 & 5 must be ON or the game will not boot.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cpu/z80/z80.h"
+#include "video/tms9928a.h"
+#include "sound/ay8910.h"
+#include "machine/i8255.h"
+#include "machine/bankdev.h"
+
+
+class pengadvb_state : public driver_device
+{
+public:
+ pengadvb_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu")
+ { }
+
+ required_device<cpu_device> m_maincpu;
+
+ address_map_bank_device *m_page[4];
+ memory_bank *m_bank[4];
+ UINT8 m_primary_slot_reg;
+ UINT8 m_kb_matrix_row;
+
+ DECLARE_READ8_MEMBER(mem_r);
+ DECLARE_WRITE8_MEMBER(mem_w);
+ DECLARE_WRITE8_MEMBER(megarom_bank_w);
+
+ DECLARE_WRITE8_MEMBER(pengadvb_psg_port_b_w);
+ DECLARE_READ8_MEMBER(pengadvb_ppi_port_a_r);
+ DECLARE_WRITE8_MEMBER(pengadvb_ppi_port_a_w);
+ DECLARE_READ8_MEMBER(pengadvb_ppi_port_b_r);
+ DECLARE_WRITE8_MEMBER(pengadvb_ppi_port_c_w);
+
+ DECLARE_WRITE_LINE_MEMBER(vdp_interrupt);
+ DECLARE_DRIVER_INIT(pengadvb);
+ virtual void machine_start();
+ virtual void machine_reset();
+ void pengadvb_decrypt(const char* region);
+};
+
+
+/***************************************************************************
+
+ Z80 Memory map
+
+***************************************************************************/
+
+READ8_MEMBER(pengadvb_state::mem_r)
+{
+ return m_page[offset >> 14 & 3]->read8(space, offset);
+}
+
+WRITE8_MEMBER(pengadvb_state::mem_w)
+{
+ m_page[offset >> 14 & 3]->write8(space, offset, data);
+}
+
+WRITE8_MEMBER(pengadvb_state::megarom_bank_w)
+{
+ m_bank[offset >> 13 & 3]->set_entry(data & 0xf);
+}
+
+static ADDRESS_MAP_START( program_mem, AS_PROGRAM, 8, pengadvb_state )
+ AM_RANGE(0x0000, 0xffff) AM_READWRITE(mem_r, mem_w) // 4 pages of 16KB
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( bank_mem, AS_PROGRAM, 8, pengadvb_state )
+ // slot 0, MSX BIOS
+ AM_RANGE(0x00000, 0x07fff) AM_ROM AM_REGION("maincpu", 0)
+
+ // slot 1, MegaROM
+ AM_RANGE(0x14000, 0x15fff) AM_ROMBANK("bank0")
+ AM_RANGE(0x16000, 0x17fff) AM_ROMBANK("bank1")
+ AM_RANGE(0x18000, 0x19fff) AM_ROMBANK("bank2")
+ AM_RANGE(0x1a000, 0x1bfff) AM_ROMBANK("bank3")
+ AM_RANGE(0x14000, 0x1bfff) AM_WRITE(megarom_bank_w)
+
+ // slot 3, 16KB RAM
+ AM_RANGE(0x3c000, 0x3ffff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( io_mem, AS_IO, 8, pengadvb_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ AM_RANGE(0x98, 0x98) AM_DEVREADWRITE("tms9128", tms9128_device, vram_read, vram_write)
+ AM_RANGE(0x99, 0x99) AM_DEVREADWRITE("tms9128", tms9128_device, register_read, register_write)
+ AM_RANGE(0xa0, 0xa1) AM_DEVWRITE("aysnd", ay8910_device, address_data_w)
+ AM_RANGE(0xa2, 0xa2) AM_DEVREAD("aysnd", ay8910_device, data_r)
+ AM_RANGE(0xa8, 0xab) AM_DEVREADWRITE("ppi8255", i8255_device, read, write)
+ADDRESS_MAP_END
+
+
+/***************************************************************************
+
+ Inputs
+
+***************************************************************************/
+
+static INPUT_PORTS_START( pengadvb )
+ 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(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("IN1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_COIN1) PORT_IMPULSE(1)
+ PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+/***************************************************************************
+
+ IC Interfaces
+
+***************************************************************************/
+
+// AY8910
+WRITE8_MEMBER(pengadvb_state::pengadvb_psg_port_b_w)
+{
+ // leftover from msx ver?
+}
+
+/**************************************************************************/
+
+// I8255
+READ8_MEMBER(pengadvb_state::pengadvb_ppi_port_a_r)
+{
+ return m_primary_slot_reg;
+}
+
+WRITE8_MEMBER(pengadvb_state::pengadvb_ppi_port_a_w)
+{
+ if (data != m_primary_slot_reg)
+ {
+ for (int i = 0; i < 4; i++)
+ m_page[i]->set_bank(data >> (i * 2) & 3);
+
+ m_primary_slot_reg = data;
+ }
+}
+
+READ8_MEMBER(pengadvb_state::pengadvb_ppi_port_b_r)
+{
+ // TODO: dipswitch
+ switch (m_kb_matrix_row)
+ {
+ case 0x0:
+ return ioport("IN1")->read();
+
+ default:
+ break;
+ }
+
+ return 0xff;
+}
+
+WRITE8_MEMBER(pengadvb_state::pengadvb_ppi_port_c_w)
+{
+ m_kb_matrix_row = data & 0x0f;
+}
+
+/**************************************************************************/
+
+// TMS9928
+WRITE_LINE_MEMBER(pengadvb_state::vdp_interrupt)
+{
+ m_maincpu->set_input_line(0, (state ? ASSERT_LINE : CLEAR_LINE));
+}
+
+/***************************************************************************
+
+ Machine config(s)
+
+***************************************************************************/
+
+static MACHINE_CONFIG_START( pengadvb, pengadvb_state )
+
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", Z80, XTAL_10_738635MHz/3)
+ MCFG_CPU_PROGRAM_MAP(program_mem)
+ MCFG_CPU_IO_MAP(io_mem)
+
+ // -_-;
+ MCFG_DEVICE_ADD("page0", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(bank_mem)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
+ MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(18)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x10000)
+
+ MCFG_DEVICE_ADD("page1", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(bank_mem)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
+ MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(18)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x10000)
+
+ MCFG_DEVICE_ADD("page2", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(bank_mem)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
+ MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(18)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x10000)
+
+ MCFG_DEVICE_ADD("page3", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(bank_mem)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
+ MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(18)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x10000)
+
+ MCFG_DEVICE_ADD("ppi8255", I8255, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(pengadvb_state, pengadvb_ppi_port_a_r))
+ MCFG_I8255_OUT_PORTA_CB(WRITE8(pengadvb_state, pengadvb_ppi_port_a_w))
+ MCFG_I8255_IN_PORTB_CB(READ8(pengadvb_state, pengadvb_ppi_port_b_r))
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(pengadvb_state, pengadvb_ppi_port_c_w))
+
+ /* video hardware */
+ MCFG_DEVICE_ADD("tms9128", TMS9128, XTAL_10_738635MHz / 2)
+ MCFG_TMS9928A_VRAM_SIZE(0x4000)
+ MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(pengadvb_state, vdp_interrupt))
+ MCFG_TMS9928A_SCREEN_ADD_NTSC( "screen" )
+ MCFG_SCREEN_UPDATE_DEVICE("tms9128", tms9128_device, screen_update)
+
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("aysnd", AY8910, XTAL_10_738635MHz/6)
+ MCFG_AY8910_PORT_A_READ_CB(IOPORT("IN0"))
+ MCFG_AY8910_PORT_B_WRITE_CB(WRITE8(pengadvb_state, pengadvb_psg_port_b_w))
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_CONFIG_END
+
+
+/***************************************************************************
+
+ Machine start/init
+
+***************************************************************************/
+
+void pengadvb_state::machine_start()
+{
+ save_item(NAME(m_primary_slot_reg));
+ save_item(NAME(m_kb_matrix_row));
+}
+
+void pengadvb_state::machine_reset()
+{
+ m_primary_slot_reg = 0;
+ m_kb_matrix_row = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_page[i]->set_bank(0);
+ m_bank[i]->set_entry(i);
+ }
+}
+
+void pengadvb_state::pengadvb_decrypt(const char* region)
+{
+ UINT8 *mem = memregion(region)->base();
+ int memsize = memregion(region)->bytes();
+
+ // data lines swap
+ for (int i = 0; i < memsize; i++)
+ {
+ mem[i] = BITSWAP8(mem[i],7,6,5,3,4,2,1,0);
+ }
+
+ // address line swap
+ dynamic_buffer buf(memsize);
+ memcpy(&buf[0], mem, memsize);
+ for (int i = 0; i < memsize; i++)
+ {
+ mem[i] = buf[BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,5,11,10,9,8,7,6,12,4,3,2,1,0)];
+ }
+}
+
+DRIVER_INIT_MEMBER(pengadvb_state,pengadvb)
+{
+ pengadvb_decrypt("maincpu");
+ pengadvb_decrypt("game");
+
+ // init banks
+ static const char * const pagenames[] = { "page0", "page1", "page2", "page3" };
+ static const char * const banknames[] = { "bank0", "bank1", "bank2", "bank3" };
+ for (int i = 0; i < 4; i++)
+ {
+ m_page[i] = machine().device<address_map_bank_device>(pagenames[i]);
+
+ m_bank[i] = membank(banknames[i]);
+ m_bank[i]->configure_entries(0, 0x10, memregion("game")->base(), 0x2000);
+ }
+}
+
+
+/***************************************************************************
+
+ Game driver(s)
+
+***************************************************************************/
+
+ROM_START( pengadvb )
+ ROM_REGION( 0x8000, "maincpu", 0 )
+ ROM_LOAD( "rom.u5", 0x00000, 0x8000, CRC(d21950d2) SHA1(0b1815677f17a680ba63c3839bea2d451813eec8) )
+
+ ROM_REGION( 0x20000, "game", 0 )
+ ROM_LOAD( "rom.u7", 0x00000, 0x8000, CRC(d4b4a4a4) SHA1(59f9299182fd8aedc7a4e9b0ddd685f2a71c033f) )
+ ROM_LOAD( "rom.u8", 0x08000, 0x8000, CRC(eada2232) SHA1(f4182f0921b621acd8be6077eb9639b31a97e907) )
+ ROM_LOAD( "rom.u9", 0x10000, 0x8000, CRC(6478c561) SHA1(6f9a794a5bb51e96552f6d1e9fa6515659d25933) )
+ ROM_LOAD( "rom.u10", 0x18000, 0x8000, CRC(5c48360f) SHA1(0866e20969f57b7b7c59df8f7ca203f18c7c9870) )
+ROM_END
+
+
+GAME( 1988, pengadvb, 0, pengadvb, pengadvb, pengadvb_state, pengadvb, ROT0, "bootleg (Screen) / Konami", "Penguin Adventure (bootleg of MSX version)", MACHINE_SUPPORTS_SAVE )