-igs/xamcu.cpp: Consolidated MCU interface logic from igs_fear.cpp and igs_m027xa.cpp.

-igs/igs_m027xa.cpp, igs/igs_fear.cpp: Updated system flags.
This commit is contained in:
Vas Crabb 2024-09-15 06:55:43 +10:00
parent c69eebe89a
commit 014fa68650
6 changed files with 486 additions and 424 deletions

View File

@ -2629,7 +2629,8 @@ void xa_cpu::check_interrupts()
void xa_cpu::execute_set_input(int inputnum, int state)
{
// This is not accurate, just test code for fearless/superkds
m_irq_pending |= 1 << inputnum;
if (state)
m_irq_pending |= 1 << inputnum;
check_interrupts();
}

View File

@ -9,13 +9,12 @@
#include "igs027a.h"
#include "pgmcrypt.h"
#include "xamcu.h"
#include "cpu/arm7/arm7core.h"
#include "cpu/xa/xa.h"
#include "machine/nvram.h"
#include "machine/ticket.h"
#include "machine/v3021.h"
#include "sound/ics2115.h"
#include "emupal.h"
#include "screen.h"
@ -24,7 +23,7 @@
#include <algorithm>
#define LOG_DEBUG (1U << 1)
#define VERBOSE (0)
//#define VERBOSE (LOG_DEBUG)
#include "logmacro.h"
@ -41,7 +40,6 @@ public:
m_videoram(*this, "videoram"),
m_maincpu(*this, "maincpu"),
m_xa(*this, "xa"),
m_ics(*this, "ics"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_ticket(*this, "ticket"),
@ -80,28 +78,15 @@ private:
void igs027_gpio_w(u8 data);
u32 xa_r(offs_t offset, u32 mem_mask);
void xa_w(offs_t offset, u32 data, u32 mem_mask);
void cpld_w(offs_t offset, u32 data, u32 mem_mask);
u8 mcu_p0_r();
u8 mcu_p1_r();
u8 mcu_p2_r();
u8 mcu_p3_r();
void mcu_p0_w(uint8_t data);
void mcu_p1_w(uint8_t data);
void mcu_p2_w(uint8_t data);
void mcu_p3_w(uint8_t data);
u16 xa_wait_r(offs_t offset);
required_region_ptr<u32> m_external_rom;
required_region_ptr<u8> m_gfxrom;
required_shared_ptr<uint32_t> m_sram;
required_shared_ptr<u32> m_videoram;
required_device<igs027a_cpu_device> m_maincpu;
required_device<mx10exa_cpu_device> m_xa;
required_device<ics2115_device> m_ics;
required_device<igs_xa_mcu_ics_sound_device> m_xa;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
@ -112,21 +97,8 @@ private:
u32 m_xor_table[0x100];
u8 m_port2_latch;
u8 m_port0_latch;
u8 m_gpio_o;
u32 m_xa_cmd;
u32 m_xa_ret0;
u32 m_xa_ret1;
u8 m_num_params;
u8 m_port0_dat;
u8 m_port1_dat;
u8 m_port2_dat;
u8 m_port3_dat;
int m_trackball_cnt;
int m_trackball_axis[2], m_trackball_axis_pre[2], m_trackball_axis_diff[2];
};
@ -142,39 +114,11 @@ void igs_fear_state::machine_start()
save_item(NAME(m_xor_table));
save_item(NAME(m_port2_latch));
save_item(NAME(m_port0_latch));
save_item(NAME(m_gpio_o));
save_item(NAME(m_xa_cmd));
save_item(NAME(m_xa_ret0));
save_item(NAME(m_xa_ret1));
save_item(NAME(m_num_params));
save_item(NAME(m_port0_dat));
save_item(NAME(m_port1_dat));
save_item(NAME(m_port2_dat));
save_item(NAME(m_port3_dat));
}
void igs_fear_state::machine_reset()
{
m_port2_latch = 0;
m_port0_latch = 0;
m_gpio_o = 0;
m_xa_cmd = 0;
m_xa_ret0 = 0;
m_xa_ret1 = 0;
m_num_params = 0;
m_port0_dat = 0;
m_port1_dat = 0;
m_port2_dat = 0;
m_port3_dat = 0;
}
void igs_fear_state::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, int xpos, int ypos, int height, int width, int palette, int flipx, int romoffset)
@ -244,7 +188,8 @@ void igs_fear_state::main_map(address_map &map)
map(0x38000000, 0x38001fff).ram().share(m_videoram);
map(0x38004000, 0x38007fff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x38008500, 0x380085ff).rw(FUNC(igs_fear_state::xa_r), FUNC(igs_fear_state::xa_w));
map(0x38008500, 0x38008503).umask32(0x0000ffff).w(m_xa, FUNC(igs_xa_mcu_ics_sound_device::cmd_w));
map(0x38008500, 0x380085ff).r(FUNC(igs_fear_state::xa_r));
map(0x50000000, 0x500003ff).umask32(0x000000ff).w(FUNC(igs_fear_state::xor_table_w));
@ -327,9 +272,9 @@ INPUT_PORTS_START( superkds )
PORT_DIPSETTING( 0x02, "Jungle" )
PORT_DIPSETTING( 0x01, "Ice Field" )
PORT_DIPSETTING( 0x00, "Ice Field (duplicate)" )
PORT_DIPNAME( 0x04, 0x00, "Ticket" ) PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
PORT_DIPNAME( 0x04, 0x00, "Ticket Dispenser" ) PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
PORT_DIPNAME( 0xf8, 0x00, "Ticket Payout Table" ) PORT_DIPLOCATION("SW1:4,5,6,7,8")
PORT_DIPSETTING( 0xf8, "3 2 2 1 1 0 0 0" )
PORT_DIPSETTING( 0xf0, "3 2 2 2 1 1 1 1" )
@ -369,13 +314,13 @@ INPUT_PORTS_START( superkds )
PORT_DIPSETTING( 0x01, DEF_STR(Off) )
PORT_DIPSETTING( 0x00, DEF_STR(On) )
PORT_DIPNAME( 0x06, 0x06, DEF_STR(Coin_A) ) PORT_DIPLOCATION("SW2:2,3")
PORT_DIPSETTING( 0x06, DEF_STR(1C_1C) )
PORT_DIPSETTING( 0x04, DEF_STR(2C_1C) )
PORT_DIPSETTING( 0x02, DEF_STR(3C_1C) )
PORT_DIPSETTING( 0x00, DEF_STR(4C_1C) )
PORT_DIPSETTING( 0x02, DEF_STR(3C_1C) )
PORT_DIPSETTING( 0x04, DEF_STR(2C_1C) )
PORT_DIPSETTING( 0x06, DEF_STR(1C_1C) )
PORT_DIPNAME( 0x08, 0x08, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW2:4")
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
PORT_DIPNAME( 0x70, 0x00, "Slave ID" ) PORT_DIPLOCATION("SW2:5,6,7")
PORT_DIPSETTING( 0x70, "0" )
PORT_DIPSETTING( 0x60, "1" )
@ -398,9 +343,9 @@ INPUT_PORTS_END
void igs_fear_state::sound_irq(int state)
{
LOGMASKED(LOG_DEBUG, "sound irq\n");
LOGMASKED(LOG_DEBUG, "sound irq = %d\n", state);
if (state)
m_xa->set_input_line(XA_EXT_IRQ2, ASSERT_LINE);
m_maincpu->trigger_irq(3);
}
void igs_fear_state::vblank_irq(int state)
@ -445,9 +390,9 @@ u32 igs_fear_state::xa_r(offs_t offset, u32 mem_mask)
{
case 0:
{
data = m_xa_ret0;
data = m_xa->response_low_r();
// TODO: This should be remove when we implement serial trackball support in XA
if (m_xa_cmd == 0xa301)
if (m_xa->cmd_r() == 0xa301)
{
switch (m_trackball_cnt++)
{
@ -485,37 +430,12 @@ u32 igs_fear_state::xa_r(offs_t offset, u32 mem_mask)
break;
}
case 0x80:
data = m_xa_ret1 << 16;
data = u32(m_xa->response_high_r()) << 16;
break;
}
return data;
}
void igs_fear_state::xa_w(offs_t offset, u32 data, u32 mem_mask)
{
m_xa_cmd = data;
if (offset == 0)
{
m_num_params--;
if (m_num_params <= 0)
{
LOGMASKED(LOG_DEBUG, "---------------m_xa_cmd is %02x size %02x\n", (data & 0xff00)>>8, data & 0xff);
m_num_params = data & 0xff;
}
else
{
LOGMASKED(LOG_DEBUG, "-------------------------- param %04x\n", data & 0xffff);
}
m_xa->set_input_line(XA_EXT_IRQ0, ASSERT_LINE);
}
else
{
LOGMASKED(LOG_DEBUG, "%s: unhandled xa_w %04x %08x (%08x)\n", machine().describe_context(), offset * 4, data, mem_mask);
}
}
void igs_fear_state::cpld_w(offs_t offset, u32 data, u32 mem_mask)
{
switch (offset * 4)
@ -530,112 +450,6 @@ void igs_fear_state::cpld_w(offs_t offset, u32 data, u32 mem_mask)
}
}
u8 igs_fear_state::mcu_p0_r()
{
u8 ret = m_port0_latch;
LOGMASKED(LOG_DEBUG, "%s: COMMAND READ LOWER mcu_p0_r() returning %02x with port3 as %02x\n", machine().describe_context(), ret, m_port3_dat);
return ret;
}
u8 igs_fear_state::mcu_p1_r()
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p1_r()\n", machine().describe_context());
return m_port1_dat; // superkds XA will end up failing returning port1 dat for now, but not attempt to play any sounds otherwise?
}
u8 igs_fear_state::mcu_p2_r()
{
u8 ret = m_port2_latch;
LOGMASKED(LOG_DEBUG, "%s: COMMAND READ mcu_p2_r() returning %02x with port3 as %02x\n", machine().describe_context(), ret, m_port3_dat);
return m_port2_latch;
}
u8 igs_fear_state::mcu_p3_r()
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p3_r()\n", machine().describe_context());
return m_port3_dat;
}
static int posedge(uint32_t oldval, uint32_t val, int bit)
{
return (!BIT(oldval, bit)) && (BIT(val, bit));
}
static int negedge(uint32_t oldval, uint32_t val, int bit)
{
return (BIT(oldval, bit)) && (!BIT(val, bit));
}
void igs_fear_state::mcu_p0_w(uint8_t data)
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p0_w() %02x with port 3 as %02x and port 1 as %02x\n", machine().describe_context(), data, m_port3_dat, m_port1_dat);
m_port0_dat = data;
}
void igs_fear_state::mcu_p1_w(uint8_t data)
{
u8 olddata = m_port1_dat;
LOGMASKED(LOG_DEBUG, "%s: mcu_p1_w() %02x\n", machine().describe_context(), data);
m_port1_dat = data;
if (posedge(olddata, m_port1_dat, 3))
{
m_maincpu->trigger_irq(3);
}
}
void igs_fear_state::mcu_p2_w(uint8_t data)
{
m_port2_dat = data;
LOGMASKED(LOG_DEBUG, "%s: mcu_p2_w() %02x with port 3 as %02x\n", machine().describe_context(), data, m_port3_dat);
}
void igs_fear_state::mcu_p3_w(uint8_t data)
{
u8 oldport3 = m_port3_dat;
m_port3_dat = data;
LOGMASKED(LOG_DEBUG, "%s: mcu_p3_w() %02x - do latches oldport3 %02x newport3 %02x\n", machine().describe_context(), data, oldport3, m_port3_dat);
// high->low transition on bit 0x80 must read into latches!
if (negedge(oldport3, m_port3_dat, 7))
{
if (!BIT(m_port3_dat, 4))
{
m_port0_latch = m_ics->read(m_port1_dat & 7);
LOGMASKED(LOG_DEBUG, "read from ics [%d] = [%02x]\n", m_port1_dat & 7, m_port0_latch);
}
else if (!BIT(m_port3_dat, 5))
{
LOGMASKED(LOG_DEBUG, "read command [%d] = [%04x]\n", m_port1_dat & 7, m_xa_cmd);
m_port2_latch = (m_xa_cmd & 0xff00) >> 8;
m_port0_latch = m_xa_cmd & 0x00ff;
}
}
if (negedge(oldport3, m_port3_dat, 6))
{
if (!BIT(m_port3_dat, 4))
{
LOGMASKED(LOG_DEBUG, "write to ics [%d] = [%02x]\n", m_port1_dat & 7, m_port0_dat);
m_ics->write(m_port1_dat & 7, m_port0_dat);
}
else if (!BIT(m_port3_dat, 5))
{
uint32_t dat = (m_port2_dat << 8) | m_port0_dat;
LOGMASKED(LOG_DEBUG, "write command [%d] = [%04x]\n", m_port1_dat & 7, dat);
switch (m_port1_dat & 7)
{
case 1:
m_xa_ret1 = dat;
break;
case 2:
m_xa_ret0 = dat;
break;
}
}
}
}
void igs_fear_state::igs_fear(machine_config &config)
{
@ -644,16 +458,6 @@ void igs_fear_state::igs_fear(machine_config &config)
m_maincpu->in_port().set(FUNC(igs_fear_state::igs027_gpio_r));
m_maincpu->out_port().set(FUNC(igs_fear_state::igs027_gpio_w));
MX10EXA(config, m_xa, 50'000'000/3); // MX10EXAQC (Philips 80C51 XA)
m_xa->port_in_cb<0>().set(FUNC(igs_fear_state::mcu_p0_r));
m_xa->port_in_cb<1>().set(FUNC(igs_fear_state::mcu_p1_r));
m_xa->port_in_cb<2>().set(FUNC(igs_fear_state::mcu_p2_r));
m_xa->port_in_cb<3>().set(FUNC(igs_fear_state::mcu_p3_r));
m_xa->port_out_cb<0>().set(FUNC(igs_fear_state::mcu_p0_w));
m_xa->port_out_cb<1>().set(FUNC(igs_fear_state::mcu_p1_w));
m_xa->port_out_cb<2>().set(FUNC(igs_fear_state::mcu_p2_w));
m_xa->port_out_cb<3>().set(FUNC(igs_fear_state::mcu_p3_w));
config.set_maximum_quantum(attotime::from_hz(600));
NVRAM(config, "sram", nvram_device::DEFAULT_ALL_0);
@ -674,11 +478,8 @@ void igs_fear_state::igs_fear(machine_config &config)
TICKET_DISPENSER(config, m_ticket, attotime::from_msec(200));
/* sound hardware */
SPEAKER(config, "mono").front_center();
ICS2115(config, m_ics, 33.8688_MHz_XTAL); // TODO : Correct?
m_ics->irq().set(FUNC(igs_fear_state::sound_irq));
m_ics->add_route(ALL_OUTPUTS, "mono", 5.0);
IGS_XA_ICS_SOUND(config, m_xa, 50'000'000/3);
m_xa->irq().set(FUNC(igs_fear_state::sound_irq));
}
void igs_fear_state::igs_fear_xor(machine_config &config)
@ -696,7 +497,7 @@ ROM_START( fearless )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "fearlessp_v-101us.u37", 0x000000, 0x80000, CRC(2522873c) SHA1(8db709877311b6d2796353fc9a44a820937e35c2) )
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
ROM_LOAD( "fearlessp_07.u33", 0x000000, 0x10000, CRC(7dae4900) SHA1(bbf7ba7c9e95ff2ffeb1dc0fc7ccedd4da274d01) )
ROM_REGION( 0x3000000, "gfx1", 0 ) // FIXED BITS (0xxxxxxx) (graphics are 7bpp)
@ -707,7 +508,7 @@ ROM_START( fearless )
ROM_LOAD32_WORD( "fearlessp_u18_cg-2l.u18", 0x2000000, 0x800000, CRC(07623d66) SHA1(041d5e44917bc16caa720ea98bdc0a4f5fb4b8e0) )
ROM_LOAD32_WORD( "fearlessp_u17_cg-2h.u17", 0x2000002, 0x800000, CRC(756fe1f2) SHA1(48ee81c5fa4808406b57b2521b836db3ff5a7fa9) )
ROM_REGION( 0x800000, "ics", 0 )
ROM_REGION( 0x800000, "xa:ics", 0 )
ROM_LOAD( "fearlessp_u25_music0.u25", 0x000000, 0x400000, CRC(a015b9b1) SHA1(7b129c59acd523dec82e58a75d873bbc5341fb28) )
ROM_LOAD( "fearlessp_u26_music1.u26", 0x400000, 0x400000, CRC(9d5f18da) SHA1(42e5224c1af0898cc2e02b2e051ea8b629d5fb6d) )
ROM_END
@ -719,7 +520,7 @@ ROM_START( superkds )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "superkids_s019cn.u37", 0x000000, 0x80000, CRC(1a7f17dd) SHA1(ba20c0f521bff2f5ae2103ea49bd413b0e6459ba) )
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
ROM_LOAD( "superkids_mx10exa.u33", 0x000000, 0x10000, CRC(8baf5ba2) SHA1(2f8c2c48e756264e593bce7c09260e50d5cac827) ) // sticker marked G6
ROM_REGION( 0x2000000, "gfx1", 0 ) // FIXED BITS (0xxxxxxx) (graphics are 7bpp)
@ -728,7 +529,7 @@ ROM_START( superkds )
ROM_LOAD32_WORD( "superkids_cg-1l.u14", 0x1000000, 0x800000, CRC(57081c96) SHA1(886ac14ad1c9ce8c7a67bbfc6c00e7c75be634dc) )
ROM_LOAD32_WORD( "superkids_cg-1h.u13", 0x1000002, 0x800000, CRC(cd1e41ef) SHA1(a40bcbd97fa3e742e8f9c7b7c7d8879175bf10ee) )
ROM_REGION( 0x800000, "ics", 0 )
ROM_REGION( 0x800000, "xa:ics", 0 )
ROM_LOAD( "superkids_music0.u25", 0x000000, 0x400000, CRC(d7c37216) SHA1(ffcf7f1bf3093eb34ad0ae2cc89062de45b9d420) )
ROM_LOAD( "superkids_music1.u26", 0x400000, 0x400000, CRC(5f080dbf) SHA1(f02330db3336f6606aae9f5a9eca819701caa3bf) )
ROM_END
@ -741,7 +542,7 @@ ROM_START( icescape ) // IGS PCB-0433-16-GK (same PCB as Fearless Pinocchio) - H
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "icescape_v-104fa.u37", 0x000000, 0x80000, CRC(e3552726) SHA1(bac34ac4fce1519c1bc8020064090e77b5c2a629) ) // TMS27C240
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked O7
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU) marked O7
ROM_LOAD( "o7.u33", 0x00000, 0x10000, NO_DUMP )
ROM_REGION( 0x2000000, "gfx1", 0 ) // FIXED BITS (0xxxxxxx) (graphics are 7bpp)
@ -751,7 +552,7 @@ ROM_START( icescape ) // IGS PCB-0433-16-GK (same PCB as Fearless Pinocchio) - H
ROM_LOAD32_WORD( "icescape_fa_cg_u13.u13", 0x1000002, 0x800000, NO_DUMP )
// u17 and u18 not populated
ROM_REGION( 0x400000, "ics", 0 )
ROM_REGION( 0x400000, "xa:ics", 0 )
ROM_LOAD( "icescape_fa_sp_u25.u25", 0x000000, 0x200000, CRC(a01febd6) SHA1(6abe8b700c5725909939421e2493940421fc823f) ) // M27C160
ROM_LOAD( "icescape_fa_sp_u26.u26", 0x200000, 0x200000, CRC(35085613) SHA1(bdc6ecf5ee6fd095a56e33e8ce893fe05bcb426c) ) // M27C160
ROM_END
@ -773,6 +574,6 @@ void igs_fear_state::init_igs_icescape()
} // anonymous namespace
GAME( 2005, superkds, 0, igs_fear_xor, superkds, igs_fear_state, init_igs_superkds, ROT0, "IGS (Golden Dragon Amusement license)", "Super Kids / Jiu Nan Xiao Yingxiong (S019CN)", 0 )
GAME( 2005, superkds, 0, igs_fear_xor, superkds, igs_fear_state, init_igs_superkds, ROT0, "IGS (Golden Dragon Amusement license)", "Super Kids / Jiu Nan Xiao Yingxiong (S019CN)", MACHINE_NODEVICE_LAN )
GAME( 2006, fearless, 0, igs_fear_xor, fear, igs_fear_state, init_igs_fear, ROT0, "IGS (American Alpha license)", "Fearless Pinocchio (V101US)", 0 )
GAME( 2006, icescape, 0, igs_fear, fear, igs_fear_state, init_igs_icescape, ROT0, "IGS", "Icescape (V104FA)", MACHINE_IS_SKELETON ) // IGS FOR V104FA 2006-11-02

View File

@ -1089,7 +1089,6 @@ INPUT_PORTS_START( cjddz )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW1", 0x02, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(igs_m027_state, counter_w<0>) // coin or key-in
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_CONDITION("DSW1", 0x02, EQUALS, 0x00) PORT_WRITE_LINE_MEMBER(igs_m027_state, counter_w<1>) // hopper or key-out
PORT_START("DSW1")
PORT_DIPNAME( 0x01, 0x01, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW1:1") // 示范音乐
PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无
@ -2762,14 +2761,14 @@ void igs_m027_state::init_lhdmg()
// Complete dumps
GAME( 1999, slqz3, 0, slqz3_xor, slqz3, igs_m027_state, init_slqz3, ROT0, "IGS", "Mahjong Shuang Long Qiang Zhu 3 (China, VS107C)", MACHINE_NOT_WORKING ) // 双龙抢珠Ⅲ
GAME( 1999, qlgs, 0, qlgs_xor, qlgs, igs_m027_state, init_qlgs, ROT0, "IGS", "Que Long Gaoshou", MACHINE_NOT_WORKING ) // 雀龙高手
GAME( 1999, qlgs, 0, qlgs_xor, qlgs, igs_m027_state, init_qlgs, ROT0, "IGS", "Que Long Gaoshou", MACHINE_NOT_WORKING | MACHINE_NODEVICE_LAN ) // 雀龙高手
GAME( 1999, lhdmg, 0, lhdmg_xor, lhdmg, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Da Manguan", MACHINE_NOT_WORKING ) // 龙虎大满贯
GAME( 1999, lhdmgp, lhdmg, lhdmg_xor, lhdmg, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Da Manguan Plus", MACHINE_NOT_WORKING ) // 龙虎大满贯
GAME( 1999, lhzb3, 0, lhdmg_xor, lhzb3, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Zhengba III", MACHINE_NOT_WORKING ) // 龙虎争霸Ⅲ
GAME( 2004, lhzb4, 0, lhzb4_xor, lhzb4, igs_m027_state, init_lhzb4, ROT0, "IGS", "Long Hu Zhengba 4", MACHINE_NOT_WORKING ) // 龙虎争霸4
GAME( 1999, lthy, 0, lthy_xor, lthy, igs_m027_state, init_lthy, ROT0, "IGS", "Long Teng Hu Yue", MACHINE_NOT_WORKING ) // 龙腾虎跃
GAME( 1999, lthy, 0, lthy_xor, lthy, igs_m027_state, init_lthy, ROT0, "IGS", "Long Teng Hu Yue", MACHINE_NOT_WORKING | MACHINE_NODEVICE_LAN ) // 龙腾虎跃
GAME( 2000, zhongguo, 0, zhongguo_xor, zhongguo, igs_m027_state, init_zhongguo, ROT0, "IGS", "Zhongguo Chu Da D", MACHINE_NOT_WORKING ) // 中国锄大D
GAMEL( 200?, jking02, 0, jking02_xor, jking02, igs_m027_state, init_jking02, ROT0, "IGS", "Jungle King 2002 (V209US)", MACHINE_NOT_WORKING, layout_jking02 )
GAMEL( 200?, jking02, 0, jking02_xor, jking02, igs_m027_state, init_jking02, ROT0, "IGS", "Jungle King 2002 (V209US)", MACHINE_NOT_WORKING | MACHINE_NODEVICE_LAN, layout_jking02 )
GAME( 2003, mgzz, 0, mgzz_xor, mgzz, igs_m027_state, init_mgzz, ROT0, "IGS", "Manguan Zhizun (V101CN)", MACHINE_NOT_WORKING ) // 满贯至尊
GAME( 2003, mgzza, mgzz, mgzz_xor, mgzza, igs_m027_state, init_mgzz, ROT0, "IGS", "Manguan Zhizun (V100CN)", MACHINE_NOT_WORKING ) // 满贯至尊
GAME( 2007, mgcs3, 0, lhzb4_xor, mgcs3, igs_m027_state, init_mgcs3, ROT0, "IGS", "Manguan Caishen 3 (V101CN)", MACHINE_NOT_WORKING ) // 满贯财神3
@ -2780,7 +2779,7 @@ GAMEL( 1999, fruitpara, fruitpar, oceanpar_xor, fruitpara,igs_m027_state, init_f
GAME( 200?, cjddz, 0, cjddz_xor, cjddz, igs_m027_state, init_cjddz, ROT0, "IGS", "Chaoji Dou Dizhu", MACHINE_NOT_WORKING ) // 超级斗地主
GAME( 2001, extradrw, 0, m027, base, igs_m027_state, init_extradrw, ROT0, "IGS", "Extra Draw", MACHINE_NOT_WORKING )
// these have an IGS025 protection device instead of the 8255
GAME( 2002, chessc2, 0, chessc2_xor, chessc2, igs_m027_state, init_chessc2, ROT0, "IGS", "Chess Challenge II", MACHINE_NOT_WORKING )
GAME( 2002, chessc2, 0, chessc2_xor, chessc2, igs_m027_state, init_chessc2, ROT0, "IGS", "Chess Challenge II", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION )
// Incomplete dumps
GAME( 1999, amazonia, 0, m027, amazonia, igs_m027_state, init_amazonia, ROT0, "IGS", "Amazonia King (V104BR)", MACHINE_NOT_WORKING )

View File

@ -13,9 +13,9 @@ These games use the IGS027A processor.
#include "igs017_igs031.h"
#include "igs027a.h"
#include "pgmcrypt.h"
#include "xamcu.h"
#include "cpu/arm7/arm7core.h"
#include "cpu/xa/xa.h"
#include "machine/i8255.h"
#include "machine/nvram.h"
@ -72,7 +72,7 @@ protected:
private:
optional_shared_ptr<u32> m_igs_mainram;
required_device<igs027a_cpu_device> m_maincpu;
required_device<mx10exa_cpu_device> m_xa;
required_device<igs_xa_mcu_subcpu_device> m_xa;
required_device<i8255_device> m_ppi;
required_device<igs017_igs031_device> m_igs017_igs031;
required_device<okim6295_device> m_oki;
@ -88,17 +88,7 @@ private:
u32 m_xor_table[0x100];
u8 m_io_select[2];
u8 m_port2_latch;
u8 m_port0_latch;
u32 m_xa_cmd;
u32 m_xa_ret0;
bool m_irq_from_igs031;
bool m_irq_from_xa;
s8 m_num_params;
u8 m_port0_dat;
u8 m_port1_dat;
u8 m_port2_dat;
u8 m_port3_dat;
u32 m_igs_40000014;
@ -120,14 +110,7 @@ private:
void igs_40000014_w(offs_t offset, u32 data, u32 mem_mask);
u8 mcu_p0_r();
u8 mcu_p1_r();
u8 mcu_p2_r();
u8 mcu_p3_r();
void mcu_p0_w(uint8_t data);
void mcu_p1_w(uint8_t data);
void mcu_p2_w(uint8_t data);
void mcu_p3_w(uint8_t data);
void xa_irq(int state);
u32 gpio_r();
void oki_bank_w(offs_t offset, u8 data);
@ -138,17 +121,7 @@ private:
void igs_m027xa_state::machine_reset()
{
m_port2_latch = 0;
m_port0_latch = 0;
m_xa_cmd = 0;
m_xa_ret0 = 0;
m_irq_from_igs031 = false;
m_irq_from_xa = false;
m_num_params = 0;
m_port0_dat = 0;
m_port1_dat = 0;
m_port2_dat = 0;
m_port3_dat = 0;
m_igs_40000014 = 0;
}
@ -162,17 +135,7 @@ void igs_m027xa_state::machine_start()
save_item(NAME(m_xor_table));
save_item(NAME(m_io_select));
save_item(NAME(m_port2_latch));
save_item(NAME(m_port0_latch));
save_item(NAME(m_xa_cmd));
save_item(NAME(m_xa_ret0));
save_item(NAME(m_irq_from_igs031));
save_item(NAME(m_irq_from_xa));
save_item(NAME(m_num_params));
save_item(NAME(m_port0_dat));
save_item(NAME(m_port1_dat));
save_item(NAME(m_port2_dat));
save_item(NAME(m_port3_dat));
save_item(NAME(m_igs_40000014));
}
@ -202,7 +165,8 @@ void igs_m027xa_state::main_map(address_map &map)
map(0x50000000, 0x500003ff).umask32(0x000000ff).w(FUNC(igs_m027xa_state::xor_table_w));
map(0x58000000, 0x580000ff).rw(FUNC(igs_m027xa_state::xa_r), FUNC(igs_m027xa_state::xa_w));
map(0x58000000, 0x58000003).umask32(0x0000ffff).rw(m_xa, FUNC(igs_xa_mcu_subcpu_device::response_r), FUNC(igs_xa_mcu_subcpu_device::cmd_w));
map(0x58000000, 0x58000003).umask32(0xffff0000).w(m_xa, FUNC(igs_xa_mcu_subcpu_device::irqack_w));
}
void igs_m027xa_state::main_xor_map(address_map &map)
@ -235,18 +199,20 @@ static INPUT_PORTS_START( base )
PORT_START("TEST2")
PORT_BIT( 0x00007, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x00008, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_NAME("Stop Reel 2 / Small")
PORT_BIT( 0x00010, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_NAME("Stop Reel 3 / Take Score")
PORT_BIT( 0x00020, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_NAME("Stop Reel 1 / Double Up")
PORT_BIT( 0xfffc0, IP_ACTIVE_LOW, IPT_UNUSED ) // peripheral interrupts in bits 8 and 9 - see gpio_r
PORT_BIT( 0x00008, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_NAME("Stop Reel 2 / Small")
PORT_BIT( 0x00010, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_NAME("Stop Reel 3 / Take Score")
PORT_BIT( 0x00020, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_NAME("Stop Reel 1 / Double Up")
PORT_BIT( 0x001c0, IP_ACTIVE_LOW, IPT_UNUSED ) // IGS031 interrupt in bit 8 - see gpio_r
PORT_BIT( 0x00200, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("xa", igs_xa_mcu_subcpu_device, irq_r)
PORT_BIT( 0xffc00, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("DSW1")
PORT_DIPNAME( 0x01, 0x01, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW1:1")
PORT_DIPSETTING( 0x00, DEF_STR(Off) )
PORT_DIPSETTING( 0x01, DEF_STR(On) )
PORT_DIPNAME( 0x02, 0x02, "Non Stop" ) PORT_DIPLOCATION("SW1:2")
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPSETTING( 0x02, DEF_STR(No) )
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPNAME( 0x04, 0x04, "Password" ) PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING( 0x00, DEF_STR(No) )
PORT_DIPSETTING( 0x04, DEF_STR(Yes) )
@ -270,19 +236,19 @@ static INPUT_PORTS_START( base )
PORT_DIPSETTING( 0x02, DEF_STR(Yes) )
PORT_DIPSETTING( 0x03, DEF_STR(No) )
PORT_DIPNAME( 0x04, 0x04, "Play Score" ) PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPSETTING( 0x04, DEF_STR(No) )
PORT_DIPNAME( 0x08, 0x08, "Hand Count" ) PORT_DIPLOCATION("SW2:4")
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPNAME( 0x08, 0x08, "Hand Count" ) PORT_DIPLOCATION("SW2:4")
PORT_DIPSETTING( 0x08, DEF_STR(No) )
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPNAME( 0x30, 0x30, "Hold Pair" ) PORT_DIPLOCATION("SW2:5,6")
PORT_DIPSETTING( 0x30, DEF_STR(Off) )
PORT_DIPSETTING( 0x20, "Regular" )
PORT_DIPSETTING( 0x00, "Georgia" )
PORT_DIPSETTING( 0x10, "Georgia (duplicate)" )
PORT_DIPSETTING( 0x20, "Regular" )
PORT_DIPSETTING( 0x30, DEF_STR(Off) )
PORT_DIPNAME( 0x40, 0x40, "Auto Hold" ) PORT_DIPLOCATION("SW2:7")
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPSETTING( 0x40, DEF_STR(No) )
PORT_DIPSETTING( 0x00, DEF_STR(Yes) )
PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW2:8" )
PORT_START("DSW3")
@ -297,20 +263,6 @@ static INPUT_PORTS_START( base )
INPUT_PORTS_END
u16 igs_m027xa_state::xa_r(offs_t offset, u16 mem_mask)
{
u32 data = ~u32(0);
switch (offset * 2)
{
case 0:
data = m_xa_ret0;
break;
}
return data;
}
void igs_m027xa_state::output_w(u8 data)
{
machine().bookkeeping().coin_counter_w(0, BIT(data, 0)); // one pulse per COINA accepted
@ -352,8 +304,6 @@ u32 igs_m027xa_state::gpio_r()
u32 ret = m_io_test[2].read_safe(0xfffff);
if (m_irq_from_igs031)
ret &= ~(u32(1) << 8);
if (m_irq_from_xa)
ret &= ~(u32(1) << 9);
return ret;
}
@ -380,114 +330,11 @@ void igs_m027xa_state::io_select_w(u8 data)
m_io_select[Select] = data;
}
void igs_m027xa_state::xa_w(offs_t offset, u16 data, u16 mem_mask)
void igs_m027xa_state::xa_irq(int state)
{
m_xa_cmd = data;
if (offset == 0)
{
m_num_params--;
if (m_num_params <= 0)
{
LOGMASKED(LOG_DEBUG, "---------------m_xa_cmd is %02x size %02x\n", (data & 0xff00)>>8, data & 0xff);
m_num_params = data & 0xff;
}
else
{
LOGMASKED(LOG_DEBUG, "-------------------------- param %04x\n", data & 0xffff);
}
m_xa->set_input_line(XA_EXT_IRQ0, ASSERT_LINE);
}
else
{
m_irq_from_xa = false;
LOGMASKED(LOG_DEBUG, "%s: unhandled xa_w %04x %08x (%08x)\n", machine().describe_context(), offset * 2, data, mem_mask);
}
}
u8 igs_m027xa_state::mcu_p0_r()
{
u8 ret = m_port0_latch;
LOGMASKED(LOG_DEBUG, "%s: COMMAND READ LOWER mcu_p0_r() returning %02x with port3 as %02x\n", machine().describe_context(), ret, m_port3_dat);
return ret;
}
u8 igs_m027xa_state::mcu_p1_r()
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p1_r()\n", machine().describe_context());
return m_port1_dat;
}
u8 igs_m027xa_state::mcu_p2_r()
{
u8 ret = m_port2_latch;
LOGMASKED(LOG_DEBUG, "%s: COMMAND READ mcu_p2_r() returning %02x with port3 as %02x\n", machine().describe_context(), ret, m_port3_dat);
return m_port2_latch;
}
u8 igs_m027xa_state::mcu_p3_r()
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p3_r()\n", machine().describe_context());
return m_port3_dat;
}
template <typename T>
constexpr bool posedge(T oldval, T val, unsigned bit)
{
return BIT(~oldval & val, bit);
}
template <typename T>
constexpr bool negedge(T oldval, T val, unsigned bit)
{
return BIT(oldval & ~val, bit);
}
void igs_m027xa_state::mcu_p0_w(uint8_t data)
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p0_w() %02x with port 3 as %02x and port 1 as %02x\n", machine().describe_context(), data, m_port3_dat, m_port1_dat);
m_port0_dat = data;
}
void igs_m027xa_state::mcu_p1_w(uint8_t data)
{
LOGMASKED(LOG_DEBUG, "%s: mcu_p1_w() %02x\n", machine().describe_context(), data);
m_port1_dat = data;
}
void igs_m027xa_state::mcu_p2_w(uint8_t data)
{
m_port2_dat = data;
LOGMASKED(LOG_DEBUG, "%s: mcu_p2_w() %02x with port 3 as %02x\n", machine().describe_context(), data, m_port3_dat);
}
void igs_m027xa_state::mcu_p3_w(uint8_t data)
{
u8 oldport3 = m_port3_dat;
m_port3_dat = data;
LOGMASKED(LOG_DEBUG, "%s: mcu_p3_w() %02x - do latches oldport3 %02x newport3 %02x\n", machine().describe_context(), data, oldport3, m_port3_dat);
if (posedge(oldport3, m_port3_dat, 5))
{
m_irq_from_xa = true;
if (state)
m_maincpu->trigger_irq(3);
}
// high->low transition on bit 0x80 must read into latches!
if (negedge(oldport3, m_port3_dat, 7))
{
LOGMASKED(LOG_DEBUG, "read command [%d] = [%04x]\n", m_port1_dat & 7, m_xa_cmd);
m_port2_latch = (m_xa_cmd & 0xff00) >> 8;
m_port0_latch = m_xa_cmd & 0x00ff;
}
if (negedge(oldport3, m_port3_dat, 6))
{
uint32_t dat = (m_port2_dat << 8) | m_port0_dat;
LOGMASKED(LOG_DEBUG, "write command [%d] = [%04x]\n", m_port1_dat & 7, dat);
m_xa_ret0 = dat;
}
}
u32 igs_m027xa_state::external_rom_r(offs_t offset)
@ -511,7 +358,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(igs_m027xa_state::interrupt)
if (scanline == 240 && m_igs017_igs031->get_irq_enable())
{
m_irq_from_igs031 = true;
m_irq_from_igs031 = true; // FIXME: this should be cleared at some point
m_maincpu->trigger_irq(3);
}
if (scanline == 0 && (m_igs_40000014 & 1))
@ -528,15 +375,8 @@ void igs_m027xa_state::igs_mahjong_xa(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
MX10EXA(config, m_xa, 10'000'000); // MX10EXAQC (Philips 80C51 XA) unknown frequency
m_xa->port_in_cb<0>().set(FUNC(igs_m027xa_state::mcu_p0_r));
m_xa->port_in_cb<1>().set(FUNC(igs_m027xa_state::mcu_p1_r));
m_xa->port_in_cb<2>().set(FUNC(igs_m027xa_state::mcu_p2_r));
m_xa->port_in_cb<3>().set(FUNC(igs_m027xa_state::mcu_p3_r));
m_xa->port_out_cb<0>().set(FUNC(igs_m027xa_state::mcu_p0_w));
m_xa->port_out_cb<1>().set(FUNC(igs_m027xa_state::mcu_p1_w));
m_xa->port_out_cb<2>().set(FUNC(igs_m027xa_state::mcu_p2_w));
m_xa->port_out_cb<3>().set(FUNC(igs_m027xa_state::mcu_p3_w));
IGS_XA_SUBCPU(config, m_xa, 10'000'000); // MX10EXAQC (Philips 80C51 XA) unknown frequency
m_xa->irq().set(FUNC(igs_m027xa_state::xa_irq));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
@ -598,7 +438,7 @@ ROM_START( haunthig )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "hauntedhouse_ver-109us.u34", 0x000000, 0x80000, CRC(300fed78) SHA1(afa4c8855cd780c57d4f92ea6131ed4e77063268) )
ROM_REGION( 0x10000, "xa", 0 )
ROM_REGION( 0x10000, "xa:mcu", 0 )
ROM_LOAD( "hauntedhouse.u17", 0x000000, 0x10000, BAD_DUMP CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) ) // not dumped for this set
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -625,7 +465,7 @@ ROM_START( haunthiga ) // IGS PCB-0575-04-HU - Has IGS027A, MX10EXAQC, IGS031, O
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "hauntedhouse_ver-101us.u34", 0x000000, 0x80000, CRC(4bf045d4) SHA1(78c848fd69961df8d9b75f92ad57c3534fbf08db) )
ROM_REGION( 0x10000, "xa", 0 )
ROM_REGION( 0x10000, "xa:mcu", 0 )
ROM_LOAD( "hauntedhouse.u17", 0x000000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) ) // MX10EXAQC (80C51 XA based MCU) marked J9, not read protected?
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -652,7 +492,7 @@ ROM_START( crzybugs ) // IGS PCB-0447-05-GM - Has IGS027A, MX10EXAQC, IGS031, Ok
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "crazy_bugs_v-204us.u23", 0x000000, 0x80000, CRC(d1232462) SHA1(685a292f39bf57a80d6ef31289cf9f673ba06dd4) ) // MX27C4096
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked J9
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU) marked J9
ROM_LOAD( "j9.u27", 0x00000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) )
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -675,7 +515,7 @@ ROM_START( crzybugsa )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "crazy_bugs_v-202us.u23", 0x000000, 0x80000, CRC(210da1e6) SHA1(c726497bebd25d6a9053e331b4c26acc7e2db0b2) ) // MX27C4096
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU)
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU)
ROM_LOAD( "j9.u27", 0x00000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) )
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -698,7 +538,7 @@ ROM_START( crzybugsb )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "crazy_bugs_v-202us.u23", 0x000000, 0x80000, CRC(129e36e9) SHA1(53f20bc3792249de8ef276f84283baa9abd30acd) ) // MX27C4096
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU)
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU)
ROM_LOAD( "j9.u27", 0x00000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) )
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -721,7 +561,7 @@ ROM_START( crzybugsj ) // IGS PCB-0575-04-HU - Has IGS027A, MX10EXAQC, IGS031, O
ROM_REGION32_LE( 0x200000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "crazy_bugs_v-103jp.u34", 0x000000, 0x200000, CRC(1e35ed79) SHA1(0e4f8b706cdfcaf2aacdc40eec422df9d865b311) )
ROM_REGION( 0x10000, "xa", 0 )
ROM_REGION( 0x10000, "xa:mcu", 0 )
ROM_LOAD( "e9.u17", 0x00000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) ) // MX10EXAQC (80C51 XA based MCU) marked E9, same as haunthig
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -749,7 +589,7 @@ ROM_START( tripfev ) // IGS PCB-0447-05-GM - Has IGS027A, MX10EXAQC, IGS031, Oki
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "triple_fever_u23_v107_us.u23", 0x000000, 0x80000, CRC(aa56d888) SHA1(0b8b2765079259b76ea803289841d867c33c8cb2) ) // 27C4096
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked P7
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU) marked P7
ROM_LOAD( "p7.u27", 0x00000, 0x10000, NO_DUMP )
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -771,7 +611,7 @@ ROM_START( wldfruit ) // IGS PCB-0447-05-GM - Has IGS027A, MX10EXAQC, IGS031, Ok
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "wild_fruit_v-208us.u23", 0x000000, 0x80000, CRC(d43398f1) SHA1(ecc4bd5cb6da16b35c63b843cf7beec1ab84ed9d) ) // M27C4002
ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked J9
ROM_REGION( 0x10000, "xa:mcu", 0 ) // MX10EXAQC (80C51 XA based MCU) marked J9
ROM_LOAD( "j9.u27", 0x00000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) )
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@ -852,9 +692,9 @@ void igs_m027xa_state::init_wldfruit()
GAME( 2008, haunthig, 0, igs_mahjong_xa, base, igs_m027xa_state, init_hauntedh, ROT0, "IGS", "Haunted House (IGS, V109US)", MACHINE_IS_SKELETON ) // IGS FOR V109US 2008 10 14
GAME( 2006, haunthiga, haunthig, igs_mahjong_xa, base, igs_m027xa_state, init_hauntedh, ROT0, "IGS", "Haunted House (IGS, V101US)", MACHINE_IS_SKELETON ) // IGS FOR V101US 2006 08 23
GAMEL( 2009, crzybugs, 0, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V204US)", MACHINE_IS_SKELETON, layout_crzybugs ) // IGS FOR V204US 2009 5 19
GAMEL( 2006, crzybugsa, crzybugs, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V202US)", MACHINE_IS_SKELETON, layout_crzybugs ) // IGS FOR V100US 2006 3 29 but also V202US string
GAMEL( 2005, crzybugsb, crzybugs, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V200US)", MACHINE_IS_SKELETON, layout_crzybugs ) // FOR V100US 2005 7 20 but also V200US string
GAMEL( 2009, crzybugs, 0, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V204US)", MACHINE_NOT_WORKING, layout_crzybugs ) // IGS FOR V204US 2009 5 19
GAMEL( 2006, crzybugsa, crzybugs, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V202US)", MACHINE_NOT_WORKING, layout_crzybugs ) // IGS FOR V100US 2006 3 29 but also V202US string
GAMEL( 2005, crzybugsb, crzybugs, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V200US)", MACHINE_NOT_WORKING, layout_crzybugs ) // FOR V100US 2005 7 20 but also V200US string
GAME( 2007, crzybugsj, crzybugs, igs_mahjong_xa, base, igs_m027xa_state, init_crzybugsj, ROT0, "IGS", "Crazy Bugs (V103JP)", MACHINE_IS_SKELETON ) // IGS FOR V101JP 2007 06 08

317
src/mame/igs/xamcu.cpp Normal file
View File

@ -0,0 +1,317 @@
// license:BSD-3-Clause
// copyright-holders:XingXing, Vas Crabb
#include "emu.h"
#include "xamcu.h"
#include "speaker.h"
//#define VERBOSE 1
#include "logmacro.h"
namespace {
template <typename T>
constexpr bool posedge(T old, T val, unsigned bit)
{
return bool(BIT(~old & val, bit));
}
template <typename T>
constexpr bool negedge(T old, T val, unsigned bit)
{
return bool(BIT(old & ~val, bit));
}
} // anonymous namespace
DEFINE_DEVICE_TYPE(IGS_XA_ICS_SOUND, igs_xa_mcu_ics_sound_device, "igs_xa_ics_sound", "IGS MX10EXAQC-based ICS2115 sound system")
DEFINE_DEVICE_TYPE(IGS_XA_SUBCPU, igs_xa_mcu_subcpu_device, "igs_xa_subcpu", "IGS MX10EXAQC sub-CPU")
igs_xa_mcu_device_base::igs_xa_mcu_device_base(
machine_config const &mconfig,
device_type type,
char const *tag,
device_t *owner,
u32 clock) :
device_t(mconfig, type, tag, owner, clock),
m_mcu(*this, "mcu"),
m_irq_cb(*this),
m_command(0),
m_num_params(0),
m_port_dat{ 0, 0, 0, 0 },
m_port0_latch(0),
m_port2_latch(0),
m_irq(0)
{
}
igs_xa_mcu_device_base::~igs_xa_mcu_device_base()
{
}
void igs_xa_mcu_device_base::cmd_w(u16 data)
{
m_command = data;
m_num_params--;
if (m_num_params <= 0)
{
LOG("command is %02x size %02x\n", data >> 8, data & 0x00ff);
m_num_params = data & 0x00ff;
}
else
{
LOG("param %04x\n", data);
}
m_mcu->pulse_input_line(XA_EXT_IRQ0, m_mcu->minimum_quantum_time());
}
void igs_xa_mcu_device_base::device_add_mconfig(machine_config &config)
{
MX10EXA(config, m_mcu, DERIVED_CLOCK(1, 1)); // MX10EXAQC (Philips 80C51XA)
m_mcu->port_in_cb<0>().set(FUNC(igs_xa_mcu_device_base::mcu_p0_r));
m_mcu->port_in_cb<1>().set(FUNC(igs_xa_mcu_device_base::mcu_p1_r));
m_mcu->port_in_cb<2>().set(FUNC(igs_xa_mcu_device_base::mcu_p2_r));
m_mcu->port_in_cb<3>().set(FUNC(igs_xa_mcu_device_base::mcu_p3_r));
m_mcu->port_out_cb<0>().set(FUNC(igs_xa_mcu_device_base::mcu_p0_w));
m_mcu->port_out_cb<1>().set(FUNC(igs_xa_mcu_device_base::mcu_p1_w));
m_mcu->port_out_cb<2>().set(FUNC(igs_xa_mcu_device_base::mcu_p2_w));
m_mcu->port_out_cb<3>().set(FUNC(igs_xa_mcu_device_base::mcu_p3_w));
}
void igs_xa_mcu_device_base::device_start()
{
save_item(NAME(m_command));
save_item(NAME(m_num_params));
save_item(NAME(m_port_dat));
save_item(NAME(m_port0_latch));
save_item(NAME(m_port2_latch));
save_item(NAME(m_irq));
}
void igs_xa_mcu_device_base::device_reset()
{
m_command = 0;
m_num_params = 0;
}
inline void igs_xa_mcu_device_base::set_irq(int state)
{
if (bool(m_irq) != bool(state))
{
m_irq = state;
m_irq_cb(state);
}
}
u8 igs_xa_mcu_device_base::mcu_p0_r()
{
LOG("%s: COMMAND READ LOWER mcu_p0_r() returning %02x with port3 as %02x\n", machine().describe_context(), m_port0_latch, m_port_dat[3]);
return m_port0_latch;
}
u8 igs_xa_mcu_device_base::mcu_p1_r()
{
LOG("%s: mcu_p1_r()\n", machine().describe_context());
return m_port_dat[1]; // superkds XA will end up failing returning port1 dat for now, but not attempt to play any sounds otherwise?
}
u8 igs_xa_mcu_device_base::mcu_p2_r()
{
LOG("%s: COMMAND READ mcu_p2_r() returning %02x with port3 as %02x\n", machine().describe_context(), m_port2_latch, m_port_dat[3]);
return m_port2_latch;
}
u8 igs_xa_mcu_device_base::mcu_p3_r()
{
LOG("%s: mcu_p3_r()\n", machine().describe_context());
return m_port_dat[3];
}
void igs_xa_mcu_device_base::mcu_p0_w(u8 data)
{
LOG("%s: mcu_p0_w() %02x with port 3 as %02x and port 1 as %02x\n", machine().describe_context(), data, m_port_dat[3], m_port_dat[1]);
m_port_dat[0] = data;
}
void igs_xa_mcu_device_base::mcu_p1_w(u8 data)
{
LOG("%s: mcu_p1_w() %02x\n", machine().describe_context(), data);
m_port_dat[1] = data;
}
void igs_xa_mcu_device_base::mcu_p2_w(u8 data)
{
LOG("%s: mcu_p2_w() %02x with port 3 as %02x\n", machine().describe_context(), data, m_port_dat[3]);
m_port_dat[2] = data;
}
void igs_xa_mcu_device_base::mcu_p3_w(u8 data)
{
LOG("%s: mcu_p3_w() %02x - do latches oldport3 %02x newport3 %02x\n", machine().describe_context(), data, m_port_dat[3], data);
m_port_dat[3] = data;
}
igs_xa_mcu_ics_sound_device::igs_xa_mcu_ics_sound_device(
machine_config const &mconfig,
char const *tag,
device_t *owner,
u32 clock) :
igs_xa_mcu_device_base(mconfig, IGS_XA_ICS_SOUND, tag, owner, clock),
m_ics(*this, "ics"),
m_response{ 0, 0 }
{
}
igs_xa_mcu_ics_sound_device::~igs_xa_mcu_ics_sound_device()
{
}
void igs_xa_mcu_ics_sound_device::device_add_mconfig(machine_config &config)
{
igs_xa_mcu_device_base::device_add_mconfig(config);
m_mcu->port_out_cb<1>().set(FUNC(igs_xa_mcu_ics_sound_device::mcu_p1_w));
m_mcu->port_out_cb<3>().set(FUNC(igs_xa_mcu_ics_sound_device::mcu_p3_w));
SPEAKER(config, "mono").front_center();
ICS2115(config, m_ics, 33.8688_MHz_XTAL); // TODO: Correct?
m_ics->irq().set_inputline(m_mcu, XA_EXT_IRQ2);
m_ics->add_route(ALL_OUTPUTS, "mono", 5.0);
}
void igs_xa_mcu_ics_sound_device::device_start()
{
igs_xa_mcu_device_base::device_start();
save_item(NAME(m_response));
}
void igs_xa_mcu_ics_sound_device::mcu_p1_w(u8 data)
{
igs_xa_mcu_device_base::mcu_p1_w(data);
set_irq(BIT(data, 3));
}
void igs_xa_mcu_ics_sound_device::mcu_p3_w(u8 data)
{
u8 const oldport3 = m_port_dat[3];
igs_xa_mcu_device_base::mcu_p3_w(data);
// high->low transition on bit 0x80 must read into latches!
if (negedge(oldport3, data, 7))
{
if (!BIT(data, 4))
{
m_port0_latch = m_ics->read(m_port_dat[1] & 7);
LOG("read from ics [%d] = [%02x]\n", m_port_dat[1] & 7, m_port0_latch);
}
else if (!BIT(data, 5))
{
LOG("read command [%d] = [%04x]\n", m_port_dat[1] & 7, m_command);
m_port2_latch = m_command >> 8;
m_port0_latch = m_command & 0x00ff;
}
}
if (negedge(oldport3, data, 6))
{
if (!BIT(data, 4))
{
LOG("write to ics [%d] = [%02x]\n", m_port_dat[1] & 7, m_port_dat[0]);
m_ics->write(m_port_dat[1] & 7, m_port_dat[0]);
}
else if (!BIT(data, 5))
{
u16 const dat = (u16(m_port_dat[2]) << 8) | m_port_dat[0];
LOG("write response [%d] = [%04x]\n", m_port_dat[1] & 7, dat);
switch (m_port_dat[1] & 7)
{
case 1:
m_response[1] = dat;
break;
case 2:
m_response[0] = dat;
break;
}
}
}
}
igs_xa_mcu_subcpu_device::igs_xa_mcu_subcpu_device(
machine_config const &mconfig,
char const *tag,
device_t *owner,
u32 clock) :
igs_xa_mcu_device_base(mconfig, IGS_XA_SUBCPU, tag, owner, clock),
m_response(0)
{
}
igs_xa_mcu_subcpu_device::~igs_xa_mcu_subcpu_device()
{
}
void igs_xa_mcu_subcpu_device::irqack_w(u16 data)
{
LOG("%s: lower IRQ %08x\n", machine().describe_context(), data);
m_command = data;
set_irq(0);
}
void igs_xa_mcu_subcpu_device::device_add_mconfig(machine_config &config)
{
igs_xa_mcu_device_base::device_add_mconfig(config);
m_mcu->port_out_cb<3>().set(FUNC(igs_xa_mcu_subcpu_device::mcu_p3_w));
}
void igs_xa_mcu_subcpu_device::device_start()
{
igs_xa_mcu_device_base::device_start();
save_item(NAME(m_response));
}
void igs_xa_mcu_subcpu_device::mcu_p3_w(u8 data)
{
u8 const oldport3 = m_port_dat[3];
igs_xa_mcu_device_base::mcu_p3_w(data);
set_irq(BIT(data, 5));
// high->low transition on bit 0x80 must read into latches!
if (negedge(oldport3, data, 7))
{
LOG("read command [%d] = [%04x]\n", m_port_dat[1] & 7, m_command);
m_port2_latch = m_command >> 8;
m_port0_latch = m_command & 0x00ff;
}
if (negedge(oldport3, data, 6))
{
u16 const dat = (u16(m_port_dat[2]) << 8) | m_port_dat[0];
LOG("write response [%d] = [%04x]\n", m_port_dat[1] & 7, dat);
m_response = dat;
}
}

104
src/mame/igs/xamcu.h Normal file
View File

@ -0,0 +1,104 @@
// license:BSD-3-Clause
// copyright-holders:XingXing, Vas Crabb
#ifndef MAME_IGS_XAMCU_H
#define MAME_IGS_XAMCU_H
#pragma once
#include "cpu/xa/xa.h"
#include "sound/ics2115.h"
class igs_xa_mcu_device_base : public device_t
{
public:
virtual ~igs_xa_mcu_device_base();
auto irq() { return m_irq_cb.bind(); }
void cmd_w(u16 data);
int irq_r() const { return m_irq; }
protected:
igs_xa_mcu_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
void set_irq(int state);
u8 mcu_p0_r();
u8 mcu_p1_r();
u8 mcu_p2_r();
u8 mcu_p3_r();
void mcu_p0_w(u8 data);
void mcu_p1_w(u8 data);
void mcu_p2_w(u8 data);
void mcu_p3_w(u8 data);
required_device<mx10exa_cpu_device> m_mcu;
devcb_write_line m_irq_cb;
u16 m_command;
s16 m_num_params;
u8 m_port_dat[4];
u8 m_port0_latch;
u8 m_port2_latch;
u8 m_irq;
};
class igs_xa_mcu_ics_sound_device : public igs_xa_mcu_device_base
{
public:
igs_xa_mcu_ics_sound_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
virtual ~igs_xa_mcu_ics_sound_device();
u16 response_low_r() { return m_response[0]; }
u16 response_high_r() { return m_response[1]; }
u16 cmd_r() const { return m_command; } // hack for HLE'ing unimplemented functionality
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override ATTR_COLD;
void mcu_p1_w(u8 data);
void mcu_p3_w(u8 data);
required_device<ics2115_device> m_ics;
u16 m_response[2];
};
class igs_xa_mcu_subcpu_device : public igs_xa_mcu_device_base
{
public:
igs_xa_mcu_subcpu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
virtual ~igs_xa_mcu_subcpu_device();
void set_disable() { m_mcu.lookup()->set_disable(); }
void irqack_w(u16 data);
u16 response_r() { return m_response; }
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override ATTR_COLD;
void mcu_p3_w(u8 data);
u16 m_response;
};
DECLARE_DEVICE_TYPE(IGS_XA_ICS_SOUND, igs_xa_mcu_ics_sound_device)
DECLARE_DEVICE_TYPE(IGS_XA_SUBCPU, igs_xa_mcu_subcpu_device)
#endif // MAME_IGS_XAMCU_H