decap + dump f1dream I8751 MCU [Caps0ff] (#3467)

* decap + dump f1dream I8751 MCU [Caps0ff]
hookup dumped MCU to f1dream [David Haywood]

some connections might need verifying on the PCB, this is based on study of the code

machines promoted to WORKING
F-1 Dream [Caps0ff, David Haywood]

* formatting (nw)
This commit is contained in:
David Haywood 2018-04-17 20:43:22 +01:00 committed by R. Belmont
parent 49d25dac06
commit eaa91d0abd
3 changed files with 103 additions and 134 deletions

View File

@ -14,8 +14,6 @@ regarding this driver.
**************************************************************************
F1 Dream protection workaround by Eric Hustvedt
Memory Overview:
0xfe0800 sprites
0xfec000 text
@ -68,6 +66,41 @@ WRITE8_MEMBER(tigeroad_state::msm5205_w)
}
WRITE8_MEMBER(f1dream_state::out1_w)
{
m_soundlatch->write(space,2,data);
}
WRITE8_MEMBER(f1dream_state::out3_w)
{
if ((m_old_p3 & 0x20) != (data & 0x20))
{
// toggles at the start and end of interrupt
}
if ((m_old_p3 & 0x01) != (data & 0x01))
{
// toggles at the end of interrupt
if (!(data & 0x01))
{
m_maincpu->resume(SUSPEND_REASON_HALT);
}
}
m_old_p3 = data;
}
WRITE16_MEMBER(f1dream_state::blktiger_to_mcu_w)
{
m_mcu->set_input_line(MCS51_INT0_LINE, HOLD_LINE);
/* after triggering this address there are one or two NOPs in the 68k code, then it expects the response to be ready
the MCU isn't that fast, so either the CPU is suspended on write, or when bit 0x20 of MCU Port 3 toggles in the
MCU interrupt code, however no combination of increasing the clock / boosting interleave etc. allows the MCU code
to get there in time before the 68k is already expecting a result */
m_maincpu->suspend(SUSPEND_REASON_HALT, true);
}
/***************************************************************************/
void tigeroad_state::main_map(address_map &map)
@ -87,6 +120,30 @@ void tigeroad_state::main_map(address_map &map)
map(0xffc000, 0xffffff).ram().share("ram16");
}
READ8_MEMBER(f1dream_state::mcu_shared_r)
{
uint8_t ret = m_ram16[(0x3fe0 / 2) + offset];
return ret;
}
WRITE8_MEMBER(f1dream_state::mcu_shared_w)
{
m_ram16[(0x3fe0 / 2) + offset] = (m_ram16[(0x3fe0 / 2) + offset] & 0xff00) | data;
}
void f1dream_state::f1dream_map(address_map &map)
{
main_map(map);
map(0xfe4002, 0xfe4003).portr("SYSTEM").w(this, FUNC(f1dream_state::blktiger_to_mcu_w));
}
void f1dream_state::f1dream_mcu_io(address_map &map)
{
map(0x7f0, 0x7ff).rw(this, FUNC(f1dream_state::mcu_shared_r), FUNC(f1dream_state::mcu_shared_w));
}
void pushman_state::pushman_map(address_map &map)
{
main_map(map);
@ -630,6 +687,18 @@ MACHINE_CONFIG_START(tigeroad_state::tigeroad)
MACHINE_CONFIG_END
MACHINE_CONFIG_START(f1dream_state::f1dream)
tigeroad(config);
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(f1dream_map)
MCFG_CPU_ADD("mcu", I8751, XTAL(10'000'000)) /* ??? */
MCFG_CPU_IO_MAP(f1dream_mcu_io)
MCFG_MCS51_PORT_P1_OUT_CB(WRITE8(f1dream_state, out1_w))
MCFG_MCS51_PORT_P3_OUT_CB(WRITE8(f1dream_state, out3_w))
MACHINE_CONFIG_END
/* same as above but with additional Z80 for samples playback */
MACHINE_CONFIG_START(tigeroad_state::toramich)
tigeroad(config);
@ -888,7 +957,7 @@ ROM_START( f1dream )
ROM_LOAD( "12k_04.bin", 0x0000, 0x8000, CRC(4b9a7524) SHA1(19004958c19ac0af35f2c97790b0082ee2c15bc4) )
ROM_REGION( 0x1000, "mcu", 0 ) /* i8751 microcontroller */
ROM_LOAD( "c8751h-88", 0x0000, 0x1000, NO_DUMP )
ROM_LOAD( "8751.mcu", 0x0000, 0x1000, CRC(c8e6075c) SHA1(d98bd358d30d22a8009cd2728dde1871a8140c23) )
ROM_REGION( 0x008000, "text", 0 )
ROM_LOAD( "10d_01.bin", 0x00000, 0x08000, CRC(361caf00) SHA1(8a109e4e116d0c5eea86f9c57c05359754daa5b9) ) /* 8x8 text */
@ -1182,10 +1251,6 @@ ROM_START( bballsa )
ROM_END
DRIVER_INIT_MEMBER(tigeroad_state, f1dream)
{
m_maincpu->space(AS_PROGRAM).install_write_handler(0xfe4002, 0xfe4003, write16_delegate(FUNC(tigeroad_state::f1dream_control_w),this));
}
/***************************************************************************/
@ -1196,9 +1261,9 @@ GAME( 1987, toramich, tigeroad, toramich, toramich, tigeroad_state, 0, ROT
GAME( 1987, tigeroadb,tigeroad, tigeroad, tigeroad, tigeroad_state, 0, ROT0, "bootleg", "Tiger Road (US bootleg)", 0 )
/* F1 Dream has an Intel 8751 microcontroller for protection */
GAME( 1988, f1dream, 0, tigeroad, f1dream, tigeroad_state, f1dream, ROT0, "Capcom (Romstar license)", "F-1 Dream", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION ) // collisions are wrong
GAME( 1988, f1dreamb, f1dream, tigeroad, f1dream, tigeroad_state, 0, ROT0, "bootleg", "F-1 Dream (bootleg, set 1)", 0 )
GAME( 1988, f1dreamba,f1dream, tigeroad, f1dream, tigeroad_state, 0, ROT0, "bootleg", "F-1 Dream (bootleg, set 2)", 0 )
GAME( 1988, f1dream, 0, f1dream, f1dream, f1dream_state, 0, ROT0, "Capcom (Romstar license)", "F-1 Dream", 0 )
GAME( 1988, f1dreamb, f1dream, tigeroad, f1dream, tigeroad_state, 0, ROT0, "bootleg", "F-1 Dream (bootleg, set 1)", 0 )
GAME( 1988, f1dreamba,f1dream, tigeroad, f1dream, tigeroad_state, 0, ROT0, "bootleg", "F-1 Dream (bootleg, set 2)", 0 )
/* This Comad hardware is based around the F1 Dream design */
GAME( 1990, pushman, 0, pushman, pushman, pushman_state, 0, ROT0, "Comad", "Pushman (Korea, set 1)", MACHINE_SUPPORTS_SAVE )

View File

@ -6,6 +6,7 @@
#include "cpu/m68000/m68000.h"
#include "cpu/m6805/m68705.h"
#include "cpu/z80/z80.h"
#include "cpu/mcs51/mcs51.h"
#include "machine/gen_latch.h"
@ -39,19 +40,16 @@ public:
int m_bgcharbank;
tilemap_t *m_bg_tilemap;
tilemap_t *m_fg_tilemap;
DECLARE_WRITE16_MEMBER(f1dream_control_w);
DECLARE_WRITE16_MEMBER(tigeroad_soundcmd_w);
DECLARE_WRITE16_MEMBER(tigeroad_videoram_w);
DECLARE_WRITE16_MEMBER(tigeroad_videoctrl_w);
DECLARE_WRITE16_MEMBER(tigeroad_scroll_w);
DECLARE_WRITE8_MEMBER(msm5205_w);
DECLARE_DRIVER_INIT(f1dream);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
TILEMAP_MAPPER_MEMBER(tigeroad_tilemap_scan);
virtual void video_start() override;
uint32_t screen_update_tigeroad(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void f1dream_protection_w(address_space &space);
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_audiocpu;
optional_device<msm5205_device> m_msm;
@ -114,3 +112,30 @@ protected:
u16 m_mcu_output;
u8 m_mcu_latch_ctl;
};
class f1dream_state : public tigeroad_state
{
public:
f1dream_state(const machine_config &mconfig, device_type type, const char *tag)
: tigeroad_state(mconfig, type, tag)
, m_mcu(*this, "mcu")
, m_old_p3(0xff)
{
}
void f1dream(machine_config &config);
void f1dream_map(address_map &map);
void f1dream_mcu_io(address_map &map);
private:
DECLARE_WRITE8_MEMBER(out1_w);
DECLARE_WRITE8_MEMBER(out3_w);
DECLARE_READ8_MEMBER(mcu_shared_r);
DECLARE_WRITE8_MEMBER(mcu_shared_w);
DECLARE_WRITE16_MEMBER(blktiger_to_mcu_w);
required_device<cpu_device> m_mcu;
uint8_t m_old_p3;
};

View File

@ -3,127 +3,6 @@
#include "emu.h"
#include "includes/tigeroad.h"
/*
F1 Dream protection code written by Eric Hustvedt (hustvedt@ma.ultranet.com).
The genuine F1 Dream game uses an 8751 microcontroller as a protection measure.
Since the microcontroller's ROM is unavailable all interactions with it are handled
via blackbox algorithm.
Some notes:
- The 8751 is triggered via location 0xfe4002, in place of the soundlatch normally
present. The main cpu writes 0 to the location when it wants the 8751 to perform some work.
- The 8751 has memory which shadows locations 0xffffe0-0xffffff of the main cpu's address space.
- The word at 0xffffe0 contains an 'opcode' which is written just before the write to 0xfe4002.
- Some of the writes to the soundlatch may not be handled. 0x27fc is the main sound routine, the
other locations are less frequently used.
*/
static const int f1dream_613ea_lookup[16] = {
0x0052, 0x0031, 0x00a7, 0x0043, 0x0007, 0x008a, 0x00b1, 0x0066, 0x009f, 0x00cc, 0x0009, 0x004d, 0x0033, 0x0028, 0x00d0, 0x0025};
static const int f1dream_613eb_lookup[256] = {
0x0001, 0x00b5, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b7, 0x0001, 0x00b8, 0x002f, 0x002f, 0x002f, 0x002f, 0x00b9,
0x00aa, 0x0031, 0x00ab, 0x00ab, 0x00ab, 0x00ac, 0x00ad, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x0091,
0x009c, 0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x009b, 0x0091,
0x00bc, 0x0092, 0x000b, 0x0009, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0073, 0x0001, 0x0098, 0x0099, 0x009a, 0x009b, 0x0091,
0x00bc, 0x007b, 0x000b, 0x0008, 0x0087, 0x0088, 0x0089, 0x008a, 0x007f, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091,
0x00bd, 0x007b, 0x000b, 0x0007, 0x007c, 0x007d, 0x007e, 0x0001, 0x007f, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086,
0x00bc, 0x0070, 0x000b, 0x0006, 0x0071, 0x0072, 0x0073, 0x0001, 0x0074, 0x000d, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a,
0x00bc, 0x00ba, 0x000a, 0x0005, 0x0065, 0x0066, 0x0067, 0x0068, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x00bc, 0x0059, 0x0001, 0x0004, 0x005a, 0x005b, 0x0001, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064,
0x0014, 0x004d, 0x0001, 0x0003, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0001, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
0x0014, 0x0043, 0x0001, 0x0002, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x00bb, 0x004a, 0x004b, 0x004c, 0x0001, 0x0001,
0x0014, 0x002b, 0x0001, 0x0038, 0x0039, 0x003a, 0x003b, 0x0031, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0001,
0x0014, 0x002d, 0x0001, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0001, 0x0014, 0x0037, 0x0001,
0x0014, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x0001, 0x0001, 0x0001, 0x002a, 0x002b, 0x002c,
0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001e, 0x001e, 0x001e, 0x001f, 0x0020,
0x000c, 0x000d, 0x000e, 0x0001, 0x000f, 0x0010, 0x0011, 0x0012, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x0013 };
static const int f1dream_17b74_lookup[128] = {
0x0003, 0x0040, 0x0005, 0x0080, 0x0003, 0x0080, 0x0005, 0x00a0, 0x0003, 0x0040, 0x0005, 0x00c0, 0x0003, 0x0080, 0x0005, 0x00e0,
0x0003, 0x0040, 0x0006, 0x0000, 0x0003, 0x0080, 0x0006, 0x0020, 0x0003, 0x0040, 0x0006, 0x0040, 0x0003, 0x0080, 0x0006, 0x0060,
0x0000, 0x00a0, 0x0009, 0x00e0, 0x0000, 0x00e0, 0x000a, 0x0000, 0x0000, 0x00a0, 0x000a, 0x0020, 0x0000, 0x00e0, 0x000a, 0x0040,
0x0000, 0x00a0, 0x000a, 0x0060, 0x0000, 0x00e0, 0x000a, 0x0080, 0x0000, 0x00a0, 0x000a, 0x00a0, 0x0000, 0x00e0, 0x000a, 0x00c0,
0x0003, 0x0040, 0x0005, 0x0080, 0x0003, 0x0080, 0x0005, 0x00a0, 0x0003, 0x0040, 0x0005, 0x00c0, 0x0003, 0x0080, 0x0005, 0x00e0,
0x0003, 0x0040, 0x0006, 0x0000, 0x0003, 0x0080, 0x0006, 0x0020, 0x0003, 0x0040, 0x0006, 0x0040, 0x0003, 0x0080, 0x0006, 0x0060,
0x0000, 0x00a0, 0x0009, 0x00e0, 0x0000, 0x00e0, 0x000a, 0x0000, 0x0000, 0x00a0, 0x000a, 0x0020, 0x0000, 0x00e0, 0x000a, 0x0040,
0x0000, 0x00a0, 0x000a, 0x0060, 0x0000, 0x00e0, 0x000a, 0x0080, 0x0000, 0x00a0, 0x000a, 0x00a0, 0x0000, 0x00e0, 0x000a, 0x00c0 };
static const int f1dream_2450_lookup[32] = {
0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0, 0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0,
0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0, 0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0 };
void tigeroad_state::f1dream_protection_w(address_space &space)
{
int indx;
int value = 255;
int prevpc = m_maincpu->pcbase();
if (prevpc == 0x244c)
{
/* Called once, when a race is started.*/
indx = m_ram16[0x3ff0/2];
m_ram16[0x3fe6/2] = f1dream_2450_lookup[indx];
m_ram16[0x3fe8/2] = f1dream_2450_lookup[++indx];
m_ram16[0x3fea/2] = f1dream_2450_lookup[++indx];
m_ram16[0x3fec/2] = f1dream_2450_lookup[++indx];
}
else if (prevpc == 0x613a)
{
/* Called for every sprite on-screen.*/
if (m_ram16[0x3ff6/2] < 15)
{
indx = f1dream_613ea_lookup[m_ram16[0x3ff6/2]] - m_ram16[0x3ff4/2];
if (indx > 255)
{
indx <<= 4;
indx += m_ram16[0x3ff6/2] & 0x00ff;
value = f1dream_613eb_lookup[indx];
}
}
m_ram16[0x3ff2/2] = value;
}
else if (prevpc == 0x17b70)
{
/* Called only before a real race, not a time trial.*/
if (m_ram16[0x3ff0/2] >= 0x04) indx = 128;
else if (m_ram16[0x3ff0/2] > 0x02) indx = 96;
else if (m_ram16[0x3ff0/2] == 0x02) indx = 64;
else if (m_ram16[0x3ff0/2] == 0x01) indx = 32;
else indx = 0;
indx += m_ram16[0x3fee/2];
if (indx < 128)
{
m_ram16[0x3fe6/2] = f1dream_17b74_lookup[indx];
m_ram16[0x3fe8/2] = f1dream_17b74_lookup[++indx];
m_ram16[0x3fea/2] = f1dream_17b74_lookup[++indx];
m_ram16[0x3fec/2] = f1dream_17b74_lookup[++indx];
}
else
{
m_ram16[0x3fe6/2] = 0x00ff;
m_ram16[0x3fe8/2] = 0x00ff;
m_ram16[0x3fea/2] = 0x00ff;
m_ram16[0x3fec/2] = 0x00ff;
}
}
else if ((prevpc == 0x27f8) || (prevpc == 0x511a) || (prevpc == 0x5142) || (prevpc == 0x516a))
{
/* The main CPU stuffs the byte for the soundlatch into 0xfffffd.*/
m_soundlatch->write(space,2,m_ram16[0x3ffc/2]);
}
}
WRITE16_MEMBER(tigeroad_state::f1dream_control_w)
{
logerror("%s protection write, FFE1 Value:%01x\n",machine().describe_context(), m_ram16[0x3fe0/2]);
f1dream_protection_w(space);
}
READ16_MEMBER(pushman_state::mcu_comm_r)
{
switch (offset & 0x03)