From d86d9b92205944e02a2894da621b2751a291e5ea Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 16 Sep 2024 01:45:33 +1000 Subject: igs/xamcu.cpp, igs/igs_m027xa.cpp: Adjusted XA MCU communication and interrupts. Systems promoted to working --------------------------- Chaoji Dou Dizhu [XingXing, Vas Crabb] Crazy Bugs (V204US) [XingXing, Vas Crabb] Fruit Paradise (V214) [XingXing, Vas Crabb, David Haywood] Jungle King 2002 (V209US) [XingXing, Vas Crabb] Long Hu Da Manguan [XingXing, Vas Crabb, David Haywood] Long Hu Zhengba 4 [XingXing, Vas Crabb, Ioannis Bampoulas, TeamEurope] Long Hu Zhengba III [XingXing, Vas Crabb, David Haywood] Long Teng Hu Yue [XingXing, Vas Crabb, David Haywood] Manguan Zhizun (V101CN) [XingXing, Vas Crabb, David Haywood] Manguan Caishen 3 (V101CN) [XingXing, Vas Crabb] Ocean Paradise (V105US) [XingXing, Vas Crabb, Ioannis Bampoulas, TeamEurope] Que Long Gaoshou [XingXing, Vas Crabb] Shuang Long Qiang Zhu 3 (China, VS107C) [XingXing, Vas Crabb, David Haywood] Zhongguo Chu Da D [XingXing, Vas Crabb, David Haywood] Clones promoted to working -------------------------- Crazy Bugs (V202US) [XingXing, Vas Crabb] Crazy Bugs (V200US) [XingXing, Vas Crabb] Fruit Paradise (V206US) [XingXing, Vas Crabb, David Haywood] Long Hu Da Manguan Plus [XingXing, Vas Crabb, David Haywood] Manguan Zhizun (V100CN) [XingXing, Vas Crabb, David Haywood] Ocean Paradise (V101US) [XingXing, Vas Crabb, Ioannis Bampoulas, TeamEurope] --- src/mame/igs/igs_m027.cpp | 55 ++++++++++++++++++++++++----------------- src/mame/igs/igs_m027xa.cpp | 26 +++++++++++++------- src/mame/igs/xamcu.cpp | 60 +++++++++++++++++++++------------------------ src/mame/igs/xamcu.h | 2 ++ 4 files changed, 79 insertions(+), 64 deletions(-) diff --git a/src/mame/igs/igs_m027.cpp b/src/mame/igs/igs_m027.cpp index d8e64d810e0..5acf8f78ead 100644 --- a/src/mame/igs/igs_m027.cpp +++ b/src/mame/igs/igs_m027.cpp @@ -1687,7 +1687,7 @@ void igs_m027_state::chessc2_xor(machine_config &config) /*************************************************************************** -Mahjong Shuang Long Qiang Zhu 3 +双龙抢珠Ⅲ (Shuāng Lóng Qiǎng Zhū III) IGS, 1999 PCB Layout @@ -2053,6 +2053,7 @@ ROM_END // samples at u14 +// 龙虎争霸Ⅲ (Lóng Hǔ Zhēngbà III) ROM_START( lhzb3 ) ROM_REGION( 0x04000, "maincpu", 0 ) // Internal ROM of IGS027A ARM based MCU @@ -2074,8 +2075,8 @@ ROM_END /********************************************************************************* -Long Hu Da Man Guan, IGS 1999 -Long Hu Da Man Guan Plus, IGS 1999 +龙虎大满贯 (Lóng Hǔ Dà Mǎnguàn), IGS 1999 +龙虎大满贯 (Lóng Hǔ Dà Mǎnguàn Plus), IGS 1999 Both boards are identical and use the same mask ROMs, only with changed program EPROM. @@ -2155,7 +2156,7 @@ ROM_END /* -Zhong Guo Chu Da D +中国锄大D (Zhōngguó chú dà D) IGS, 2000 PCB Layout @@ -2219,6 +2220,7 @@ ROM_END +// 满贯至尊 (Mǎnguàn Zhìzūn) ROM_START( mgzz ) ROM_REGION( 0x04000, "maincpu", 0 ) // Internal ROM of IGS027A ARM based MCU @@ -2238,6 +2240,7 @@ ROM_START( mgzz ) ROM_END +// 满贯至尊 (Mǎnguàn Zhìzūn) ROM_START( mgzza ) // IGS PCB 0295-00 (IGS027A, M6295, IGS031, 8255, Battery) ROM_REGION( 0x04000, "maincpu", 0 ) // Internal ROM of IGS027A type G ARM based MCU @@ -2256,9 +2259,10 @@ ROM_START( mgzza ) // IGS PCB 0295-00 (IGS027A, M6295, IGS031, 8255, Battery) ROM_LOAD( "sp.u14", 0x00000, 0x80000, CRC(f037952e) SHA1(0fa83e164937c9e8245861da7fd11f225525918d) ) ROM_END + /********************************************************************************* -Long Teng Hu Yue, IGS 1999 +龙腾虎跃 (Lóng Téng Hǔ Yuè), IGS 1999 PCB Layout ---------- @@ -2479,6 +2483,7 @@ ROM_END // cg at u28 // samples at u4 (or u5?) +// 超级斗地主 (Chāojí Dòu Dìzhǔ) ROM_START( cjddz ) ROM_REGION( 0x04000, "maincpu", 0 ) // Internal ROM of IGS027A ARM based MCU @@ -2499,6 +2504,7 @@ ROM_START( cjddz ) ROM_LOAD( "ddz_sp.u4", 0x00000, 0x200000, CRC(7ef65d95) SHA1(345c587cd449d6d06908e9687480be76b2cb2d28) ) ROM_END +// 龙虎争霸4 (Lóng Hǔ Zhēngbà 4) ROM_START( lhzb4 ) ROM_REGION( 0x04000, "maincpu", 0 ) // Internal ROM of IGS027A ARM based MCU @@ -2518,7 +2524,8 @@ ROM_START( lhzb4 ) ROM_LOAD( "w05502.u5", 0x00000, 0x200000, CRC(467f677e) SHA1(63927c0d606176c0e22db89ea3a9777ed702abbd) ) ROM_END -// Que Long Gao Shou (Master on Mahjong Dragon) (IGS, 1999) - PCB-0489-17-FM-1 (IGS027A, M6295, IGS031, 8255, Battery) +// 雀龙高手 (Què Lóng Gāoshǒu) (IGS, 1999) +// PCB-0489-17-FM-1 (IGS027A, M6295, IGS031, 8255, Battery) ROM_START( qlgs ) ROM_REGION( 0x04000, "maincpu", 0 ) // Internal ROM of IGS027A type G ARM based MCU @@ -2537,6 +2544,8 @@ ROM_START( qlgs ) ROM_LOAD( "sp_u5.u5", 0x00000, 0x200000, CRC(6049b892) SHA1(f87285a288bd3fd169080045f70ff15181661582) ) // 11xxxxxxxxxxxxxxxxxxx = 0x00 ROM_END + +// 满贯财神3 (Mǎnguàn Cáishén 3) // PCB-0489-15-FM-1 (IGS027A, M6295, IGS031, 8255, Battery) - same PCB as qlgs ROM_START( mgcs3 ) ROM_REGION( 0x04000, "maincpu", 0 ) @@ -2760,23 +2769,23 @@ 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 | 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 | 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 | 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 -GAMEL( 1999, oceanpar, 0, oceanpar_xor, oceanpar, igs_m027_state, init_oceanpar, ROT0, "IGS", "Ocean Paradise (V105US)", MACHINE_NOT_WORKING, layout_oceanpar ) // 1999 copyright in ROM -GAMEL( 1999, oceanpara, oceanpar, oceanpar_xor, oceanpara,igs_m027_state, init_oceanpar, ROT0, "IGS", "Ocean Paradise (V101US)", MACHINE_NOT_WORKING, layout_oceanpar ) // 1999 copyright in ROM -GAMEL( 1999, fruitpar, 0, oceanpar_xor, oceanpar, igs_m027_state, init_fruitpar, ROT0, "IGS", "Fruit Paradise (V214)", MACHINE_NOT_WORKING, layout_oceanpar ) -GAMEL( 1999, fruitpara, fruitpar, oceanpar_xor, fruitpara,igs_m027_state, init_fruitpar, ROT0, "IGS", "Fruit Paradise (V206US)", MACHINE_NOT_WORKING, layout_oceanpar ) -GAME( 200?, cjddz, 0, cjddz_xor, cjddz, igs_m027_state, init_cjddz, ROT0, "IGS", "Chaoji Dou Dizhu", MACHINE_NOT_WORKING ) // 超级斗地主 +GAME( 1999, slqz3, 0, slqz3_xor, slqz3, igs_m027_state, init_slqz3, ROT0, "IGS", "Shuang Long Qiang Zhu 3 (China, VS107C)", 0 ) +GAME( 1999, qlgs, 0, qlgs_xor, qlgs, igs_m027_state, init_qlgs, ROT0, "IGS", "Que Long Gaoshou", MACHINE_NODEVICE_LAN ) +GAME( 1999, lhdmg, 0, lhdmg_xor, lhdmg, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Da Manguan", 0 ) +GAME( 1999, lhdmgp, lhdmg, lhdmg_xor, lhdmg, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Da Manguan Plus", 0 ) +GAME( 1999, lhzb3, 0, lhdmg_xor, lhzb3, igs_m027_state, init_lhdmg, ROT0, "IGS", "Long Hu Zhengba III", 0 ) +GAME( 2004, lhzb4, 0, lhzb4_xor, lhzb4, igs_m027_state, init_lhzb4, ROT0, "IGS", "Long Hu Zhengba 4", 0 ) +GAME( 1999, lthy, 0, lthy_xor, lthy, igs_m027_state, init_lthy, ROT0, "IGS", "Long Teng Hu Yue", MACHINE_NODEVICE_LAN ) +GAME( 2000, zhongguo, 0, zhongguo_xor, zhongguo, igs_m027_state, init_zhongguo, ROT0, "IGS", "Zhongguo Chu Da D", 0 ) +GAMEL( 200?, jking02, 0, jking02_xor, jking02, igs_m027_state, init_jking02, ROT0, "IGS", "Jungle King 2002 (V209US)", MACHINE_NODEVICE_LAN, layout_jking02 ) +GAME( 2003, mgzz, 0, mgzz_xor, mgzz, igs_m027_state, init_mgzz, ROT0, "IGS", "Manguan Zhizun (V101CN)", 0 ) +GAME( 2003, mgzza, mgzz, mgzz_xor, mgzza, igs_m027_state, init_mgzz, ROT0, "IGS", "Manguan Zhizun (V100CN)", 0 ) +GAME( 2007, mgcs3, 0, lhzb4_xor, mgcs3, igs_m027_state, init_mgcs3, ROT0, "IGS", "Manguan Caishen 3 (V101CN)", 0 ) +GAMEL( 1999, oceanpar, 0, oceanpar_xor, oceanpar, igs_m027_state, init_oceanpar, ROT0, "IGS", "Ocean Paradise (V105US)", 0, layout_oceanpar ) // 1999 copyright in ROM +GAMEL( 1999, oceanpara, oceanpar, oceanpar_xor, oceanpara,igs_m027_state, init_oceanpar, ROT0, "IGS", "Ocean Paradise (V101US)", 0, layout_oceanpar ) // 1999 copyright in ROM +GAMEL( 1999, fruitpar, 0, oceanpar_xor, oceanpar, igs_m027_state, init_fruitpar, ROT0, "IGS", "Fruit Paradise (V214)", 0, layout_oceanpar ) +GAMEL( 1999, fruitpara, fruitpar, oceanpar_xor, fruitpara,igs_m027_state, init_fruitpar, ROT0, "IGS", "Fruit Paradise (V206US)", 0, layout_oceanpar ) +GAME( 200?, cjddz, 0, cjddz_xor, cjddz, igs_m027_state, init_cjddz, ROT0, "IGS", "Chaoji Dou Dizhu", 0 ) 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 | MACHINE_UNEMULATED_PROTECTION ) diff --git a/src/mame/igs/igs_m027xa.cpp b/src/mame/igs/igs_m027xa.cpp index b53c31ccbd4..5a66a82ea36 100644 --- a/src/mame/igs/igs_m027xa.cpp +++ b/src/mame/igs/igs_m027xa.cpp @@ -302,7 +302,7 @@ void igs_m027xa_state::igs_40000014_w(offs_t offset, u32 data, u32 mem_mask) u32 igs_m027xa_state::gpio_r() { u32 ret = m_io_test[2].read_safe(0xfffff); - if (m_irq_from_igs031) + if (m_irq_from_igs031 && m_igs017_igs031->get_irq_enable()) ret &= ~(u32(1) << 8); return ret; } @@ -356,13 +356,21 @@ TIMER_DEVICE_CALLBACK_MEMBER(igs_m027xa_state::interrupt) // should be using m_maincpu->trigger_irq with more compelx interrupt logic? - if (scanline == 240 && m_igs017_igs031->get_irq_enable()) + switch (scanline) { - m_irq_from_igs031 = true; // FIXME: this should be cleared at some point - m_maincpu->trigger_irq(3); + case 0: + if (m_igs_40000014 & 1) + m_maincpu->pulse_input_line(ARM7_FIRQ_LINE, m_maincpu->minimum_quantum_time()); // vbl? + m_irq_from_igs031 = false; + break; + case 240: + if (m_igs017_igs031->get_irq_enable()) + { + m_irq_from_igs031 = true; + m_maincpu->trigger_irq(3); + } + break; } - if (scanline == 0 && (m_igs_40000014 & 1)) - m_maincpu->pulse_input_line(ARM7_FIRQ_LINE, m_maincpu->minimum_quantum_time()); // vbl? } @@ -692,9 +700,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_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 +GAMEL( 2009, crzybugs, 0, igs_mahjong_xa_xor, base, igs_m027xa_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V204US)", 0, 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)", 0, 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)", 0, 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 diff --git a/src/mame/igs/xamcu.cpp b/src/mame/igs/xamcu.cpp index c7dd19a8d49..110348684d4 100644 --- a/src/mame/igs/xamcu.cpp +++ b/src/mame/igs/xamcu.cpp @@ -10,17 +10,6 @@ #include "logmacro.h" -namespace { - -template -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") @@ -50,19 +39,7 @@ 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()); + machine().scheduler().synchronize(timer_expired_delegate(FUNC(igs_xa_mcu_device_base::do_cmd_w), this), s32(u32(data))); } @@ -156,6 +133,24 @@ void igs_xa_mcu_device_base::mcu_p3_w(u8 data) } +TIMER_CALLBACK_MEMBER(igs_xa_mcu_device_base::do_cmd_w) +{ + m_command = u16(u32(param)); + + m_num_params--; + if (m_num_params <= 0) + { + LOG("command is %02x size %02x\n", m_command >> 8, m_command & 0x00ff); + m_num_params = m_command & 0x00ff; + } + else + { + LOG("param %04x\n", m_command); + } + m_mcu->pulse_input_line(XA_EXT_IRQ0, m_mcu->minimum_quantum_time()); +} + + igs_xa_mcu_ics_sound_device::igs_xa_mcu_ics_sound_device( machine_config const &mconfig, @@ -204,11 +199,11 @@ void igs_xa_mcu_ics_sound_device::mcu_p1_w(u8 data) void igs_xa_mcu_ics_sound_device::mcu_p3_w(u8 data) { - u8 const oldport3 = m_port_dat[3]; + u8 const falling = m_port_dat[3] & ~data; 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(falling, 7)) { if (!BIT(data, 4)) { @@ -223,7 +218,7 @@ void igs_xa_mcu_ics_sound_device::mcu_p3_w(u8 data) } } - if (negedge(oldport3, data, 6)) + if (BIT(falling, 6)) { if (!BIT(data, 4)) { @@ -267,7 +262,6 @@ 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); } @@ -289,20 +283,22 @@ void igs_xa_mcu_subcpu_device::device_start() void igs_xa_mcu_subcpu_device::mcu_p3_w(u8 data) { - u8 const oldport3 = m_port_dat[3]; + u8 const rising = ~m_port_dat[3] & data; + u8 const falling = m_port_dat[3] & ~data; igs_xa_mcu_device_base::mcu_p3_w(data); - set_irq(BIT(data, 5)); + if (BIT(rising, 5)) + set_irq(1); // high->low transition on bit 0x80 must read into latches! - if (negedge(oldport3, data, 7)) + if (BIT(falling, 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)) + if (BIT(falling, 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); diff --git a/src/mame/igs/xamcu.h b/src/mame/igs/xamcu.h index aa308cdd001..c049e093332 100644 --- a/src/mame/igs/xamcu.h +++ b/src/mame/igs/xamcu.h @@ -38,6 +38,8 @@ protected: void mcu_p2_w(u8 data); void mcu_p3_w(u8 data); + TIMER_CALLBACK_MEMBER(do_cmd_w); + required_device m_mcu; devcb_write_line m_irq_cb; -- cgit v1.2.3