From 8bfa5a599fb8942bdaaeda59bcd9a8d56132ea9b Mon Sep 17 00:00:00 2001 From: hap Date: Sat, 18 Jul 2020 20:58:31 +0200 Subject: [PATCH] 6502: nmi is edge triggered --- src/devices/cpu/m6502/m6502.cpp | 21 ++++++++++++++------- src/devices/cpu/m6502/m6502.h | 2 +- src/devices/cpu/m6502/m740.cpp | 1 + src/devices/cpu/m6502/odeco16.lst | 6 +++--- src/devices/cpu/m6502/om6502.lst | 6 +++--- src/devices/cpu/m6502/om65c02.lst | 10 +++++----- src/devices/cpu/m6502/om65ce02.lst | 6 +++--- src/devices/cpu/m6502/om740.lst | 6 +++--- src/devices/cpu/m6502/or65c19.lst | 8 ++++---- src/devices/cpu/m6502/ost2xxx.lst | 8 ++++---- src/devices/cpu/m6502/oxavix.lst | 8 ++++---- src/mame/drivers/saitek_intchess.cpp | 11 +---------- 12 files changed, 46 insertions(+), 47 deletions(-) diff --git a/src/devices/cpu/m6502/m6502.cpp b/src/devices/cpu/m6502/m6502.cpp index 7999749153f..f69e672ed31 100644 --- a/src/devices/cpu/m6502/m6502.cpp +++ b/src/devices/cpu/m6502/m6502.cpp @@ -31,7 +31,7 @@ m6502_device::m6502_device(const machine_config &mconfig, device_type type, cons sync_w(*this), program_config("program", ENDIANNESS_LITTLE, 8, 16), sprogram_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16), PPC(0), NPC(0), PC(0), SP(0), TMP(0), TMP2(0), A(0), X(0), Y(0), P(0), IR(0), inst_state_base(0), mintf(nullptr), - inst_state(0), inst_substate(0), icount(0), nmi_state(false), irq_state(false), apu_irq_state(false), v_state(false), irq_taken(false), sync(false), inhibit_interrupts(false) + inst_state(0), inst_substate(0), icount(0), nmi_state(false), irq_state(false), apu_irq_state(false), v_state(false), nmi_pending(false), irq_taken(false), sync(false), inhibit_interrupts(false) { } @@ -82,10 +82,11 @@ void m6502_device::init() save_item(NAME(irq_state)); save_item(NAME(apu_irq_state)); save_item(NAME(v_state)); + save_item(NAME(nmi_pending)); + save_item(NAME(irq_taken)); save_item(NAME(inst_state)); save_item(NAME(inst_substate)); save_item(NAME(inst_state_base)); - save_item(NAME(irq_taken)); save_item(NAME(inhibit_interrupts)); set_icountptr(icount); @@ -103,8 +104,9 @@ void m6502_device::init() nmi_state = false; irq_state = false; apu_irq_state = false; - irq_taken = false; v_state = false; + nmi_pending = false; + irq_taken = false; inst_state = STATE_RESET; inst_substate = 0; inst_state_base = 0; @@ -118,11 +120,12 @@ void m6502_device::device_reset() inst_state = STATE_RESET; inst_substate = 0; inst_state_base = 0; - nmi_state = false; irq_state = false; + nmi_state = false; apu_irq_state = false; - irq_taken = false; v_state = false; + nmi_pending = false; + irq_taken = false; sync = false; sync_w(CLEAR_LINE); inhibit_interrupts = false; @@ -410,7 +413,11 @@ void m6502_device::execute_set_input(int inputnum, int state) switch(inputnum) { case IRQ_LINE: irq_state = state == ASSERT_LINE; break; case APU_IRQ_LINE: apu_irq_state = state == ASSERT_LINE; break; - case NMI_LINE: nmi_state = nmi_state || (state == ASSERT_LINE); break; + case NMI_LINE: + if(!nmi_state && state == ASSERT_LINE) + nmi_pending = true; + nmi_state = state == ASSERT_LINE; + break; case V_LINE: if(!v_state && state == ASSERT_LINE) P |= F_V; @@ -484,7 +491,7 @@ void m6502_device::prefetch() sync = false; sync_w(CLEAR_LINE); - if((nmi_state || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) { + if((nmi_pending || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) { irq_taken = true; IR = 0x00; } else diff --git a/src/devices/cpu/m6502/m6502.h b/src/devices/cpu/m6502/m6502.h index 413925efa0d..077de2920ac 100644 --- a/src/devices/cpu/m6502/m6502.h +++ b/src/devices/cpu/m6502/m6502.h @@ -122,7 +122,7 @@ protected: int inst_state, inst_substate; int icount, bcount, count_before_instruction_step; bool nmi_state, irq_state, apu_irq_state, v_state; - bool irq_taken, sync, inhibit_interrupts; + bool nmi_pending, irq_taken, sync, inhibit_interrupts; uint8_t read(uint16_t adr) { return mintf->read(adr); } uint8_t read_9(uint16_t adr) { return mintf->read_9(adr); } diff --git a/src/devices/cpu/m6502/m740.cpp b/src/devices/cpu/m6502/m740.cpp index 684bff6773b..748c48e79cb 100644 --- a/src/devices/cpu/m6502/m740.cpp +++ b/src/devices/cpu/m6502/m740.cpp @@ -52,6 +52,7 @@ void m740_device::device_reset() m_irq_vector = 0xfffc; apu_irq_state = false; irq_taken = false; + nmi_pending = false; v_state = false; sync = false; inhibit_interrupts = false; diff --git a/src/devices/cpu/m6502/odeco16.lst b/src/devices/cpu/m6502/odeco16.lst index 694eb2f3613..53f9e1b1977 100644 --- a/src/devices/cpu/m6502/odeco16.lst +++ b/src/devices/cpu/m6502/odeco16.lst @@ -2,7 +2,7 @@ # copyright-holders:Olivier Galibert # deco 16 opcodes brk_16_imp - // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state) + // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending) if(irq_taken) { read_pc_noinc(); } else { @@ -14,10 +14,10 @@ brk_16_imp dec_SP(); write(SP, irq_taken ? P & ~F_B : P); dec_SP(); - if(nmi_state) { + if(nmi_pending) { PC = read_arg(0xfff7); PC = set_h(PC, read_arg(0xfff6)); - nmi_state = false; + nmi_pending = false; standard_irq_callback(NMI_LINE); } else { PC = read_arg(0xfff3); diff --git a/src/devices/cpu/m6502/om6502.lst b/src/devices/cpu/m6502/om6502.lst index d34e63c1d81..4026965ffa0 100644 --- a/src/devices/cpu/m6502/om6502.lst +++ b/src/devices/cpu/m6502/om6502.lst @@ -259,7 +259,7 @@ bpl_rel prefetch(); brk_imp - // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state) + // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending) if(irq_taken) { read_pc_noinc(); } else { @@ -271,10 +271,10 @@ brk_imp dec_SP(); write(SP, irq_taken ? P & ~F_B : P); dec_SP(); - if(nmi_state) { + if(nmi_pending) { PC = read_arg(0xfffa); PC = set_h(PC, read_arg(0xfffb)); - nmi_state = false; + nmi_pending = false; standard_irq_callback(NMI_LINE); } else { PC = read_arg(0xfffe); diff --git a/src/devices/cpu/m6502/om65c02.lst b/src/devices/cpu/m6502/om65c02.lst index 3e414cd7bfd..34cc070b6f1 100644 --- a/src/devices/cpu/m6502/om65c02.lst +++ b/src/devices/cpu/m6502/om65c02.lst @@ -220,7 +220,7 @@ bra_rel prefetch(); brk_c_imp - if(irq_taken || nmi_state) { + if(irq_taken || nmi_pending) { read_pc_noinc(); } else { read_pc(); @@ -229,12 +229,12 @@ brk_c_imp dec_SP(); write(SP, PC); dec_SP(); - write(SP, irq_taken || nmi_state ? P & ~F_B : P); + write(SP, irq_taken || nmi_pending ? P & ~F_B : P); dec_SP(); - if(irq_taken && nmi_state) { + if(irq_taken && nmi_pending) { PC = read_arg(0xfffa); PC = set_h(PC, read_arg(0xfffb)); - nmi_state = false; + nmi_pending = false; standard_irq_callback(NMI_LINE); } else { PC = read_arg(0xfffe); @@ -766,7 +766,7 @@ tsb_zpg wai_imp read_pc_noinc(); read_pc_noinc(); - while(!nmi_state && !irq_state) { + while(!nmi_pending && !irq_state) { eat-all-cycles; } prefetch(); diff --git a/src/devices/cpu/m6502/om65ce02.lst b/src/devices/cpu/m6502/om65ce02.lst index 85648fd610d..e836b45a150 100644 --- a/src/devices/cpu/m6502/om65ce02.lst +++ b/src/devices/cpu/m6502/om65ce02.lst @@ -359,12 +359,12 @@ brk_ce_imp dec_SP_ce(); write(SP, PC); dec_SP_ce(); - write(SP, irq_taken || nmi_state ? P & ~F_B : P); + write(SP, irq_taken || nmi_pending ? P & ~F_B : P); dec_SP_ce(); - if(nmi_state) { + if(nmi_pending) { PC = read_arg(0xfffa); PC = set_h(PC, read_arg(0xfffb)); - nmi_state = false; + nmi_pending = false; } else { PC = read_arg(0xfffe); PC = set_h(PC, read_arg(0xffff)); diff --git a/src/devices/cpu/m6502/om740.lst b/src/devices/cpu/m6502/om740.lst index 34652361335..342d224131d 100644 --- a/src/devices/cpu/m6502/om740.lst +++ b/src/devices/cpu/m6502/om740.lst @@ -120,7 +120,7 @@ reset740 inst_state = -1; brk740_imp - // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state) + // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending) if(irq_taken) { read_pc_noinc(); } else { @@ -132,10 +132,10 @@ brk740_imp dec_SP(); write(SP, irq_taken ? P & ~F_B : P); dec_SP(); - if(nmi_state) { + if(nmi_pending) { PC = read_arg(0xfffa); PC = set_h(PC, read_arg(0xfffb)); - nmi_state = false; + nmi_pending = false; standard_irq_callback(NMI_LINE); } else { PC = read_arg(m_irq_vector); diff --git a/src/devices/cpu/m6502/or65c19.lst b/src/devices/cpu/m6502/or65c19.lst index e8314033b9d..47f24f57329 100644 --- a/src/devices/cpu/m6502/or65c19.lst +++ b/src/devices/cpu/m6502/or65c19.lst @@ -95,7 +95,7 @@ bas_amr prefetch(); brk_r_imp - if(irq_taken || nmi_state) { + if(irq_taken || nmi_pending) { read_pc_noinc(); } else { read_pc(); @@ -104,12 +104,12 @@ brk_r_imp dec_SP(); write(SP, PC); dec_SP(); - write(SP, irq_taken || nmi_state ? P & ~F_B : P); + write(SP, irq_taken || nmi_pending ? P & ~F_B : P); dec_SP(); - if(irq_taken && nmi_state) { + if(irq_taken && nmi_pending) { PC = read_arg(0xfffc); PC = set_h(PC, read_arg(0xfffd)); - nmi_state = false; + nmi_pending = false; standard_irq_callback(NMI_LINE); } else { TMP = get_irq_vector(); diff --git a/src/devices/cpu/m6502/ost2xxx.lst b/src/devices/cpu/m6502/ost2xxx.lst index 9b30c2e9b05..4468fe14476 100644 --- a/src/devices/cpu/m6502/ost2xxx.lst +++ b/src/devices/cpu/m6502/ost2xxx.lst @@ -3,7 +3,7 @@ # m65c02 opcodes, with a twist brk_st_imp - if(irq_taken || nmi_state) { + if(irq_taken || nmi_pending) { read_pc_noinc(); } else { read_pc(); @@ -12,13 +12,13 @@ brk_st_imp dec_SP(); write(SP, PC); dec_SP(); - write(SP, irq_taken || nmi_state ? P & ~F_B : P); + write(SP, irq_taken || nmi_pending ? P & ~F_B : P); dec_SP(); set_irq_service(true); - if(irq_taken && nmi_state) { // NMI is not present on actual parts + if(irq_taken && nmi_pending) { // NMI is not present on actual parts PC = read_vector(0x7ffa); PC = set_h(PC, read_vector(0x7ffb)); - nmi_state = false; + nmi_pending = false; } else if(irq_taken) { TMP = acknowledge_irq(); PC = read_vector(0x7ff8 - (TMP << 1)); diff --git a/src/devices/cpu/m6502/oxavix.lst b/src/devices/cpu/m6502/oxavix.lst index 0f1f60e4221..c45e89e0a61 100644 --- a/src/devices/cpu/m6502/oxavix.lst +++ b/src/devices/cpu/m6502/oxavix.lst @@ -40,8 +40,8 @@ retf_imp prefetch(); brk_xav_imp - // there is code in soem games to indicate this doesn't always push the far bank to the stack.. - // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state) + // there is code in some games to indicate this doesn't always push the far bank to the stack.. + // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending) if(irq_taken) { read_pc_noinc(); } else { @@ -56,7 +56,7 @@ brk_xav_imp dec_SP(); write_stack(SP, irq_taken ? P & ~F_B : P); dec_SP(); - if(nmi_state) { + if(nmi_pending) { if (m_vector_callback.isnull()) { PC = read_arg(0xfffa); @@ -76,7 +76,7 @@ brk_xav_imp } } - nmi_state = false; + nmi_pending = false; standard_irq_callback(NMI_LINE); } else { if (m_vector_callback.isnull()) diff --git a/src/mame/drivers/saitek_intchess.cpp b/src/mame/drivers/saitek_intchess.cpp index c49b4a4f3f1..faff4fe2fb9 100644 --- a/src/mame/drivers/saitek_intchess.cpp +++ b/src/mame/drivers/saitek_intchess.cpp @@ -18,8 +18,6 @@ Hardware notes: - 4-digit 7seg display TODO: -- 6502 CPU core NMI isn't working properly at the moment, it acts like a hold_line, - m_nmistate can be removed once that is fixed - colors are estimated from photos (black and white are obvious, but the green and cyan are not standard 0x00ff00 / 0x00ffff) - video timing is unknown, sprite offsets are estimated from photos @@ -101,7 +99,6 @@ private: u8 m_select = 0; u8 m_7seg_data = 0; - bool m_nmistate = false; }; void intchess_state::machine_start() @@ -109,7 +106,6 @@ void intchess_state::machine_start() // register for savestates save_item(NAME(m_select)); save_item(NAME(m_7seg_data)); - save_item(NAME(m_nmistate)); } INPUT_CHANGED_MEMBER(intchess_state::reset_button) @@ -209,12 +205,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(intchess_state::cass_input) { // cassette input is tied to NMI bool state = ((m_cass->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) && (m_cass->input() < -0.04); - - if (state != m_nmistate) - { - m_maincpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE); - m_nmistate = state; - } + m_maincpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE); }