diff --git a/src/mame/drivers/dreamwld.cpp b/src/mame/drivers/dreamwld.cpp index 38b5e7d8781..d26c5ecec0d 100644 --- a/src/mame/drivers/dreamwld.cpp +++ b/src/mame/drivers/dreamwld.cpp @@ -94,6 +94,13 @@ Stephh's notes (based on the game M68EC020 code and some tests) : appear to support it properly either, so it might be missing on these clone boards. + At least based on the dumped Dream World MCU code, the internal ROM + doesn't appear to do any kind of bounds checking when reading out the data + table, so assuming no read address lock up the MCU you could probably just + overflow the counter to read out internal ROM. Also compared to earlier + SemiCom MCUs the code is minimal, just 0x3a bytes and the payload table, + no header with the game title, programmer name or date. + */ #include "emu.h" @@ -117,11 +124,11 @@ public: , m_vregs(*this, "vregs") , m_workram(*this, "workram") , m_lineram(*this, "lineram", 32) - , m_prot(*this, "prot") , m_spritelut(*this, "spritelut") , m_okibank(*this, "oki%ubank", 1) , m_dsw(*this, "DSW") , m_maincpu(*this, "maincpu") + , m_mcu(*this, "mcu") , m_gfxdecode(*this, "gfxdecode") , m_palette(*this, "palette") { @@ -143,8 +150,6 @@ private: required_shared_ptr m_vregs; required_shared_ptr m_workram; required_shared_ptr m_lineram; - - optional_memory_region m_prot; required_memory_region m_spritelut; optional_memory_bank_array<2> m_okibank; required_ioport m_dsw; @@ -161,12 +166,22 @@ private: std::unique_ptr m_spritebuf[2]; /* misc */ - int m_protindex; + uint8_t m_port1_data; + uint8_t m_port2_data; + uint8_t m_protlatch; required_device m_maincpu; + required_device m_mcu; required_device m_gfxdecode; required_device m_palette; + DECLARE_WRITE8_MEMBER(prot_p1_w); + DECLARE_WRITE8_MEMBER(prot_p2_w); + DECLARE_READ8_MEMBER(prot_p2_r); + + DECLARE_WRITE32_MEMBER(to_prot_w); + + template u16 vram_r(offs_t offset); template void vram_w(offs_t offset, u16 data, u16 mem_mask = ~0); u32 protdata_r(); @@ -375,23 +390,7 @@ u32 dreamwld_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c } -u32 dreamwld_state::protdata_r() -{ - //static int count = 0; - size_t protsize = m_prot->bytes(); - const u8 dat = m_prot->base()[m_protindex]; - - if (!machine().side_effects_disabled()) - m_protindex = (m_protindex + 1) % protsize; - //printf("protection read %04x %02x\n", count, dat); - //count++; - - // real hw returns 00 after end of data, I haven't checked if it's possible to overflow the read counter - // and read out the internal rom. - - return dat << 24; -} void dreamwld_state::oki1_map(address_map &map) { @@ -429,6 +428,8 @@ void dreamwld_state::baryon_map(address_map &map) map(0xc0000f, 0xc0000f).w(FUNC(dreamwld_state::okibank_w<0>)); // sfx map(0xc00018, 0xc00018).rw("oki1", FUNC(okim6295_device::read), FUNC(okim6295_device::write)); // sfx + // C00010 might reset the MCU? + map(0xc00020, 0xc00023).w(FUNC(dreamwld_state::to_prot_w)); map(0xc00030, 0xc00033).r(FUNC(dreamwld_state::protdata_r)); // it reads protection data (irq code) from here and puts it at ffd000 map(0xfe0000, 0xffffff).ram().share("workram"); // work ram @@ -723,7 +724,10 @@ void dreamwld_state::machine_start() m_okibank[1]->set_entry(0); } - save_item(NAME(m_protindex)); + save_item(NAME(m_port1_data)); + save_item(NAME(m_port2_data)); + save_item(NAME(m_protlatch)); + save_item(NAME(m_tilebank)); save_item(NAME(m_tilebankold)); } @@ -732,7 +736,69 @@ void dreamwld_state::machine_reset() { m_tilebankold[0] = m_tilebankold[1] = -1; m_tilebank[0] = m_tilebank[1] = 0; - m_protindex = 0; + m_port1_data = 0; + m_port2_data = 0; + m_protlatch = 0; +} + +WRITE8_MEMBER(dreamwld_state::prot_p1_w) +{ + logerror("%s:prot_p1_w %02x\n", machine().describe_context(), data); + m_port1_data = data; +} + +WRITE8_MEMBER(dreamwld_state::prot_p2_w) +{ + logerror("%s:prot_p2_w %02x\n", machine().describe_context(), data); + + for (int bit = 0; bit < 8; bit++) + { + if ((m_port2_data & (1 << bit)) != (data & (1 << bit))) + { + if (data & (1 << bit)) + { + logerror("bit %d low to high\n", bit); + + // bit == 0 is toggled before reading from port 0 (data not used, maybe reads whatever was written on to_prot_w into port 0 for reading tho) + + if (bit == 1) // toggled after writing a byte on port 1 + { + m_protlatch = m_port1_data; + } + } + else + { + logerror("bit %d high to low\n", bit); + } + } + } + + m_port2_data = data; +} + +READ8_MEMBER(dreamwld_state::prot_p2_r) +{ + // bit 2 is waited on before reading from port 0 + // bit 3 is waited on after writing a byte + + // will inf loop reading here once the 68k stops requesting data + //logerror("%s:prot_p2_r\n", machine().describe_context()); + return m_port2_data; +} + +WRITE32_MEMBER(dreamwld_state::to_prot_w) +{ + m_port2_data &= 0xfb; // lower bit 0x04 to indicate data sent? + logerror("%s:to_prot_w %08x\n", machine().describe_context(), data); + m_maincpu->spin_until_time(attotime::from_usec(50)); // give it time to respond +} + +u32 dreamwld_state::protdata_r() +{ + m_port2_data &= 0xf7; // clear bit 0x08 to indicate data received? + logerror("%s:protdata_r\n", machine().describe_context()); + m_maincpu->spin_until_time(attotime::from_usec(50)); // give it time to respond + return m_protlatch << 24; } @@ -743,7 +809,12 @@ void dreamwld_state::baryon(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &dreamwld_state::baryon_map); m_maincpu->set_vblank_int("screen", FUNC(dreamwld_state::irq4_line_hold)); - AT89C52(config, "mcu", XTAL(32'000'000)/2).set_disable(); /* AT89C52 or 87(C)52, unknown clock (value from docs), internal ROMs aren't dumped */ + AT89C52(config, m_mcu, XTAL(32'000'000) / 2); /* AT89C52 or 87(C)52, unknown clock (value from docs) */ + m_mcu->port_out_cb<1>().set(FUNC(dreamwld_state::prot_p1_w)); + m_mcu->port_out_cb<2>().set(FUNC(dreamwld_state::prot_p2_w)); + m_mcu->port_in_cb<2>().set(FUNC(dreamwld_state::prot_p2_r)); + + //config.set_perfect_quantum(m_maincpu); /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); @@ -778,6 +849,7 @@ void dreamwld_state::dreamwld(machine_config &config) } + /* Baryon @@ -822,10 +894,7 @@ ROM_START( baryon ) // this set had original SemiCom labels ROM_LOAD32_BYTE( "3_semicom", 0x000003, 0x040000, CRC(0ae6d86e) SHA1(410ad161688ec8516fe5ac7160a4a228dbb01936) ) ROM_REGION( 0x02000, "mcu", 0 ) /* 87C52 MCU Code */ - ROM_LOAD( "87c52.mcu", 0x00000, 0x02000 , NO_DUMP ) /* can't be dumped. */ - - ROM_REGION( 0x6bd, "prot", 0 ) /* Protection data - from baryona set, assumed to be the same */ - ROM_LOAD( "protdata.bin", 0x000, 0x6bd, CRC(117f32a8) SHA1(837bea09d3e59ab9e13bd1103b1fc988edb361c0) ) /* extracted */ + ROM_LOAD( "mcu.bin", 0x00000, 0x02000, BAD_DUMP CRC(1ee7896c) SHA1(f1e8500b7b6aa4e6ae939e228ffd11462f10ba33) ) // handcrafted from Dream World MCU using correct protection data for this game ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples */ ROM_LOAD( "1_semicom", 0x000000, 0x80000, CRC(e0349074) SHA1(f3d53d96dff586a0ad1632f52e5559cdce5ed0d8) ) // eprom type 27C040 @@ -853,10 +922,7 @@ ROM_START( baryona ) // replacment labels? no SemiCom logo ROM_LOAD32_BYTE( "5.bin", 0x000003, 0x040000, CRC(63d5e7cb) SHA1(269bf5ffe10f2464f823c4d377921e19cfb8bc46) ) ROM_REGION( 0x02000, "mcu", 0 ) /* 87C52 MCU Code */ - ROM_LOAD( "87c52.mcu", 0x00000, 0x02000 , NO_DUMP ) /* can't be dumped. */ - - ROM_REGION( 0x6bd, "prot", 0 ) /* Protection data */ - ROM_LOAD( "protdata.bin", 0x000, 0x6bd, CRC(117f32a8) SHA1(837bea09d3e59ab9e13bd1103b1fc988edb361c0) ) /* extracted */ + ROM_LOAD( "mcu.bin", 0x00000, 0x02000, BAD_DUMP CRC(1ee7896c) SHA1(f1e8500b7b6aa4e6ae939e228ffd11462f10ba33) ) // handcrafted from Dream World MCU using correct protection data for this game ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples */ ROM_LOAD( "1.bin", 0x000000, 0x80000, CRC(e0349074) SHA1(f3d53d96dff586a0ad1632f52e5559cdce5ed0d8) ) @@ -923,10 +989,7 @@ ROM_START( cutefght ) ROM_LOAD32_BYTE( "4_semicom", 0x000003, 0x080000, CRC(476a3bf5) SHA1(5be1c70bbf4fcfc534b7f20bfceaa8da2e961330) ) ROM_REGION( 0x02000, "mcu", 0 ) /* 87C52 MCU Code */ - ROM_LOAD( "87c52.mcu", 0x00000, 0x02000 , NO_DUMP ) /* can't be dumped. */ - - ROM_REGION( 0x1000, "prot", ROMREGION_ERASEFF ) /* Protection data */ - ROM_LOAD( "protdata.bin", 0x000, 0x701 , CRC(764c3c0e) SHA1(ae044d016850b730b2d97ccb7845b6b438c1e074) ) + ROM_LOAD( "mcu.bin", 0x00000, 0x02000, BAD_DUMP CRC(7d9acd7d) SHA1(12059143ac9e10f3a21402d2879ff0b5097d6de0) ) // handcrafted from Dream World MCU using correct protection data for this game ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples - 1st chip */ ROM_LOAD( "2_semicom", 0x000000, 0x80000, CRC(694ddaf9) SHA1(f9138e7e1d8f771c4e69c17f27fb2b70fbee076a) ) @@ -1002,10 +1065,7 @@ ROM_START( rolcrush ) ROM_LOAD32_BYTE( "mx27c2000_1.bin", 0x000003, 0x040000, CRC(a37e15b2) SHA1(f0fc945a894d6ed58daf05390a17051d0f3cda20) ) ROM_REGION( 0x02000, "mcu", 0 ) /* 87C52 MCU Code */ - ROM_LOAD( "87c52.mcu", 0x00000, 0x02000 , NO_DUMP ) /* can't be dumped. */ - - ROM_REGION( 0x10000, "prot", ROMREGION_ERASE00 ) /* Protection data */ - ROM_LOAD( "protdata.bin", 0x000, 0x745, CRC(06b8a880) SHA1(b7d4bf26d34cb544825270c2c474bbd4c81a6c9e) ) /* extracted */ + ROM_LOAD( "mcu.bin", 0x00000, 0x02000, BAD_DUMP CRC(9185e237) SHA1(866255242130503fa9a164645082640f1da0a8ff) ) // handcrafted from Dream World MCU using correct protection data for this game ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples - 1st chip*/ ROM_LOAD( "mx27c4000_5.bin", 0x000000, 0x80000, CRC(7afa6adb) SHA1(d4049e1068a5f7abf0e14d0b9fbbbc6dfb5d0170) ) @@ -1036,10 +1096,7 @@ ROM_START( rolcrusha ) ROM_LOAD32_BYTE( "1", 0x000003, 0x040000, CRC(ef23ccf3) SHA1(14dcf8bfca991f6aa9b20236c879ae715a009ca2) ) ROM_REGION( 0x02000, "mcu", 0 ) /* 87C52 MCU Code */ - ROM_LOAD( "87c52.mcu", 0x00000, 0x02000 , NO_DUMP ) /* can't be dumped. */ - - ROM_REGION( 0x10000, "prot", ROMREGION_ERASE00 ) /* Protection data */ - ROM_LOAD( "protdata.bin", 0x000, 0x745, CRC(06b8a880) SHA1(b7d4bf26d34cb544825270c2c474bbd4c81a6c9e) ) + ROM_LOAD( "mcu.bin", 0x00000, 0x02000, BAD_DUMP CRC(9185e237) SHA1(866255242130503fa9a164645082640f1da0a8ff) ) // handcrafted from Dream World MCU using correct protection data for this game ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples - 1st chip*/ ROM_LOAD( "5", 0x000000, 0x80000, CRC(7afa6adb) SHA1(d4049e1068a5f7abf0e14d0b9fbbbc6dfb5d0170) ) @@ -1111,15 +1168,7 @@ ROM_START( dreamwld ) ROM_LOAD32_BYTE( "2.bin", 0x000003, 0x040000, CRC(5409e7fc) SHA1(2f94a6a8e4c94b36b43f0b94d58525f594339a9d) ) ROM_REGION( 0x02000, "mcu", 0 ) // chip marked P87C52EBPN, die shows 87C51RA+ after decapping - ROM_LOAD( "87c51rap.bin", 0x00000, 0x02000 , CRC(987bbfe8) SHA1(7717ed5cf97bc11c104356f6ff1d893d1606bcf0) ) // not hooked up yet, from 0x3c onwards it contains the exact same data as in the extracted protdata.bin below - - ROM_REGION( 0x6c9, "prot", 0 ) /* Protection data */ - /* The MCU supplies this data. - The 68k reads it through a port, taking the size and destination write address from the level 1 - and level 2 irq positions in the 68k vector table (there is code to check that they haven't been - modified!) It then decodes the data using the rom checksum previously calculated and puts it in - ram. The interrupt vectors point at the code placed in RAM. */ - ROM_LOAD( "protdata.bin", 0x000, 0x6c9 , CRC(f284b2fd) SHA1(9e8096c8aa8a288683f002311b38787b120748d1) ) /* extracted */ + ROM_LOAD( "87c51rap.bin", 0x00000, 0x02000 , CRC(987bbfe8) SHA1(7717ed5cf97bc11c104356f6ff1d893d1606bcf0) ) ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples - 1st chip */ ROM_LOAD( "5.bin", 0x000000, 0x80000, CRC(9689570a) SHA1(4414233da8f46214ca7e9022df70953922a63aa4) ) @@ -1198,10 +1247,7 @@ ROM_START( gaialast ) ROM_LOAD32_BYTE( "3", 0x000003, 0x040000, CRC(a8e845d8) SHA1(f8c7e702bd747a22e76c861effec4cd3cd2f3fc9) ) ROM_REGION( 0x02000, "mcu", 0 ) /* 87C52 MCU Code */ - ROM_LOAD( "87c52.mcu", 0x00000, 0x02000 , NO_DUMP ) /* can't be dumped. */ - - ROM_REGION( 0x6c9, "prot", ROMREGION_ERASEFF ) /* Protection data */ - ROM_LOAD( "protdata.bin", 0x000, 0x6c9 , CRC(d3403b7b) SHA1(712a7f27fc41b632d584237f7641e8ae20035111) ) + ROM_LOAD( "mcu.bin", 0x00000, 0x02000, BAD_DUMP CRC(fb3db92b) SHA1(3ae3649debf79a4345b05c2f4ae9674c13a66ed1) ) // handcrafted from Dream World MCU using correct protection data for this game ROM_REGION( 0x80000, "oki1", 0 ) /* OKI Samples */ ROM_LOAD( "1", 0x000000, 0x80000, CRC(2dbad410) SHA1(bb788ea14bb605be9af9c8f8adec94ad1c17ab55) ) @@ -1231,4 +1277,4 @@ GAME( 1998, cutefght, 0, dreamwld, cutefght, dreamwld_state, empty_init, GAME( 1999, rolcrush, 0, baryon, rolcrush, dreamwld_state, empty_init, ROT0, "SemiCom / Exit (Trust license)", "Rolling Crush (version 1.07.E - 1999/02/11, Trust license)", MACHINE_SUPPORTS_SAVE ) GAME( 1999, rolcrusha,rolcrush, baryon, rolcrush, dreamwld_state, empty_init, ROT0, "SemiCom / Exit", "Rolling Crush (version 1.03.E - 1999/01/29)", MACHINE_SUPPORTS_SAVE ) GAME( 1999, gaialast, 0, baryon, gaialast, dreamwld_state, empty_init, ROT0, "SemiCom / XESS", "Gaia - The Last Choice of Earth", MACHINE_SUPPORTS_SAVE ) -GAME( 2000, dreamwld, 0, dreamwld, dreamwld, dreamwld_state, empty_init, ROT0, "SemiCom", "Dream World", MACHINE_SUPPORTS_SAVE ) // MCU dump not hooked up yet +GAME( 2000, dreamwld, 0, dreamwld, dreamwld, dreamwld_state, empty_init, ROT0, "SemiCom", "Dream World", MACHINE_SUPPORTS_SAVE )