summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2025-11-25 22:26:52 +0100
committer hap <happppp@users.noreply.github.com>2025-11-25 22:27:04 +0100
commit3af9439e613b46eb31af7a3aa0696f927c0dec7f (patch)
tree7d9807765b1a48b14132f529e672bca04d8452fe
parent7395079fcfd73322b3a661e6230c0851b6497f38 (diff)
ghostb: delay nmi flipflop by 1 cycle (fixes stage 2 bug)
-rw-r--r--src/mame/dataeast/dec8.cpp26
-rw-r--r--src/mame/dataeast/dec8.h3
2 files changed, 28 insertions, 1 deletions
diff --git a/src/mame/dataeast/dec8.cpp b/src/mame/dataeast/dec8.cpp
index d9460c8c863..99d75e01383 100644
--- a/src/mame/dataeast/dec8.cpp
+++ b/src/mame/dataeast/dec8.cpp
@@ -43,6 +43,24 @@ TODO:
- gondo 2nd coin doesn't work, probably due to hacked MCU ROM
- ghostb coinage dipswitch
- how does meikyuhbl circumvent the MCU? It won't boot in MAME if MCU is removed
+- weird NMI issue in ghostb: Before starting stage 2, it waits for vblank, then
+ enables NMI by writing to ghostb_bank_w, then stores the written value in RAM.
+ It fails to initialize stage 2 properly if NMI happens right after enabling
+ the NMI flip-flop (when it hasn't yet stored a copy the bank register value
+ in RAM), so it appears that it expects 1 more opcode, see:
+
+ 88D5: LDA $3803
+ 88D8: ANDA #$08 ; vblank flag
+ 88DA: BNE $88D5
+
+ 88DC: LDA #$B7
+ 88DE: STA $3840 ; ghostb_bank_w
+ 88E1: STA <$68 ; expects NMI after this opcode
+
+ Where does this delay come from? Is it a MAME 6809 timing bug with NMI edge
+ detection? Or a brief TTL delay and it works by luck? Either way, it looks
+ like a bug by Data East. Normally you'd store the local variable first,
+ then write to the register.
***************************************************************************/
@@ -184,8 +202,12 @@ void ghostb_state::gondo_bank_w(u8 data)
if (!m_secclr)
m_maincpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
- m_nmigate->in_w<0>(BIT(data, 1));
+ // it relies on 1 more opcode after enabling NMI (see TODO notes)
+ if (BIT(m_bank_data ^ data, 1))
+ m_nmi_timer->adjust(m_maincpu->minimum_quantum_time(), BIT(data, 1));
+
flip_screen_set(BIT(data, 3));
+ m_bank_data = data;
}
void ghostb_state::ghostb_bank_w(u8 data)
@@ -1914,9 +1936,11 @@ void ghostb_state::machine_start()
{
lastmisn_state::machine_start();
+ m_nmi_timer = timer_alloc(FUNC(ghostb_state::nmigate_set), this);
m_6502_timer = timer_alloc(FUNC(ghostb_state::audiocpu_nmi_clear), this);
m_i8751_timer = timer_alloc(FUNC(ghostb_state::mcu_irq_clear), this);
+ save_item(NAME(m_bank_data));
save_item(NAME(m_secclr));
save_item(NAME(m_buffer_strobe));
}
diff --git a/src/mame/dataeast/dec8.h b/src/mame/dataeast/dec8.h
index c2ac489daa7..9990e8ba131 100644
--- a/src/mame/dataeast/dec8.h
+++ b/src/mame/dataeast/dec8.h
@@ -226,6 +226,7 @@ protected:
TIMER_CALLBACK_MEMBER(audiocpu_nmi_clear);
TIMER_CALLBACK_MEMBER(mcu_irq_clear);
+ TIMER_CALLBACK_MEMBER(nmigate_set) { m_nmigate->in_w<0>(param); }
TILE_GET_INFO_MEMBER(get_gondo_fix_tile_info);
TILE_GET_INFO_MEMBER(get_gondo_tile_info);
@@ -246,9 +247,11 @@ private:
void ghostb_map(address_map &map) ATTR_COLD;
void garyoret_map(address_map &map) ATTR_COLD;
+ u8 m_bank_data = 0xff;
bool m_secclr = false;
bool m_buffer_strobe = false;
+ emu_timer *m_nmi_timer = nullptr;
emu_timer *m_6502_timer = nullptr;
emu_timer *m_i8751_timer = nullptr;
};