6502: nmi is edge triggered

This commit is contained in:
hap 2020-07-18 20:58:31 +02:00
parent 5716df3b90
commit 8bfa5a599f
12 changed files with 46 additions and 47 deletions

View File

@ -31,7 +31,7 @@ m6502_device::m6502_device(const machine_config &mconfig, device_type type, cons
sync_w(*this), sync_w(*this),
program_config("program", ENDIANNESS_LITTLE, 8, 16), 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), 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(irq_state));
save_item(NAME(apu_irq_state)); save_item(NAME(apu_irq_state));
save_item(NAME(v_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_state));
save_item(NAME(inst_substate)); save_item(NAME(inst_substate));
save_item(NAME(inst_state_base)); save_item(NAME(inst_state_base));
save_item(NAME(irq_taken));
save_item(NAME(inhibit_interrupts)); save_item(NAME(inhibit_interrupts));
set_icountptr(icount); set_icountptr(icount);
@ -103,8 +104,9 @@ void m6502_device::init()
nmi_state = false; nmi_state = false;
irq_state = false; irq_state = false;
apu_irq_state = false; apu_irq_state = false;
irq_taken = false;
v_state = false; v_state = false;
nmi_pending = false;
irq_taken = false;
inst_state = STATE_RESET; inst_state = STATE_RESET;
inst_substate = 0; inst_substate = 0;
inst_state_base = 0; inst_state_base = 0;
@ -118,11 +120,12 @@ void m6502_device::device_reset()
inst_state = STATE_RESET; inst_state = STATE_RESET;
inst_substate = 0; inst_substate = 0;
inst_state_base = 0; inst_state_base = 0;
nmi_state = false;
irq_state = false; irq_state = false;
nmi_state = false;
apu_irq_state = false; apu_irq_state = false;
irq_taken = false;
v_state = false; v_state = false;
nmi_pending = false;
irq_taken = false;
sync = false; sync = false;
sync_w(CLEAR_LINE); sync_w(CLEAR_LINE);
inhibit_interrupts = false; inhibit_interrupts = false;
@ -410,7 +413,11 @@ void m6502_device::execute_set_input(int inputnum, int state)
switch(inputnum) { switch(inputnum) {
case IRQ_LINE: irq_state = state == ASSERT_LINE; break; case IRQ_LINE: irq_state = state == ASSERT_LINE; break;
case APU_IRQ_LINE: apu_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: case V_LINE:
if(!v_state && state == ASSERT_LINE) if(!v_state && state == ASSERT_LINE)
P |= F_V; P |= F_V;
@ -484,7 +491,7 @@ void m6502_device::prefetch()
sync = false; sync = false;
sync_w(CLEAR_LINE); 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; irq_taken = true;
IR = 0x00; IR = 0x00;
} else } else

View File

@ -122,7 +122,7 @@ protected:
int inst_state, inst_substate; int inst_state, inst_substate;
int icount, bcount, count_before_instruction_step; int icount, bcount, count_before_instruction_step;
bool nmi_state, irq_state, apu_irq_state, v_state; 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(uint16_t adr) { return mintf->read(adr); }
uint8_t read_9(uint16_t adr) { return mintf->read_9(adr); } uint8_t read_9(uint16_t adr) { return mintf->read_9(adr); }

View File

@ -52,6 +52,7 @@ void m740_device::device_reset()
m_irq_vector = 0xfffc; m_irq_vector = 0xfffc;
apu_irq_state = false; apu_irq_state = false;
irq_taken = false; irq_taken = false;
nmi_pending = false;
v_state = false; v_state = false;
sync = false; sync = false;
inhibit_interrupts = false; inhibit_interrupts = false;

View File

@ -2,7 +2,7 @@
# copyright-holders:Olivier Galibert # copyright-holders:Olivier Galibert
# deco 16 opcodes # deco 16 opcodes
brk_16_imp 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) { if(irq_taken) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
@ -14,10 +14,10 @@ brk_16_imp
dec_SP(); dec_SP();
write(SP, irq_taken ? P & ~F_B : P); write(SP, irq_taken ? P & ~F_B : P);
dec_SP(); dec_SP();
if(nmi_state) { if(nmi_pending) {
PC = read_arg(0xfff7); PC = read_arg(0xfff7);
PC = set_h(PC, read_arg(0xfff6)); PC = set_h(PC, read_arg(0xfff6));
nmi_state = false; nmi_pending = false;
standard_irq_callback(NMI_LINE); standard_irq_callback(NMI_LINE);
} else { } else {
PC = read_arg(0xfff3); PC = read_arg(0xfff3);

View File

@ -259,7 +259,7 @@ bpl_rel
prefetch(); prefetch();
brk_imp 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) { if(irq_taken) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
@ -271,10 +271,10 @@ brk_imp
dec_SP(); dec_SP();
write(SP, irq_taken ? P & ~F_B : P); write(SP, irq_taken ? P & ~F_B : P);
dec_SP(); dec_SP();
if(nmi_state) { if(nmi_pending) {
PC = read_arg(0xfffa); PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb)); PC = set_h(PC, read_arg(0xfffb));
nmi_state = false; nmi_pending = false;
standard_irq_callback(NMI_LINE); standard_irq_callback(NMI_LINE);
} else { } else {
PC = read_arg(0xfffe); PC = read_arg(0xfffe);

View File

@ -220,7 +220,7 @@ bra_rel
prefetch(); prefetch();
brk_c_imp brk_c_imp
if(irq_taken || nmi_state) { if(irq_taken || nmi_pending) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
read_pc(); read_pc();
@ -229,12 +229,12 @@ brk_c_imp
dec_SP(); dec_SP();
write(SP, PC); write(SP, PC);
dec_SP(); dec_SP();
write(SP, irq_taken || nmi_state ? P & ~F_B : P); write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
dec_SP(); dec_SP();
if(irq_taken && nmi_state) { if(irq_taken && nmi_pending) {
PC = read_arg(0xfffa); PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb)); PC = set_h(PC, read_arg(0xfffb));
nmi_state = false; nmi_pending = false;
standard_irq_callback(NMI_LINE); standard_irq_callback(NMI_LINE);
} else { } else {
PC = read_arg(0xfffe); PC = read_arg(0xfffe);
@ -766,7 +766,7 @@ tsb_zpg
wai_imp wai_imp
read_pc_noinc(); read_pc_noinc();
read_pc_noinc(); read_pc_noinc();
while(!nmi_state && !irq_state) { while(!nmi_pending && !irq_state) {
eat-all-cycles; eat-all-cycles;
} }
prefetch(); prefetch();

View File

@ -359,12 +359,12 @@ brk_ce_imp
dec_SP_ce(); dec_SP_ce();
write(SP, PC); write(SP, PC);
dec_SP_ce(); 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(); dec_SP_ce();
if(nmi_state) { if(nmi_pending) {
PC = read_arg(0xfffa); PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb)); PC = set_h(PC, read_arg(0xfffb));
nmi_state = false; nmi_pending = false;
} else { } else {
PC = read_arg(0xfffe); PC = read_arg(0xfffe);
PC = set_h(PC, read_arg(0xffff)); PC = set_h(PC, read_arg(0xffff));

View File

@ -120,7 +120,7 @@ reset740
inst_state = -1; inst_state = -1;
brk740_imp 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) { if(irq_taken) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
@ -132,10 +132,10 @@ brk740_imp
dec_SP(); dec_SP();
write(SP, irq_taken ? P & ~F_B : P); write(SP, irq_taken ? P & ~F_B : P);
dec_SP(); dec_SP();
if(nmi_state) { if(nmi_pending) {
PC = read_arg(0xfffa); PC = read_arg(0xfffa);
PC = set_h(PC, read_arg(0xfffb)); PC = set_h(PC, read_arg(0xfffb));
nmi_state = false; nmi_pending = false;
standard_irq_callback(NMI_LINE); standard_irq_callback(NMI_LINE);
} else { } else {
PC = read_arg(m_irq_vector); PC = read_arg(m_irq_vector);

View File

@ -95,7 +95,7 @@ bas_amr
prefetch(); prefetch();
brk_r_imp brk_r_imp
if(irq_taken || nmi_state) { if(irq_taken || nmi_pending) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
read_pc(); read_pc();
@ -104,12 +104,12 @@ brk_r_imp
dec_SP(); dec_SP();
write(SP, PC); write(SP, PC);
dec_SP(); dec_SP();
write(SP, irq_taken || nmi_state ? P & ~F_B : P); write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
dec_SP(); dec_SP();
if(irq_taken && nmi_state) { if(irq_taken && nmi_pending) {
PC = read_arg(0xfffc); PC = read_arg(0xfffc);
PC = set_h(PC, read_arg(0xfffd)); PC = set_h(PC, read_arg(0xfffd));
nmi_state = false; nmi_pending = false;
standard_irq_callback(NMI_LINE); standard_irq_callback(NMI_LINE);
} else { } else {
TMP = get_irq_vector(); TMP = get_irq_vector();

View File

@ -3,7 +3,7 @@
# m65c02 opcodes, with a twist # m65c02 opcodes, with a twist
brk_st_imp brk_st_imp
if(irq_taken || nmi_state) { if(irq_taken || nmi_pending) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
read_pc(); read_pc();
@ -12,13 +12,13 @@ brk_st_imp
dec_SP(); dec_SP();
write(SP, PC); write(SP, PC);
dec_SP(); dec_SP();
write(SP, irq_taken || nmi_state ? P & ~F_B : P); write(SP, irq_taken || nmi_pending ? P & ~F_B : P);
dec_SP(); dec_SP();
set_irq_service(true); 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 = read_vector(0x7ffa);
PC = set_h(PC, read_vector(0x7ffb)); PC = set_h(PC, read_vector(0x7ffb));
nmi_state = false; nmi_pending = false;
} else if(irq_taken) { } else if(irq_taken) {
TMP = acknowledge_irq(); TMP = acknowledge_irq();
PC = read_vector(0x7ff8 - (TMP << 1)); PC = read_vector(0x7ff8 - (TMP << 1));

View File

@ -40,8 +40,8 @@ retf_imp
prefetch(); prefetch();
brk_xav_imp brk_xav_imp
// there is code in soem games to indicate this doesn't always push the far bank to the stack.. // 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_state) // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_pending)
if(irq_taken) { if(irq_taken) {
read_pc_noinc(); read_pc_noinc();
} else { } else {
@ -56,7 +56,7 @@ brk_xav_imp
dec_SP(); dec_SP();
write_stack(SP, irq_taken ? P & ~F_B : P); write_stack(SP, irq_taken ? P & ~F_B : P);
dec_SP(); dec_SP();
if(nmi_state) { if(nmi_pending) {
if (m_vector_callback.isnull()) if (m_vector_callback.isnull())
{ {
PC = read_arg(0xfffa); PC = read_arg(0xfffa);
@ -76,7 +76,7 @@ brk_xav_imp
} }
} }
nmi_state = false; nmi_pending = false;
standard_irq_callback(NMI_LINE); standard_irq_callback(NMI_LINE);
} else { } else {
if (m_vector_callback.isnull()) if (m_vector_callback.isnull())

View File

@ -18,8 +18,6 @@ Hardware notes:
- 4-digit 7seg display - 4-digit 7seg display
TODO: 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 - colors are estimated from photos (black and white are obvious, but the green
and cyan are not standard 0x00ff00 / 0x00ffff) and cyan are not standard 0x00ff00 / 0x00ffff)
- video timing is unknown, sprite offsets are estimated from photos - video timing is unknown, sprite offsets are estimated from photos
@ -101,7 +99,6 @@ private:
u8 m_select = 0; u8 m_select = 0;
u8 m_7seg_data = 0; u8 m_7seg_data = 0;
bool m_nmistate = false;
}; };
void intchess_state::machine_start() void intchess_state::machine_start()
@ -109,7 +106,6 @@ void intchess_state::machine_start()
// register for savestates // register for savestates
save_item(NAME(m_select)); save_item(NAME(m_select));
save_item(NAME(m_7seg_data)); save_item(NAME(m_7seg_data));
save_item(NAME(m_nmistate));
} }
INPUT_CHANGED_MEMBER(intchess_state::reset_button) 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 // cassette input is tied to NMI
bool state = ((m_cass->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) && (m_cass->input() < -0.04); bool state = ((m_cass->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) && (m_cass->input() < -0.04);
m_maincpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE);
if (state != m_nmistate)
{
m_maincpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE);
m_nmistate = state;
}
} }