diff options
Diffstat (limited to 'src/mame/drivers/spg2xx_wiwi.cpp')
-rw-r--r-- | src/mame/drivers/spg2xx_wiwi.cpp | 267 |
1 files changed, 236 insertions, 31 deletions
diff --git a/src/mame/drivers/spg2xx_wiwi.cpp b/src/mame/drivers/spg2xx_wiwi.cpp index ceeec61c580..7d3836ec0a2 100644 --- a/src/mame/drivers/spg2xx_wiwi.cpp +++ b/src/mame/drivers/spg2xx_wiwi.cpp @@ -28,38 +28,249 @@ class spg2xx_game_marc101_state : public spg2xx_game_state { public: spg2xx_game_marc101_state(const machine_config &mconfig, device_type type, const char *tag) : - spg2xx_game_state(mconfig, type, tag) + spg2xx_game_state(mconfig, type, tag), + m_prev_porta(0), + m_toggle(false) { } + void marc101(machine_config &config); + void init_m489(); protected: + void machine_start() override; + void machine_reset() override; + + virtual void device_timer(emu_timer& timer, device_timer_id id, int param, void* ptr) override; + + virtual uint16_t porta_r(); + virtual void porta_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override; + virtual void portb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override; + + uint16_t m_prev_porta; + bool m_toggle; + emu_timer *m_pulse_timer; private: - void portb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override; + }; -class spg2xx_game_marc250_state : public spg2xx_game_state +class spg2xx_game_marc250_state : public spg2xx_game_marc101_state { public: spg2xx_game_marc250_state(const machine_config &mconfig, device_type type, const char *tag) : - spg2xx_game_state(mconfig, type, tag) + spg2xx_game_marc101_state(mconfig, type, tag), + m_toggle2(false) { } void init_m527(); protected: - void machine_reset() override - { - spg2xx_game_state::machine_reset(); - switch_bank(31); - m_maincpu->reset(); - } + void machine_start() override; + void machine_reset() override; + + virtual void device_timer(emu_timer& timer, device_timer_id id, int param, void* ptr) override; + + virtual uint16_t porta_r() override; + virtual void porta_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override; + virtual void portb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override; private: - void portb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override; + bool m_toggle2; + emu_timer *m_pulse_timer2; }; +void spg2xx_game_marc101_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case 0: + m_toggle = !m_toggle; + //printf("toggle\n"); + break; + } +} + +void spg2xx_game_marc250_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case 0: + m_toggle = !m_toggle; + //printf("toggle\n"); + break; + + case 1: + m_toggle2 = !m_toggle2; + //printf("toggle\n"); + break; + } +} + + +void spg2xx_game_marc101_state::machine_start() +{ + spg2xx_game_state::machine_start(); + m_pulse_timer = timer_alloc(0); + m_pulse_timer->adjust(attotime::never); + +} + +void spg2xx_game_marc101_state::machine_reset() +{ + spg2xx_game_state::machine_reset(); + m_pulse_timer->adjust(attotime::never); + m_prev_porta = 0; + m_toggle = false; +} + +void spg2xx_game_marc250_state::machine_start() +{ + spg2xx_game_marc101_state::machine_start(); + m_pulse_timer2 = timer_alloc(1); + m_pulse_timer2->adjust(attotime::never); + + // hack, makes x-racer3 and some others more stable, TODO: find out what is really wrong + m_maincpu->set_clock_scale(2.0000f); + +} + +void spg2xx_game_marc250_state::machine_reset() +{ + spg2xx_game_marc101_state::machine_reset(); + switch_bank(31); + m_maincpu->reset(); + + m_pulse_timer2->adjust(attotime::never); + m_toggle2 = false; +} + + +void spg2xx_game_marc101_state::marc101(machine_config &config) +{ + spg2xx(config); + + m_maincpu->set_pal(true); + m_screen->set_refresh_hz(50); + + m_maincpu->porta_in().set(FUNC(spg2xx_game_marc101_state::porta_r)); + m_maincpu->porta_out().set(FUNC(spg2xx_game_marc101_state::porta_w)); +} + + +// are these Port A behaviors related to IO A Special mode on the SoC? +// the bits being tested do seem to be 'ExtClk2 / ExtClk1' + +uint16_t spg2xx_game_marc101_state::porta_r() +{ + uint16_t ret = m_io_p1->read() &~ 0x2000; + + ret |= m_toggle ? 0x2000 : 0x0000; + + return ret; +} + + +void spg2xx_game_marc101_state::porta_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + logerror("%s: porta_w %04x (%04x) %c %c %c %c | %c %c %c %c | %c %c %c %c | %c %c %c %c \n", machine().describe_context(), data, mem_mask, + (mem_mask & 0x8000) ? ((data & 0x8000) ? '1' : '0') : 'x', + (mem_mask & 0x4000) ? ((data & 0x4000) ? '1' : '0') : 'x', + (mem_mask & 0x2000) ? ((data & 0x2000) ? '1' : '0') : 'x', + (mem_mask & 0x1000) ? ((data & 0x1000) ? '1' : '0') : 'x', + (mem_mask & 0x0800) ? ((data & 0x0800) ? '1' : '0') : 'x', + (mem_mask & 0x0400) ? ((data & 0x0400) ? '1' : '0') : 'x', + (mem_mask & 0x0200) ? ((data & 0x0200) ? '1' : '0') : 'x', + (mem_mask & 0x0100) ? ((data & 0x0100) ? '1' : '0') : 'x', + (mem_mask & 0x0080) ? ((data & 0x0080) ? '1' : '0') : 'x', + (mem_mask & 0x0040) ? ((data & 0x0040) ? '1' : '0') : 'x', + (mem_mask & 0x0020) ? ((data & 0x0020) ? '1' : '0') : 'x', + (mem_mask & 0x0010) ? ((data & 0x0010) ? '1' : '0') : 'x', + (mem_mask & 0x0008) ? ((data & 0x0008) ? '1' : '0') : 'x', + (mem_mask & 0x0004) ? ((data & 0x0004) ? '1' : '0') : 'x', + (mem_mask & 0x0002) ? ((data & 0x0002) ? '1' : '0') : 'x', + (mem_mask & 0x0001) ? ((data & 0x0001) ? '1' : '0') : 'x'); + + // see function at 053E19 (marc101) + // it has several states + // 00 - wait a while + // 01 - set 0x0400 in port a high + // 02 - clear 0x0400 in port a + // 07 - measure number of times 0x2000 on port a changes, with min/max acceptable values and a timeout + // ff - failure (causes blank screen / shutdown + inf loop) + if ((data & 0x0400) != (m_prev_porta & 0x0400)) + { + if (!(data & 0x0400)) + { + //logerror("pulse / timer reset\n"); + m_pulse_timer->adjust(attotime::from_hz(32), 0, attotime::from_hz(32)); + } + } + + m_prev_porta = data; +} + +uint16_t spg2xx_game_marc250_state::porta_r() +{ + uint16_t ret = m_io_p1->read() &~ 0x6000; + ret |= m_toggle ? 0x2000 : 0x0000; + ret |= m_toggle2 ? 0x4000 : 0x0000; +// printf("porta %04x\n", ret); + + return ret; +} + + +void spg2xx_game_marc250_state::porta_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + logerror("%s: porta_w %04x (%04x) %c %c %c %c | %c %c %c %c | %c %c %c %c | %c %c %c %c \n", machine().describe_context(), data, mem_mask, + (mem_mask & 0x8000) ? ((data & 0x8000) ? '1' : '0') : 'x', + (mem_mask & 0x4000) ? ((data & 0x4000) ? '1' : '0') : 'x', + (mem_mask & 0x2000) ? ((data & 0x2000) ? '1' : '0') : 'x', + (mem_mask & 0x1000) ? ((data & 0x1000) ? '1' : '0') : 'x', + (mem_mask & 0x0800) ? ((data & 0x0800) ? '1' : '0') : 'x', + (mem_mask & 0x0400) ? ((data & 0x0400) ? '1' : '0') : 'x', + (mem_mask & 0x0200) ? ((data & 0x0200) ? '1' : '0') : 'x', + (mem_mask & 0x0100) ? ((data & 0x0100) ? '1' : '0') : 'x', + (mem_mask & 0x0080) ? ((data & 0x0080) ? '1' : '0') : 'x', + (mem_mask & 0x0040) ? ((data & 0x0040) ? '1' : '0') : 'x', + (mem_mask & 0x0020) ? ((data & 0x0020) ? '1' : '0') : 'x', + (mem_mask & 0x0010) ? ((data & 0x0010) ? '1' : '0') : 'x', + (mem_mask & 0x0008) ? ((data & 0x0008) ? '1' : '0') : 'x', + (mem_mask & 0x0004) ? ((data & 0x0004) ? '1' : '0') : 'x', + (mem_mask & 0x0002) ? ((data & 0x0002) ? '1' : '0') : 'x', + (mem_mask & 0x0001) ? ((data & 0x0001) ? '1' : '0') : 'x'); + + // see function at 8AB2 (marc250 menu) + // it has several states + // 00 - wait a while + // 01 - clear 0x1000 in port a + // 02 - wait a while + // 05 - check rate of port a bit 0x4000 + + // 06 - wait a while + // 07 - clear 0x1000 in port a + // 08 - wait a while + // 09 - check rate of port a bit 0x2000 + + // ff - failure (causes blank screen / shutdown + inf loop) + + // function is at 04D918 in x-racer 3 (values tweaked to pass) + // but x-racer 3 also seems to need faster CPU or it randomly corrupts (or its an IRQ problem?) + + if ((data & 0x1000) != (m_prev_porta & 0x1000)) + { + if (!(data & 0x1000)) + { + // these values stop the marc250 menu from failing, but not the games + //printf("pulse / timer reset\n"); + m_pulse_timer->adjust(attotime::from_hz(6), 0, attotime::from_hz(6)); + m_pulse_timer2->adjust(attotime::from_hz(12), 0, attotime::from_hz(12)); + } + } + + m_prev_porta = data; +} static INPUT_PORTS_START( wiwi18 ) @@ -302,7 +513,7 @@ void spg2xx_game_wiwi18_state::init_wiwi18() } - void spg2xx_game_wiwi18_state::portb_w(offs_t offset, uint16_t data, uint16_t mem_mask) +void spg2xx_game_wiwi18_state::portb_w(offs_t offset, uint16_t data, uint16_t mem_mask) { logerror("%s: portb_w %04x (%04x) %c %c %c %c | %c %c %c %c | %c %c %c %c | %c %c %c %c \n", machine().describe_context(), data, mem_mask, (mem_mask & 0x8000) ? ((data & 0x8000) ? '1' : '0') : 'x', @@ -329,15 +540,10 @@ void spg2xx_game_wiwi18_state::init_wiwi18() else switch_bank(0); } - } void spg2xx_game_marc101_state::init_m489() { - uint16_t* rom = (uint16_t*)memregion("maincpu")->base(); - - // bypass a call that turns unit off after about 2 seconds, maybe it's a battery check? - if (rom[0x6460]==0x4240) rom[0x6460] = 0x4241; } void spg2xx_game_marc101_state::portb_w(offs_t offset, uint16_t data, uint16_t mem_mask) @@ -383,13 +589,11 @@ void spg2xx_game_marc101_state::portb_w(offs_t offset, uint16_t data, uint16_t m void spg2xx_game_marc250_state::init_m527() { - uint16_t* rom = (uint16_t*)memregion("maincpu")->base(); - // bypass a call that turns unit off after about 10 seconds, maybe it's a battery check? - rom[((31 * 0x800000) / 2) | 0x004ea5] = 0x4241; - - // same for xracing 3 - rom[((22 * 0x800000) / 2) | 0x00eb2a] = 0x4241; + // the code being patched turns the IRQ off, code looks a bit like smarttv code.. is SoC IRQ handling wrong? + // or is this more security, or something else? games don't run with the IRQ off... +#if 1 + uint16_t* rom = (uint16_t*)memregion("maincpu")->base(); uint16_t ident2[6] = { 0x9512, 0x2862, 0xa70a, 0x0002, 0xd71b, 0x2862 }; @@ -412,7 +616,6 @@ void spg2xx_game_marc250_state::init_m527() } } - // this turns the IRQ off, code looks a bit like smarttv code.. is SoC IRQ handling wrong? // pass maze road //rom[((12 * 0x800000) / 2) | 0x0284b5] = 0x0003; @@ -422,7 +625,7 @@ void spg2xx_game_marc250_state::init_m527() //rom[((17 * 0x800000) / 2) | 0x015e58] = 0x0003; // cliff overhang / gym dancing //rom[((18 * 0x800000) / 2) | 0x01cab4] = 0x0003; - rom[((18 * 0x800000) / 2) | 0x021e25] = 0xffff; + rom[((18 * 0x800000) / 2) | 0x021e25] = 0xffff; // secondary 'turn off' // jump chess //rom[((19 * 0x800000) / 2) | 0x012c3a] = 0x0003; // boxing, basketball etc. @@ -435,13 +638,14 @@ void spg2xx_game_marc250_state::init_m527() //rom[((26 * 0x800000) / 2) | 0x0084dd] = 0x0003; // 4 score //rom[((27 * 0x800000) / 2) | 0x145cdd] = 0x0003; +#endif } void spg2xx_game_marc250_state::portb_w(offs_t offset, uint16_t data, uint16_t mem_mask) { - if (m_maincpu->pc() == 0x18) + if (m_maincpu->pc() < 0x2000) { - printf("%s: portb_w %04x (%04x) %c %c %c %c | %c %c %c %c | %c %c %c %c | %c %c %c %c \n", machine().describe_context().c_str(), data, mem_mask, + logerror("%s: portb_w %04x (%04x) %c %c %c %c | %c %c %c %c | %c %c %c %c | %c %c %c %c \n", machine().describe_context(), data, mem_mask, (mem_mask & 0x8000) ? ((data & 0x8000) ? '1' : '0') : 'x', (mem_mask & 0x4000) ? ((data & 0x4000) ? '1' : '0') : 'x', (mem_mask & 0x2000) ? ((data & 0x2000) ? '1' : '0') : 'x', @@ -496,9 +700,10 @@ void spg2xx_game_marc250_state::portb_w(offs_t offset, uint16_t data, uint16_t m // bank 30 = (used) 'ROM 2 64M' // bank 31 = (used) menu (no bank number check) - if ((m_maincpu->pc() == 0x18) && (data != 0x00ff)) + // bits 0x1804 aren't set as an output, but clearly need to be treated as output, also bad values of 0x00ff and 0x0000 are written on startup, with direction bits set! + // this seems similar to issues with banking in some other units. + if ((m_maincpu->pc() < 0x2000) && (data != 0x00ff) && (data != 0x0000)) { - // bits 0x1804 aren't set as an output, but clearly need to be treated as output switch (data & 0x1807) { case 0x0000: switch_bank(0); break; // unused @@ -583,6 +788,6 @@ CONS( 200?, foxsport, 0, 0, rad_skat, wiwi18, spg2xx_game_wiwi18_state, // thtere is another 'Drahtlose Spielekonsole 48-in-1' with '11 hyper sports games' (including Running) which are clearly SunPlus and would fit here, with the 37 non-hyper sports games presumably again being a NES/Famiclone cart -CONS( 200?, marc101, 0, 0, spg2xx, m489, spg2xx_game_marc101_state, init_m489, "Millennium 2000 GmbH", "Millennium Arcade 101 (M489) (Game Station 2 101-in-1)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2014, marc101, 0, 0, marc101, m489, spg2xx_game_marc101_state, init_m489, "Millennium 2000 GmbH", "Millennium Arcade 101 (M489) (Game Station 2 101-in-1)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) -CONS( 200?, marc250, 0, 0, spg2xx, m489, spg2xx_game_marc250_state, init_m527, "Millennium 2000 GmbH", "Millennium Arcade 250 (M527)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2015, marc250, 0, 0, marc101, m489, spg2xx_game_marc250_state, init_m527, "Millennium 2000 GmbH", "Millennium Arcade 250 (M527)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) |