From 11e2d67805dee981713fbf7c1c9b7908f15c3c48 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Sat, 16 Apr 2022 01:37:05 +0200 Subject: MT08203 fix (#9549) * imagetek_i4100.cpp: add external pin callbacks, disallow internal irq acks for 5 to 7 lines; metro.cpp: tie irq line 5 to a vblank source with external pin 0 as irq enable, fixes MT08203; * imagetek_i4100.cpp: extend external pin notes * metro.cpp: add note about vmetal layer alignments, fix blzntrnd/gstrik2 regressions, address code review; --- src/devices/video/imagetek_i4100.cpp | 42 +++++++++---- src/devices/video/imagetek_i4100.h | 8 ++- src/mame/drivers/metro.cpp | 118 ++++++++++++++++++++--------------- src/mame/includes/metro.h | 6 +- 4 files changed, 109 insertions(+), 65 deletions(-) diff --git a/src/devices/video/imagetek_i4100.cpp b/src/devices/video/imagetek_i4100.cpp index 92b7fbe5716..080d2159553 100644 --- a/src/devices/video/imagetek_i4100.cpp +++ b/src/devices/video/imagetek_i4100.cpp @@ -291,6 +291,9 @@ imagetek_i4100_device::imagetek_i4100_device(const machine_config &mconfig, devi , m_tilemap_flip_scrolldx{0, 0, 0} , m_tilemap_flip_scrolldy{0, 0, 0} , m_spriteram_buffered(false) + , m_ext_ctrl_0_cb(*this) + , m_ext_ctrl_1_cb(*this) + , m_ext_ctrl_2_cb(*this) { } @@ -385,6 +388,10 @@ void imagetek_i4100_device::device_start() m_spritelist = std::make_unique(0x1000 / 8); m_sprite_end = m_spritelist.get(); + + m_ext_ctrl_0_cb.resolve_safe(); + m_ext_ctrl_1_cb.resolve_safe(); + m_ext_ctrl_2_cb.resolve_safe(); } void imagetek_i4300_device::device_start() @@ -459,7 +466,11 @@ void imagetek_i4100_device::irq_cause_w(u8 data) return; LOGINT("%s: Interrupts acknowledged (%02X)\n", machine().describe_context(), data); - m_requested_int &= ~data; + // NB: at least i4100 device doesn't have control over bits 5-6-7 + // it's cleared on top of irq services in karatour & ladykill with a 0xffea + // bit 5 seems more like an external irq service that is acknowledged separately, + // and is necessary for those + 3kokushi for updating scroll registers. + m_requested_int &= ~(data & 0x1f); update_irq_state(); } @@ -670,32 +681,41 @@ void imagetek_i4100_device::window_w(offs_t offset, uint16_t data, uint16_t mem_ uint16_t imagetek_i4100_device::scroll_r(offs_t offset) { return m_scroll[offset]; } void imagetek_i4100_device::scroll_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_scroll[offset]); } -/**************************************************** +/* * * Screen Control Register: * - * f--- ---- ---- ---- ? + * f--- ---- ---- ---- ? karatour during POST (CRTC i/f sync?) * -edc b--- ---- ---- - * ---- -a98 ---- ---- ? Leds (see gakusai attract) + * ---- -a98 ---- ---- external control pins + * \- gakusai attract, unknown purpose + * (bit 2 enabled during title photo flashes, + * bit 1 always?, + * bit 0 periodically during gal sequences); + * \- (bit 0) karatour/ladykill/3kokushi external irq level 5 enable, (bit 1-2) unknown; + * \- puzzli [hblank] timer stop/start? 0 during transitions, 7 otherwise + * (including individual printouts of ROM statuses during POST); + * \- mouja (1 during POST, 7 otherwise) * ---- ---- 765- ---- 16x16 Tiles (Layer 2-1-0) * ---- ---- ---4 32-- * ---- ---- ---- --1- Blank Screen * ---- ---- ---- ---0 Flip Screen * - ****************************************************/ + */ void imagetek_i4100_device::screen_ctrl_w(offs_t offset, uint16_t data, uint16_t mem_mask) { - m_layer_tile_select[2] = BIT(data,7); - m_layer_tile_select[1] = BIT(data,6); - m_layer_tile_select[0] = BIT(data,5); + m_ext_ctrl_2_cb(BIT(data, 10)); + m_ext_ctrl_1_cb(BIT(data, 9)); + m_ext_ctrl_0_cb(BIT(data, 8)); + + for (int i = 0; i < 3; i++) + m_layer_tile_select[i] = BIT(data, 5 + i); - // TODO: some of these must be externalized m_screen_blank = BIT(data,1); m_screen_flip = BIT(data,0); if (data & 0xff1c) - logerror("%s warning: screen_ctrl_w write with %04x %04x\n",this->tag(),data,mem_mask); - + logerror("%s warning: screen_ctrl_w write with %04x %04x\n", this->tag(), data, mem_mask); } diff --git a/src/devices/video/imagetek_i4100.h b/src/devices/video/imagetek_i4100.h index 8b72600c328..f8c0f78c034 100644 --- a/src/devices/video/imagetek_i4100.h +++ b/src/devices/video/imagetek_i4100.h @@ -52,6 +52,9 @@ public: } auto irq_cb() { return m_irq_cb.bind(); } + auto ext_ctrl_0_cb() { return m_ext_ctrl_0_cb.bind(); } + auto ext_ctrl_1_cb() { return m_ext_ctrl_1_cb.bind(); } + auto ext_ctrl_2_cb() { return m_ext_ctrl_2_cb.bind(); } void set_vblank_irq_level(int level) { m_vblank_irq_level = level; } void set_blit_irq_level(int level) { m_blit_irq_level = level; } void set_spriteram_buffered(bool buffer) { m_spriteram_buffered = buffer; } @@ -191,7 +194,6 @@ protected: uint16_t scroll_r(offs_t offset); void scroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t gfxrom_r(offs_t offset); void crtc_vert_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); void crtc_horz_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); @@ -222,6 +224,10 @@ protected: bool m_inited_hack; DECLARE_GFXDECODE_MEMBER(gfxinfo); DECLARE_GFXDECODE_MEMBER(gfxinfo_ext); + + devcb_write_line m_ext_ctrl_0_cb; + devcb_write_line m_ext_ctrl_1_cb; + devcb_write_line m_ext_ctrl_2_cb; }; class imagetek_i4220_device : public imagetek_i4100_device diff --git a/src/mame/drivers/metro.cpp b/src/mame/drivers/metro.cpp index 8cdbbb48816..40559220e45 100644 --- a/src/mame/drivers/metro.cpp +++ b/src/mame/drivers/metro.cpp @@ -71,13 +71,16 @@ To Do: - For video related issues @see devices/video/imagetek_i4100.cpp - Most games in service mode, seem to require that you press start1&2 *exactly at once* in order to advance to the next screen (e.g. holding 1 then pressing 2 doesn't work). -- Coin lockout - Interrupt timing needs figuring out properly, having it incorrect causes scrolling glitches in some games. Test cases Mouse Go Go title screen, GunMaster title screen. Changing it can cause excessive slowdown in said games however. +- karatour, ladykill, 3kokushi: understand what the irq source 5 is really tied to. + All these games also have a vblank delay check outside irq routine, + cfr. PC=1322 in karatour; - vmetal: ES8712 actually controls a M6585 and an unknown logic selector chip. - split these games into different files, check PCB markings. +- Coin lockout; Notes: @@ -132,11 +135,6 @@ void metro_state::device_timer(emu_timer &timer, device_timer_id id, int param) { switch (id) { - case TIMER_KARATOUR_IRQ: - if (m_vdp) m_vdp->clear_irq(5); - if (m_vdp2) m_vdp2->clear_irq(5); - if (m_vdp3) m_vdp3->clear_irq(5); - break; case TIMER_MOUJA_IRQ: if (m_vdp) m_vdp->set_irq(0); if (m_vdp2) m_vdp2->set_irq(0); @@ -184,18 +182,32 @@ TIMER_DEVICE_CALLBACK_MEMBER(metro_state::bangball_scanline) /* lev 2-7 (lev 1 seems sound related) */ WRITE_LINE_MEMBER(metro_state::karatour_vblank_irq) { +// printf("%d %d %lld\n", state, m_screen->vpos(), m_screen->frame_number()); + if (state) { - /* write to scroll registers, the duration is a guess */ - m_karatour_irq_timer->adjust(attotime::from_usec(2500)); - if (m_vdp) m_vdp->set_irq(5); - if (m_vdp2) m_vdp2->set_irq(5); - if (m_vdp3) m_vdp3->set_irq(5); - if (m_vdp) m_vdp->screen_eof(state); if (m_vdp2) m_vdp2->screen_eof(state); if (m_vdp3) m_vdp3->screen_eof(state); + + if (m_ext_irq_enable) + { + if (m_vdp) m_vdp->set_irq(5); + if (m_vdp2) m_vdp2->set_irq(5); + if (m_vdp3) m_vdp3->set_irq(5); + } } + else + { + if (m_vdp) m_vdp->clear_irq(5); + if (m_vdp2) m_vdp2->clear_irq(5); + if (m_vdp3) m_vdp3->clear_irq(5); + } +} + +WRITE_LINE_MEMBER(metro_state::ext_irq5_enable_w) +{ + m_ext_irq_enable = state; } void metro_state::mouja_irq_timer_ctrl_w(uint16_t data) @@ -2139,30 +2151,30 @@ INPUT_PORTS_END static INPUT_PORTS_START( mouja ) PORT_START("IN0") //$478880 - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) - PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) - PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) - PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) - PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) - PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_START("IN1") //$478882 PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START2 ) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(2) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(2) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(2) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(2) PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_SERVICE_NO_TOGGLE(0x0080, IP_ACTIVE_LOW) @@ -2796,8 +2808,8 @@ void metro_state::i4100_config(machine_config &config) SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(58.2328); // VSync 58.2328Hz, HSync 15.32kHz - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); - m_screen->set_size(320, 240); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1500)); + m_screen->set_size(392, 263); m_screen->set_visarea(0, 320-1, 0, 240-1); m_screen->set_screen_update("vdp", FUNC(imagetek_i4100_device::screen_update)); } @@ -2810,8 +2822,8 @@ void metro_state::i4220_config(machine_config &config) SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(58.2328); // VSync 58.2328Hz, HSync 15.32kHz - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); - m_screen->set_size(320, 240); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1500)); + m_screen->set_size(392, 263); m_screen->set_visarea(0, 320-1, 0, 224-1); m_screen->set_screen_update("vdp2", FUNC(imagetek_i4100_device::screen_update)); } @@ -2824,8 +2836,8 @@ void metro_state::i4300_config(machine_config &config) SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(58.2328); // VSync 58.2328Hz, HSync 15.32kHz - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); - m_screen->set_size(320, 240); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1500)); + m_screen->set_size(392, 263); m_screen->set_visarea(0, 320-1, 0, 224-1); m_screen->set_screen_update("vdp3", FUNC(imagetek_i4100_device::screen_update)); } @@ -2835,7 +2847,7 @@ void metro_state::i4100_config_360x224(machine_config &config) { i4100_config(config); - m_screen->set_size(360, 224); +// m_screen->set_size(392, 263); m_screen->set_visarea(0, 360-1, 0, 224-1); } @@ -2843,7 +2855,7 @@ void metro_state::i4220_config_320x240(machine_config &config) { i4220_config(config); - m_screen->set_size(320, 240); +// m_screen->set_size(320, 240); m_screen->set_visarea(0, 320-1, 0, 240-1); } @@ -2851,7 +2863,6 @@ void metro_state::i4220_config_304x224(machine_config &config) { i4220_config(config); - m_screen->set_size(320, 240); m_screen->set_visarea(0, 304-1, 0, 224-1); } @@ -2860,7 +2871,7 @@ void metro_state::i4300_config_384x224(machine_config &config) i4300_config(config); m_vdp3->set_clock(32_MHz_XTAL); - m_screen->set_size(384, 240); +// m_screen->set_size(384, 240); m_screen->set_visarea(0, 384-1, 0, 224-1); } @@ -2868,7 +2879,7 @@ void metro_state::i4300_config_320x240(machine_config &config) { i4300_config(config); - m_screen->set_size(384, 240); +// m_screen->set_size(384, 240); m_screen->set_visarea(0, 320-1, 0, 240-1); } @@ -3042,7 +3053,7 @@ void metro_state::karatour(machine_config &config) /* video hardware */ i4100_config(config); m_vdp->irq_cb().set_inputline(m_maincpu, M68K_IRQ_2); - + m_vdp->ext_ctrl_0_cb().set(FUNC(metro_state::ext_irq5_enable_w)); m_screen->screen_vblank().set(FUNC(metro_state::karatour_vblank_irq)); /* sound hardware */ @@ -3067,6 +3078,7 @@ void metro_state::sankokushi(machine_config &config) /* video hardware */ i4220_config_320x240(config); m_vdp2->irq_cb().set_inputline(m_maincpu, M68K_IRQ_2); + m_vdp2->ext_ctrl_0_cb().set(FUNC(metro_state::ext_irq5_enable_w)); m_screen->screen_vblank().set(FUNC(metro_state::karatour_vblank_irq)); @@ -3117,7 +3129,7 @@ void metro_state::lastforg(machine_config &config) i4100_config_360x224(config); m_vdp->irq_cb().set_inputline(m_maincpu, M68K_IRQ_2); - + m_vdp->ext_ctrl_0_cb().set(FUNC(metro_state::ext_irq5_enable_w)); m_screen->screen_vblank().set(FUNC(metro_state::karatour_vblank_irq)); /* sound hardware */ @@ -3385,8 +3397,12 @@ void metro_state::vmetal(machine_config &config) m_vdp2->set_tmap_xoffsets(0,0,0); m_vdp2->set_tmap_yoffsets(0,0,0); - m_vdp2->set_tmap_flip_xoffsets(16,16,16); - m_vdp2->set_tmap_flip_yoffsets(16,16,16); + // TODO: very fussy on screen geometry changes + // CRTC is set as 320x224, bottom 16 pixels are actually aligned properly when flip screen is on. + // Easiest alignment test is during story lore in attract, specifically at bomb explosion screen + // (latter being a sprite needs to be 1:1 aligned with underlying background layer) + m_vdp2->set_tmap_flip_xoffsets(88,88,88); + m_vdp2->set_tmap_flip_yoffsets(39,39,39); /* sound hardware */ SPEAKER(config, "mono").front_center(); @@ -3421,11 +3437,12 @@ void metro_state::blzntrnd(machine_config &config) m_vdp2->set_vblank_irq_level(0); m_vdp2->set_blit_irq_level(3); m_vdp2->set_spriteram_buffered(true); // sprites are 1 frame delayed + m_vdp2->ext_ctrl_0_cb().set(FUNC(metro_state::ext_irq5_enable_w)); SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(58.2328); // VSync 58.2328Hz, HSync 15.32kHz - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); - m_screen->set_size(320, 240); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1500)); + m_screen->set_size(392, 263); m_screen->set_visarea(0, 304-1, 0, 224-1); m_screen->set_screen_update(FUNC(metro_state::screen_update_psac_vdp2_mix)); m_screen->screen_vblank().set(FUNC(metro_state::karatour_vblank_irq)); @@ -5356,8 +5373,7 @@ void metro_state::init_metro() void metro_state::init_karatour() { - m_karatour_irq_timer = timer_alloc(TIMER_KARATOUR_IRQ); - + save_item(NAME(m_ext_irq_enable)); init_metro(); } @@ -5395,7 +5411,7 @@ void metro_state::init_dharmak() void metro_state::init_blzntrnd() { m_audiobank->configure_entries(0, 8, memregion("audiocpu")->base(), 0x4000); - m_karatour_irq_timer = timer_alloc(TIMER_KARATOUR_IRQ); + save_item(NAME(m_ext_irq_enable)); } void metro_state::init_vmetal() @@ -5413,7 +5429,7 @@ void metro_state::init_mouja() void metro_state::init_lastfortg() { init_metro(); - m_karatour_irq_timer = timer_alloc(TIMER_KARATOUR_IRQ); + save_item(NAME(m_ext_irq_enable)); } /*************************************************************************** diff --git a/src/mame/includes/metro.h b/src/mame/includes/metro.h index e0c0cb12c24..c7306cdb17a 100644 --- a/src/mame/includes/metro.h +++ b/src/mame/includes/metro.h @@ -97,7 +97,6 @@ public: private: enum { - TIMER_KARATOUR_IRQ, TIMER_MOUJA_IRQ }; @@ -210,7 +209,6 @@ private: /* irq_related */ emu_timer *m_mouja_irq_timer = nullptr; - emu_timer *m_karatour_irq_timer = nullptr; /* sound related */ u8 m_sound_data = 0; @@ -226,6 +224,10 @@ private: int m_gakusai_oki_bank_hi = 0; void gakusai_oki_bank_set(); + + DECLARE_WRITE_LINE_MEMBER(ext_irq5_enable_w); + + bool m_ext_irq_enable = false; }; #endif // MAME_INCLUDES_METRO_H -- cgit v1.2.3