--- Frodo4/Src/CPUC64_SC.cpp 2004/01/11 14:03:29 1.4 +++ Frodo4/Src/CPUC64_SC.cpp 2010/04/22 15:08:18 1.8 @@ -1,7 +1,7 @@ /* * CPUC64_SC.cpp - Single-cycle 6510 (C64) emulation * - * Frodo (C) 1994-1997,2002-2003 Christian Bauer + * Frodo Copyright (C) Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -103,6 +103,7 @@ MOS6510::MOS6510(C64 *c64, uint8 *Ram, u dfff_byte = 0x55; BALow = false; first_irq_cycle = first_nmi_cycle = 0; + opflags = 0; } @@ -179,6 +180,7 @@ void MOS6510::SetState(MOS6510State *s) ddr = s->ddr; pr = s->pr; + pr_out = 0; // FIXME: should be saved in MOS6510State new_config(); pc = s->pc; @@ -201,7 +203,8 @@ void MOS6510::SetState(MOS6510State *s) void MOS6510::new_config(void) { - uint8 port = ~ddr | pr; + pr_out = (pr_out & ~ddr) | (pr & ddr); + uint8 port = pr | ~ddr; basic_in = (port & 3) == 3; kernal_in = port & 2; @@ -279,12 +282,16 @@ inline uint8 MOS6510::read_byte_io(uint1 uint8 MOS6510::read_byte(uint16 adr) { if (adr < 0xa000) { - if (adr >= 2) + if (adr >= 2) { return ram[adr]; - else if (adr == 0) + } else if (adr == 0) { return ddr; - else - return (ddr & pr) | (~ddr & 0x17); + } else { + uint8 byte = (pr | ~ddr) & (pr_out | 0x17); + if (!(ddr & 0x20)) + byte &= 0xdf; + return byte; + } } else return read_byte_io(adr); } @@ -294,7 +301,7 @@ uint8 MOS6510::read_byte(uint16 adr) * $dfa0-$dfff: Emulator identification */ -const char frodo_id[0x5c] = "FRODO\r(C) 1994-1997 CHRISTIAN BAUER"; +const char frodo_id[0x5c] = "FRODO\r(C) CHRISTIAN BAUER"; uint8 MOS6510::read_emulator_id(uint16 adr) { @@ -546,12 +553,13 @@ void MOS6510::Reset(void) ram[0x8004] = 0; // Initialize extra 6510 registers and memory configuration - ddr = pr = 0; + ddr = pr = pr_out = 0; new_config(); // Clear all interrupt lines interrupt.intr_any = 0; nmi_state = false; + opflags = 0; // Read reset vector pc = read_word(0xfffc); @@ -596,13 +604,23 @@ void MOS6510::EmulateCycle(void) // Any pending interrupts in state 0 (opcode fetch)? if (!state && interrupt.intr_any) { - if (interrupt.intr[INT_RESET]) + if (interrupt.intr[INT_RESET]) { Reset(); - else if (interrupt.intr[INT_NMI] && (the_c64->CycleCounter-first_nmi_cycle >= 2)) { - interrupt.intr[INT_NMI] = false; // Simulate an edge-triggered input - state = 0x0010; - } else if ((interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]) && (the_c64->CycleCounter-first_irq_cycle >= 2) && !i_flag) - state = 0x0008; + } else if (interrupt.intr[INT_NMI]) { + uint32 int_delay = (opflags & OPFLAG_INT_DELAYED) ? 1 : 0; // Taken branches to the same page delay the NMI + if (the_c64->CycleCounter - first_nmi_cycle - int_delay >= 2) { + interrupt.intr[INT_NMI] = false; // Simulate an edge-triggered input + state = 0x0010; + opflags = 0; + } + } else if ((interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]) && + (!i_flag || (opflags & OPFLAG_IRQ_DISABLED)) && !(opflags & OPFLAG_IRQ_ENABLED)) { + uint32 int_delay = (opflags & OPFLAG_INT_DELAYED) ? 1 : 0; // Taken branches to the same page delay the IRQ + if (the_c64->CycleCounter - first_irq_cycle - int_delay >= 2) { + state = 0x0008; + opflags = 0; + } + } } #include "CPU_emulcycle.h"