Previous 199869 Revisions Next

r31726 Thursday 21st August, 2014 at 14:35:43 UTC by Luca Elia
Preliminary IGS029 protection simulation for mgcs: [Luca Elia]
fixes sound, dips and crash at game start.
[src/mame/drivers]igs017.c

trunk/src/mame/drivers/igs017.c
r31725r31726
3030- Protection emulation, instead of patching the roms.
3131- NVRAM.
3232- iqblockf: protection.
33- mgcs: implement joystick inputs. Sound banking and DSW go through protection.
33- mgcs: implement joystick inputs. Finish IGS029 protection simulation.
3434
3535Notes:
3636
r31725r31726
5050#include "sound/okim6295.h"
5151#include "machine/igs025.h"
5252#include "machine/igs022.h"
53#include "machine/ticket.h"
5354
5455class igs017_state : public driver_device
5556{
r31725r31726
6263      m_fg_videoram(*this, "fg_videoram", 0),
6364      m_bg_videoram(*this, "bg_videoram", 0),
6465      m_oki(*this, "oki"),
66      m_hopperdev(*this, "hopper"),
6567      m_igs025(*this,"igs025"),
6668      m_igs022(*this,"igs022"),
6769      m_gfxdecode(*this, "gfxdecode"),
r31725r31726
7779   optional_shared_ptr<UINT8> m_fg_videoram;
7880   optional_shared_ptr<UINT8> m_bg_videoram;
7981   required_device<okim6295_device> m_oki;
82   optional_device<ticket_dispenser_device> m_hopperdev;
8083   optional_device<igs025_device> m_igs025; // Mj Shuang Long Qiang Zhu 2
8184   optional_device<igs022_device> m_igs022; // Mj Shuang Long Qiang Zhu 2
8285   required_device<gfxdecode_device> m_gfxdecode;
r31725r31726
102105   UINT16 m_igs_magic[2];
103106   UINT8 m_scramble_data;
104107   int m_irq1_enable;
108   UINT8 m_dsw_select;
105109
106110   // lhzb2a protection:
107111   UINT16 m_prot_regs[2], m_prot_val, m_prot_word, m_prot_m3, m_prot_mf;
108112   UINT8 m_prot2;
109113
114   // IGS029 protection (communication)
115   UINT8 m_igs029_send_data, m_igs029_recv_data;
116   UINT8 m_igs029_send_buf[256], m_igs029_recv_buf[256];
117   int m_igs029_send_len, m_igs029_recv_len;
118   // IGS029 protection (mgcs)
119   UINT32 m_igs029_mgcs_long;
120
110121   int m_irq2_enable;
111122   DECLARE_WRITE8_MEMBER(video_disable_w);
112123   DECLARE_WRITE16_MEMBER(video_disable_lsb_w);
r31725r31726
174185   TILE_GET_INFO_MEMBER(get_fg_tile_info);
175186   TILE_GET_INFO_MEMBER(get_bg_tile_info);
176187   virtual void video_start();
177   virtual void video_reset();
188   virtual void machine_reset();
178189   DECLARE_MACHINE_RESET(iqblocka);
179190   DECLARE_MACHINE_RESET(mgcs);
180191   DECLARE_MACHINE_RESET(lhzb2a);
r31725r31726
193204   void mgcs_decrypt_tiles();
194205   void mgcs_flip_sprites();
195206   void mgcs_patch_rom();
207   void mgcs_igs029_run();
196208   void starzan_decrypt(UINT8 *ROM, int size, bool isOpcode);
197209   void lhzb2_patch_rom();
198210   void lhzb2_decrypt_tiles();
r31725r31726
202214   void spkrform_decrypt_sprites();
203215};
204216
217void igs017_state::machine_reset()
218{
219   m_video_disable = 0;
220   m_igs029_send_len = m_igs029_recv_len = 0;
221}
205222
206
207223/***************************************************************************
208224                                Video Hardware
209225***************************************************************************/
r31725r31726
221237      video_disable_w(space,offset,data);
222238}
223239
224void igs017_state::video_reset()
225{
226   m_video_disable = 0;
227}
228240
229
230241#define COLOR(_X)   (((_X)>>2)&7)
231242
232243TILE_GET_INFO_MEMBER(igs017_state::get_fg_tile_info)
r31725r31726
709720
710721void igs017_state::mgcs_patch_rom()
711722{
712   UINT16 *rom = (UINT16 *)memregion("maincpu")->base();
723//   UINT16 *rom = (UINT16 *)memregion("maincpu")->base();
713724
714   rom[0x4e036/2] = 0x6006;
725//   rom[0x20666/2] = 0x601e;    // 020666: 671E    beq $20686 (rom check)
715726
716   // IGS029 reads the dips?
717   rom[0x4e00e/2] = 0x4e75;
718
719   rom[0x4dfce/2] = 0x6010;    // 04DFCE: 6610    bne $4dfe0
720   rom[0x20666/2] = 0x601e;    // 020666: 671E    beq $20686 (rom check)
727   // IGS029 send command
728//   rom[0x4dfce/2] = 0x6010;    // 04DFCE: 6610    bne $4dfe0
729//   rom[0x4e00e/2] = 0x4e75;
730//   rom[0x4e036/2] = 0x6006;   // 04E036: 6306    bls     $4e03e
721731}
722732
723733DRIVER_INIT_MEMBER(igs017_state,mgcs)
r31725r31726
14251435
14261436// mgcs
14271437
1438// IGS029 appears to be an MCU that receives commands (write port with value, read port, etc.)
1439// Sound banking and DSW are accessed through it. It also performs some game specific calculations.
1440void igs017_state::mgcs_igs029_run()
1441{
1442   logerror("%s: running igs029 command ", machine().describe_context());
1443   for (int i = 0; i < m_igs029_send_len; i++)
1444      logerror("%02x ", m_igs029_send_buf[i]);
14281445
1446   if (m_igs029_send_buf[0] == 0x05 && m_igs029_send_buf[1] == 0x5a)
1447   {
1448      UINT8 data = m_igs029_send_buf[2];
1449      UINT8 port = m_igs029_send_buf[3];
1450
1451      logerror("PORT %02x = %02x\n", port, data);
1452
1453      switch (port)
1454      {
1455         case 0x01:
1456            m_oki->set_bank_base((data & 0x10) ? 0x40000 : 0);
1457            coin_counter_w(machine(), 0, (~data) & 0x20);   // coin in
1458            coin_counter_w(machine(), 1, (~data) & 0x40);   // coin out
1459
1460//            popmessage("PORT1 %02X", data);
1461
1462            if ( data & ~0x70 )
1463               logerror("%s: warning, unknown bits written in port %02x = %02x\n", machine().describe_context(), port, data);
1464
1465            break;
1466
1467         case 0x03:
1468            m_dsw_select = data;
1469
1470//            popmessage("PORT3 %02X", data);
1471
1472            if ( data & ~0x03 )
1473               logerror("%s: warning, unknown bits written in port %02x = %02x\n", machine().describe_context(), port, data);
1474
1475            break;
1476
1477         default:
1478            logerror("%s: warning, unknown port %02x written with %02x\n", machine().describe_context(), port, data);
1479      }
1480
1481      m_igs029_recv_len = 0;
1482      m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;
1483   }
1484   else if (m_igs029_send_buf[0] == 0x03 && m_igs029_send_buf[1] == 0x55)
1485   {
1486      logerror("MIN BET?\n");
1487
1488      // No inputs. Returns 1 long
1489
1490      UINT8 min_bets[4] = {1, 2, 3, 5};
1491
1492      m_igs029_recv_len = 0;
1493      m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
1494      m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
1495      m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
1496      m_igs029_recv_buf[m_igs029_recv_len++] = min_bets[ (~ioport("DSW2")->read()) & 3 ];
1497      m_igs029_recv_buf[m_igs029_recv_len++] = 0x05;
1498   }
1499   else if (m_igs029_send_buf[0] == 0x03 && m_igs029_send_buf[1] == 0x39)
1500   {
1501      logerror("READ DSW\n");
1502
1503      UINT8 ret;
1504      if      (~m_dsw_select & 0x01)   ret = ioport("DSW1")->read();
1505      else if (~m_dsw_select & 0x02)   ret = ioport("DSW2")->read();
1506      else
1507      {
1508         logerror("%s: warning, reading dsw with dsw_select = %02x\n", machine().describe_context(), m_dsw_select);
1509         ret = 0xff;
1510      }
1511
1512      m_igs029_recv_len = 0;
1513      m_igs029_recv_buf[m_igs029_recv_len++] = ret;
1514      m_igs029_recv_buf[m_igs029_recv_len++] = 0x02;
1515   }
1516   else if (m_igs029_send_buf[0] == 0x07 && m_igs029_send_buf[1] == 0x2c)
1517   {
1518      logerror("?? (2C)\n");   // ??
1519
1520      // 4 inputs. Returns 1 long
1521
1522      // called when pressing start without betting.
1523      // Returning high values produces an overflow causing a division by 0, and then the game hangs.
1524      m_igs029_recv_len = 0;
1525      m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
1526      m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
1527      m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
1528      m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;   // ??
1529      m_igs029_recv_buf[m_igs029_recv_len++] = 0x05;
1530   }
1531   else if (m_igs029_send_buf[0] == 0x07 && m_igs029_send_buf[1] == 0x15)
1532   {
1533      logerror("SET LONG\n");
1534
1535      m_igs029_mgcs_long = (m_igs029_send_buf[2] << 24) | (m_igs029_send_buf[3] << 16) | (m_igs029_send_buf[4] << 8) | m_igs029_send_buf[5];
1536
1537      m_igs029_recv_len = 0;
1538      m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;
1539   }
1540   else if (m_igs029_send_buf[0] == 0x03 && m_igs029_send_buf[1] == 0x04)
1541   {
1542      logerror("GET LONG\n");
1543
1544      m_igs029_recv_len = 0;
1545      m_igs029_recv_buf[m_igs029_recv_len++] = (m_igs029_mgcs_long >>  0) & 0xff;
1546      m_igs029_recv_buf[m_igs029_recv_len++] = (m_igs029_mgcs_long >>  8) & 0xff;
1547      m_igs029_recv_buf[m_igs029_recv_len++] = (m_igs029_mgcs_long >> 16) & 0xff;
1548      m_igs029_recv_buf[m_igs029_recv_len++] = (m_igs029_mgcs_long >> 24) & 0xff;
1549      m_igs029_recv_buf[m_igs029_recv_len++] = 0x05;
1550   }
1551   else
1552   {
1553      logerror("UNKNOWN\n");
1554
1555      m_igs029_recv_len = 0;
1556      m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;
1557   }
1558
1559   m_igs029_send_len = 0;
1560}
1561
14291562WRITE16_MEMBER(igs017_state::mgcs_magic_w)
14301563{
14311564   COMBINE_DATA(&m_igs_magic[offset]);
r31725r31726
14381571      case 0x00:
14391572         if (ACCESSING_BITS_0_7)
14401573         {
1574            bool igs029_irq = !(m_input_select & 0x04) &&  (data & 0x04);   // 0->1
1575
1576            // 7654 3--- Keys
1577            // ---- -2-- IRQ on IGS029
1578            // ---- --1-
1579            // ---- ---0 Hopper Motor
14411580            m_input_select = data & 0xff;
1581
1582            m_hopperdev->write(space, 0, (data & 0x0001) ? 0x80 : 0x00);
1583
1584            if (igs029_irq)
1585            {
1586               if (!m_igs029_recv_len)
1587               {
1588                  // SEND
1589                  if (m_igs029_send_len < sizeof(m_igs029_send_buf))
1590                     m_igs029_send_buf[m_igs029_send_len++] = m_igs029_send_data;
1591
1592                  logerror("%s: igs029 send ", machine().describe_context());
1593                  for (int i = 0; i < m_igs029_send_len; i++)
1594                     logerror("%02x ", m_igs029_send_buf[i]);
1595                  logerror("\n");
1596
1597                  if (m_igs029_send_buf[0] == m_igs029_send_len)
1598                     mgcs_igs029_run();
1599               }
1600
1601               if (m_igs029_recv_len)
1602               {
1603                  // RECV
1604                  logerror("%s: igs029 recv ", machine().describe_context());
1605                  for (int i = 0; i < m_igs029_recv_len; i++)
1606                     logerror("%02x ", m_igs029_recv_buf[i]);
1607                  logerror("\n");
1608
1609                  if (m_igs029_recv_len)
1610                     --m_igs029_recv_len;
1611
1612                  m_igs029_recv_data = m_igs029_recv_buf[m_igs029_recv_len];
1613               }
1614            }
14421615         }
14431616
1444         if ( m_input_select & ~0xf8 )
1617         if ( m_input_select & ~0xfd )
14451618            logerror("%s: warning, unknown bits written in input_select = %02x\n", machine().describe_context(), m_input_select);
1619
14461620         break;
14471621
14481622      case 0x01:
14491623         if (ACCESSING_BITS_0_7)
14501624         {
14511625            m_scramble_data = data & 0xff;
1626//            logerror("%s: writing %02x to igs_magic = %02x\n", machine().describe_context(), data & 0xff, m_igs_magic[0]);
14521627         }
14531628         break;
14541629
14551630      // case 0x02: ?
1456      // case 0x03: ?
14571631
1632      case 0x03:
1633         if (ACCESSING_BITS_0_7)
1634         {
1635            m_igs029_send_data = data & 0xff;
1636//            logerror("%s: writing %02x to igs_magic = %02x\n", machine().describe_context(), data & 0xff, m_igs_magic[0]);
1637         }
1638         break;
1639
14581640      default:
14591641         logerror("%s: warning, writing to igs_magic %02x = %02x\n", machine().describe_context(), m_igs_magic[0], data);
14601642   }
r31725r31726
14621644
14631645READ16_MEMBER(igs017_state::mgcs_magic_r)
14641646{
1647   if (offset == 0)
1648      return m_igs_magic[0];
1649
14651650   switch(m_igs_magic[0])
14661651   {
1652      case 0x00:
1653         return m_input_select | 0x02;
1654
14671655      case 0x01:
1468         return BITSWAP8(m_scramble_data, 4,5,6,7, 0,1,2,3);
1656      {
1657         UINT16 ret = BITSWAP8( (BITSWAP8(m_scramble_data, 0,1,2,3,4,5,6,7) + 1) & 3, 4,5,6,7, 0,1,2,3);
1658         logerror("%s: reading %02x from igs_magic = %02x\n", machine().describe_context(), ret, m_igs_magic[0]);
1659         return ret;
1660      }
14691661
1662      case 0x02:
1663      {
1664         UINT8 ret = m_igs029_recv_data;
1665         logerror("%s: reading %02x from igs_magic = %02x\n", machine().describe_context(), ret, m_igs_magic[0]);
1666         return ret;
1667      }
1668
1669//      case 0x05: ???
1670
14701671      default:
14711672         logerror("%s: warning, reading with igs_magic = %02x\n", machine().describe_context(), m_igs_magic[0]);
14721673         break;
r31725r31726
15201721static ADDRESS_MAP_START( mgcs, AS_PROGRAM, 16, igs017_state )
15211722   AM_RANGE( 0x000000, 0x07ffff ) AM_ROM
15221723   AM_RANGE( 0x300000, 0x303fff ) AM_RAM
1523   AM_RANGE( 0x49c000, 0x49c003 ) AM_WRITE(mgcs_magic_w )
1524   AM_RANGE( 0x49c002, 0x49c003 ) AM_READ(mgcs_magic_r )
1724   AM_RANGE( 0x49c000, 0x49c003 ) AM_WRITE(mgcs_magic_w ) AM_READ(mgcs_magic_r )
15251725   AM_RANGE( 0xa02000, 0xa02fff ) AM_READWRITE(spriteram_lsb_r, spriteram_lsb_w ) AM_SHARE("spriteram")
15261726   AM_RANGE( 0xa03000, 0xa037ff ) AM_RAM_WRITE(mgcs_paletteram_w ) AM_SHARE("paletteram")
15271727   AM_RANGE( 0xa04020, 0xa04027 ) AM_DEVREAD8("ppi8255", i8255_device, read, 0x00ff)
15281728   AM_RANGE( 0xa04024, 0xa04025 ) AM_WRITE(video_disable_lsb_w )
1529   AM_RANGE( 0xa04028, 0xa04029 ) AM_WRITE(irq2_enable_w )
1530   AM_RANGE( 0xa0402a, 0xa0402b ) AM_WRITE(irq1_enable_w )
1729   AM_RANGE( 0xa04028, 0xa04029 ) AM_RAM_WRITE(irq2_enable_w )
1730   AM_RANGE( 0xa0402a, 0xa0402b ) AM_RAM_WRITE(irq1_enable_w )
15311731   AM_RANGE( 0xa08000, 0xa0bfff ) AM_READWRITE(fg_lsb_r, fg_lsb_w ) AM_SHARE("fg_videoram")
15321732   AM_RANGE( 0xa0c000, 0xa0ffff ) AM_READWRITE(bg_lsb_r, bg_lsb_w ) AM_SHARE("bg_videoram")
15331733   AM_RANGE( 0xa12000, 0xa12001 ) AM_DEVREADWRITE8("oki", okim6295_device, read, write, 0x00ff )
r31725r31726
27472947
27482948static INPUT_PORTS_START( mgcs )
27492949
2750   // DSWs don't work: they are read through a protection device (IGS029? see code at 1CF16)
2950   // DSWs are read through a protection device (IGS029). See code at 1CF16
27512951
2752   PORT_START("DSW1")
2952   PORT_START("DSW1")   // $3009e2
27532953   PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) )
27542954   PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ) )
27552955   PORT_DIPSETTING(    0x02, DEF_STR( 1C_2C ) )
27562956   PORT_DIPSETTING(    0x01, DEF_STR( 1C_3C ) )
2757   PORT_DIPSETTING(    0x00, DEF_STR( 1C_4C ) )
2957   PORT_DIPSETTING(    0x00, DEF_STR( 1C_5C ) )
27582958   PORT_DIPNAME( 0x0c, 0x0c, "Credits Per Note" )
27592959   PORT_DIPSETTING(    0x0c, "10" )
27602960   PORT_DIPSETTING(    0x08, "20" )
r31725r31726
27732973   PORT_DIPSETTING(    0x80, "1000" )
27742974   PORT_DIPSETTING(    0x00, "2000" )
27752975
2776   PORT_START("DSW2")
2976   PORT_START("DSW2")   // $3009e3
27772977   PORT_DIPNAME( 0x03, 0x03, "Min Bet" )
27782978   PORT_DIPSETTING(    0x03, "1" )
27792979   PORT_DIPSETTING(    0x02, "2" )
r31725r31726
27822982   PORT_DIPNAME( 0x04, 0x04, "Double Up" )
27832983   PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
27842984   PORT_DIPSETTING(    0x04, DEF_STR( On ) )
2785   PORT_DIPNAME( 0x10, 0x10, "Double Up Type" )
2786   PORT_DIPSETTING(    0x10, "Double" )
2787   PORT_DIPSETTING(    0x00, DEF_STR( Single ) )
2788   PORT_DIPNAME( 0x20, 0x20, DEF_STR( Controls ) )
2789   PORT_DIPSETTING(    0x20, "Keyboard" )
2985   PORT_DIPNAME( 0x10, 0x10, DEF_STR( Controls ) )
2986   PORT_DIPSETTING(    0x10, "Keyboard" )
27902987   PORT_DIPSETTING(    0x00, DEF_STR( Joystick ) )
2791   PORT_DIPNAME( 0x40, 0x40, "Number Type" )
2792   PORT_DIPSETTING(    0x40, "Number" )
2988   PORT_DIPNAME( 0x20, 0x20, "Number Type" )
2989   PORT_DIPSETTING(    0x20, "Number" )
27932990   PORT_DIPSETTING(    0x00, "Tile" )
2991   PORT_DIPNAME( 0x40, 0x40, "Double Up Type" )
2992   PORT_DIPSETTING(    0x40, "Double" )
2993   PORT_DIPSETTING(    0x00, DEF_STR( Single ) )
27942994   PORT_DIPNAME( 0x80, 0x80, "Bet Number" )
27952995   PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
27962996   PORT_DIPSETTING(    0x80, DEF_STR( On ) )
r31725r31726
27982998   // the top 2 bits of COINS (port A) and KEYx (port B) are read and combined with the bottom 4 bits read from port C (see code at 1C83A)
27992999
28003000   PORT_START("COINS")
2801   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE2 ) // hopper switch (unimplemented)
3001   PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL  ) PORT_READ_LINE_DEVICE_MEMBER("hopper", ticket_dispenser_device, line_r) // hopper switch
28023002   PORT_SERVICE_NO_TOGGLE( 0x02,   IP_ACTIVE_LOW ) // service mode (keep pressed during boot too)
28033003   PORT_BIT( 0x04, IP_ACTIVE_LOW,  IPT_SERVICE1 ) PORT_NAME("Statistics")  // press with the above for sound test
28043004   PORT_BIT( 0x08, IP_ACTIVE_LOW,  IPT_COIN1    ) PORT_IMPULSE(5)
r31725r31726
30063206   PORT_DIPNAME( 0x20, 0x20, "Pay Out Type" )
30073207   PORT_DIPSETTING(    0x20, "Coins" )
30083208   PORT_DIPSETTING(    0x00, "Notes" )
3009   PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Unknown ) )
3209   PORT_DIPNAME( 0xc0, 0xc0, "Min Bet" )
30103210   PORT_DIPSETTING(    0xc0, "1" )
30113211   PORT_DIPSETTING(    0x80, "2" )
30123212   PORT_DIPSETTING(    0x40, "3" )
r31725r31726
35413741   MCFG_I8255_IN_PORTA_CB(IOPORT("COINS"))
35423742   MCFG_I8255_IN_PORTB_CB(READ8(igs017_state, mgcs_keys_r))
35433743
3744   MCFG_TICKET_DISPENSER_ADD("hopper", attotime::from_msec(50), TICKET_MOTOR_ACTIVE_HIGH, TICKET_STATUS_ACTIVE_LOW )
3745
35443746   /* video hardware */
35453747   MCFG_SCREEN_ADD("screen", RASTER)
35463748   MCFG_SCREEN_REFRESH_RATE(60)

Previous 199869 Revisions Next


© 1997-2024 The MAME Team