1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-07 08:28:57 +00:00

Merge pull request #35 from TomHarte/BRKDiversion

Adds a small amount of test coverage to the functioning of 6502 interrupts
This commit is contained in:
Thomas Harte 2016-06-29 21:03:19 -04:00 committed by GitHub
commit 7f10616be9
12 changed files with 179 additions and 57 deletions

View File

@ -69,7 +69,7 @@ void MOS6560::set_output_mode(OutputMode output_mode)
chrominances = ntsc_chrominances;
display_type = Outputs::CRT::NTSC60;
_timing.cycles_per_line = 65;
_timing.line_counter_increment_offset = 65 - 36; // TODO: 36 is from memory; need to look up.
_timing.line_counter_increment_offset = 65 - 33; // TODO: this is a bit of a hack; separate vertical and horizontal counting
_timing.lines_per_progressive_field = 261;
_timing.supports_interlacing = true;
break;

View File

@ -28,7 +28,6 @@ Machine::Machine() :
_is_pal_region(false)
{
memset(_collisions, 0xff, sizeof(_collisions));
set_reset_line(true);
setup_reported_collisions();
for(int vbextend = 0; vbextend < 2; vbextend++)
@ -414,8 +413,6 @@ void Machine::output_pixels(unsigned int count)
unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
set_reset_line(false);
uint8_t returnValue = 0xff;
unsigned int cycles_run_for = 3;

View File

@ -55,7 +55,6 @@ Machine::Machine() :
memset(_roms[c], 0xff, 16384);
_tape.set_delegate(this);
set_reset_line(true);
}
void Machine::setup_output(float aspect_ratio)
@ -86,7 +85,6 @@ void Machine::close_output()
unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
unsigned int cycles = 1;
set_reset_line(false);
if(address < 0x8000)
{

View File

@ -18,7 +18,6 @@ Machine::Machine() :
_userPortVIA.set_delegate(this);
_keyboardVIA.set_delegate(this);
_tape.set_delegate(this);
set_reset_line(true);
}
Machine::~Machine()
@ -28,8 +27,6 @@ Machine::~Machine()
unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
set_reset_line(false);
// test for PC at F92F
if(_use_fast_tape_hack && address == 0xf92f && operation == CPU6502::BusOperation::ReadOpcode)
{

View File

@ -35,7 +35,7 @@
4B73C71A1D036BD90074D992 /* Vic20Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B73C7191D036BD90074D992 /* Vic20Document.swift */; };
4B73C71D1D036C030074D992 /* Vic20Document.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B73C71B1D036C030074D992 /* Vic20Document.xib */; };
4B886FF21D03B517004291C3 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B886FF01D03B517004291C3 /* Vic20.cpp */; };
4B92EACA1B7C112B00246143 /* TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* TimingTests.swift */; };
4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */; };
4BB298EE1B587D8400A49093 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */; };
4BB298EF1B587D8400A49093 /* AllSuiteA.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E11B587D8300A49093 /* AllSuiteA.bin */; };
4BB298F01B587D8400A49093 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BB297E31B587D8300A49093 /* TestMachine.mm */; };
@ -323,6 +323,7 @@
4BC91B831D1F160E00884B76 /* CommodoreTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC91B811D1F160E00884B76 /* CommodoreTAP.cpp */; };
4BC9DF451D044FCA00F44158 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; };
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9DF4D1D04691600F44158 /* 6560.cpp */; };
4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */; };
4BD5F1951D13528900631CD1 /* CSBestEffortUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.m */; };
/* End PBXBuildFile section */
@ -397,7 +398,7 @@
4B73C71C1D036C030074D992 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Vic20Document.xib"; sourceTree = SOURCE_ROOT; };
4B886FF01D03B517004291C3 /* Vic20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Vic20.cpp; path = "Vic-20/Vic20.cpp"; sourceTree = "<group>"; };
4B886FF11D03B517004291C3 /* Vic20.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Vic20.hpp; path = "Vic-20/Vic20.hpp"; sourceTree = "<group>"; };
4B92EAC91B7C112B00246143 /* TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimingTests.swift; sourceTree = "<group>"; };
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6502TimingTests.swift; sourceTree = "<group>"; };
4BB297DF1B587D8200A49093 /* Clock SignalTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Clock SignalTests-Bridging-Header.h"; sourceTree = "<group>"; };
4BB297E01B587D8300A49093 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = "<group>"; };
4BB297E11B587D8300A49093 /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = AllSuiteA.bin; sourceTree = "<group>"; };
@ -708,6 +709,7 @@
4BC9DF441D044FCA00F44158 /* ROMImages */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ROMImages; path = ../../../../ROMImages; sourceTree = "<group>"; };
4BC9DF4D1D04691600F44158 /* 6560.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6560.cpp; sourceTree = "<group>"; };
4BC9DF4E1D04691600F44158 /* 6560.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6560.hpp; sourceTree = "<group>"; };
4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6502InterruptTests.swift; sourceTree = "<group>"; };
4BCA98C21D065CA20062F44C /* 6522.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6522.hpp; sourceTree = "<group>"; };
4BD5F1931D13528900631CD1 /* CSBestEffortUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSBestEffortUpdater.h; path = Updater/CSBestEffortUpdater.h; sourceTree = "<group>"; };
4BD5F1941D13528900631CD1 /* CSBestEffortUpdater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CSBestEffortUpdater.m; path = Updater/CSBestEffortUpdater.m; sourceTree = "<group>"; };
@ -1253,9 +1255,10 @@
4B1E85801D176468001EF87D /* 6532Tests.swift */,
4BB73EB61B587A5100552FC2 /* AllSuiteATests.swift */,
4B1414611B58888700E04248 /* KlausDormannTests.swift */,
4B92EAC91B7C112B00246143 /* TimingTests.swift */,
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */,
4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */,
4B1414631B588A1100E04248 /* Test Binaries */,
4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */,
);
path = "Clock SignalTests";
sourceTree = "<group>";
@ -1814,7 +1817,8 @@
4B14145E1B5887AA00E04248 /* CPU6502AllRAM.cpp in Sources */,
4B14145D1B5887A600E04248 /* CPU6502.cpp in Sources */,
4B1E85811D176468001EF87D /* 6532Tests.swift in Sources */,
4B92EACA1B7C112B00246143 /* TimingTests.swift in Sources */,
4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */,
4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */,
4BB73EB71B587A5100552FC2 /* AllSuiteATests.swift in Sources */,
4BC751B21D157E61006C31D9 /* 6522Tests.swift in Sources */,
4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */,

View File

@ -0,0 +1,73 @@
//
// 6502InterruptTests.swift
// Clock Signal
//
// Created by Thomas Harte on 28/06/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
import XCTest
class MOS6502InterruptTests: XCTestCase {
var machine: CSTestMachine! = nil
override func setUp() {
super.setUp()
// create a machine full of NOPs
machine = CSTestMachine()
for c in 0...65535 {
machine.setValue(0xea, forAddress: UInt16(c))
}
// set the IRQ vector to be 0x1234
machine.setValue(0x34, forAddress: 0xfffe)
machine.setValue(0x12, forAddress: 0xffff)
// add a CLI
machine.setValue(0x58, forAddress: 0x4000)
// pick things off at 0x4000
machine.setValue(0x4000, forRegister: CSTestMachineRegister.ProgramCounter)
}
func testIRQLine() {
// run for six cycles; check that no interrupt has occurred
machine.runForNumberOfCycles(6)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x4003, "No interrupt should have occurred with line low")
// enable the interrupt line, check that it was too late
machine.irqLine = true
machine.runForNumberOfCycles(2)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x4004, "No interrupt should have occurred from interrupt raised between instructions")
// run for a further 7 cycles, confirm that the IRQ vector was jumped to
machine.runForNumberOfCycles(7)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x1234, "Interrupt routine should just have begun")
}
func testIFlagSet() {
// enable the interrupt line, run for eleven cycles to get past the CLIP and the following NOP and into the interrupt routine
machine.irqLine = true
machine.runForNumberOfCycles(11)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x1234, "Interrupt routine should just have begun")
XCTAssert(machine.valueForRegister(.Flags) & 0x04 == 0x04, "Interrupt status flag should be set")
}
func testCLISEIFlagClear() {
// set up an SEI as the second instruction, enable the IRQ line
machine.setValue(0x78, forAddress: 0x4001)
machine.irqLine = true
// run for four cycles; the CLI and SEI should have been performed
machine.runForNumberOfCycles(4)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x4002, "CLI/SEI pair should have been performed in their entirety")
// run for seven more cycles
machine.runForNumberOfCycles(7)
// interrupt should have taken place despite SEI
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x1234, "Interrupt routine should just have begun")
}
}

View File

@ -9,7 +9,7 @@
import Foundation
import XCTest
class TimingTests: XCTestCase, CSTestMachineJamHandler {
class MOS6502TimingTests: XCTestCase, CSTestMachineJamHandler {
private var endTime: UInt32 = 0

View File

@ -46,12 +46,8 @@ class KlausDormannTests: XCTestCase {
if newPC == oldPC {
let error = errorForTrapAddress(oldPC)
if let error = error {
NSException(name: "Failed test", reason: error, userInfo: nil).raise()
} else {
return
}
XCTAssert(error == nil, "Failed with error \(error)")
return
}
}
}

View File

@ -41,5 +41,7 @@ extern const uint8_t CSTestMachineJamOpcode;
@property (nonatomic, readonly) BOOL isJammed;
@property (nonatomic, readonly) uint32_t timestamp;
@property (nonatomic, weak) id <CSTestMachineJamHandler> jamHandler;
@property (nonatomic, assign) BOOL irqLine;
@property (nonatomic, assign) BOOL nmiLine;
@end

View File

@ -99,4 +99,14 @@ class MachineJamHandler: public CPU6502::AllRAMProcessor::JamHandler {
return _processor.get_timestamp();
}
- (void)setIrqLine:(BOOL)irqLine {
_irqLine = irqLine;
_processor.set_irq_line(irqLine);
}
- (void)setNmiLine:(BOOL)nmiLine {
_nmiLine = nmiLine;
_processor.set_nmi_line(nmiLine);
}
@end

View File

@ -92,9 +92,14 @@ template <class T> class Processor {
enum MicroOp {
CycleFetchOperation, CycleFetchOperand, OperationDecodeOperation, CycleIncPCPushPCH,
CyclePushPCH, CyclePushPCL, CyclePushA, CyclePushOperand,
CycleSetIReadBRKLow, CycleReadBRKHigh,
OperationSetI,
OperationBRKPickVector, OperationNMIPickVector, OperationRSTPickVector,
CycleReadVectorLow, CycleReadVectorHigh,
CycleReadFromS, CycleReadFromPC,
CyclePullOperand, CyclePullPCL, CyclePullPCH, CyclePullA,
CycleNoWritePush,
CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL,
CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute,
OperationLoadAddressZeroPage, CycleLoadAddessZeroX, CycleLoadAddessZeroY, CycleAddXToAddressLow,
@ -121,7 +126,6 @@ template <class T> class Processor {
OperationLAS, CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet,
OperationSetOperandFromFlags,
OperationSetFlagsFromA,
CycleReadRSTLow, CycleReadRSTHigh, CycleReadNMILow, CycleReadNMIHigh,
CycleScheduleJam
};
@ -271,7 +275,7 @@ template <class T> class Processor {
static const MicroOp operations[256][10] = {
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, CycleSetIReadBRKLow, CycleReadBRKHigh),
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetI, CycleReadVectorLow, CycleReadVectorHigh),
/* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA),
/* 0x02 JAM */ JAM, /* 0x03 ASO x, ind */ IndexedIndirectReadModifyWrite(OperationASO),
/* 0x04 NOP zpg */ ZeroNop(), /* 0x05 ORA zpg */ ZeroRead(OperationORA),
@ -455,11 +459,19 @@ template <class T> class Processor {
int _cycles_left_to_run;
bool _ready_line_is_enabled;
bool _reset_line_is_enabled;
bool _irq_line_is_enabled, _irq_request_history[2];
bool _nmi_line_is_enabled;
enum InterruptRequestFlags: uint8_t {
Reset = 0x80,
IRQ = 0x40,
NMI = 0x20,
PowerOn = 0x10,
};
uint8_t _interrupt_requests;
bool _ready_is_active;
bool _ready_line_is_enabled;
bool _irq_line_is_enabled, _irq_request_history;
/*!
Gets the program representing an RST response.
@ -470,11 +482,12 @@ template <class T> class Processor {
static const MicroOp reset[] = {
CycleFetchOperand,
CycleFetchOperand,
CyclePullOperand,
CyclePullOperand,
CyclePullOperand,
CycleReadRSTLow,
CycleReadRSTHigh,
CycleNoWritePush,
CycleNoWritePush,
OperationRSTPickVector,
CycleNoWritePush,
CycleReadVectorLow,
CycleReadVectorHigh,
OperationMoveToNextProgram
};
return reset;
@ -487,12 +500,16 @@ template <class T> class Processor {
*/
inline const MicroOp *get_irq_program() {
static const MicroOp reset[] = {
CycleFetchOperand,
CycleFetchOperand,
CyclePushPCH,
CyclePushPCL,
OperationBRKPickVector,
OperationSetOperandFromFlags,
CyclePushOperand,
CycleSetIReadBRKLow,
CycleReadBRKHigh,
OperationSetI,
CycleReadVectorLow,
CycleReadVectorHigh,
OperationMoveToNextProgram
};
return reset;
@ -505,12 +522,15 @@ template <class T> class Processor {
*/
inline const MicroOp *get_nmi_program() {
static const MicroOp reset[] = {
CycleFetchOperand,
CycleFetchOperand,
CyclePushPCH,
CyclePushPCL,
OperationNMIPickVector,
OperationSetOperandFromFlags,
CyclePushOperand,
CycleReadNMILow,
CycleReadNMIHigh,
CycleReadVectorLow,
CycleReadVectorHigh,
OperationMoveToNextProgram
};
return reset;
@ -528,8 +548,8 @@ template <class T> class Processor {
_scheduledPrograms{nullptr, nullptr, nullptr, nullptr},
_interruptFlag(Flag::Interrupt),
_s(0),
_nextBusOperation(BusOperation::None)
_nextBusOperation(BusOperation::None),
_interrupt_requests(InterruptRequestFlags::PowerOn)
{
// only the interrupt flag is defined upon reset but get_flags isn't going to
// mask the other flags so we need to do that, at least
@ -576,13 +596,16 @@ template <class T> class Processor {
#define checkSchedule(op) \
if(!_scheduledPrograms[scheduleProgramsReadPointer]) {\
scheduleProgramsReadPointer = _scheduleProgramsWritePointer = scheduleProgramProgramCounter = 0;\
if(_reset_line_is_enabled) {\
schedule_program(get_reset_program());\
} else if(_nmi_line_is_enabled) {\
_nmi_line_is_enabled = false;\
schedule_program(get_nmi_program());\
} else if(_irq_request_history[0]) {\
schedule_program(get_irq_program());\
if(_interrupt_requests) {\
if(_interrupt_requests & (InterruptRequestFlags::Reset | InterruptRequestFlags::PowerOn)) {\
_interrupt_requests &= ~InterruptRequestFlags::PowerOn;\
schedule_program(get_reset_program());\
} else if(_interrupt_requests & InterruptRequestFlags::NMI) {\
_interrupt_requests &= ~InterruptRequestFlags::NMI;\
schedule_program(get_nmi_program());\
} else if(_interrupt_requests & InterruptRequestFlags::IRQ) {\
schedule_program(get_irq_program());\
} \
} else {\
schedule_program(fetch_decode_execute);\
}\
@ -602,8 +625,8 @@ template <class T> class Processor {
while (!_ready_is_active && number_of_cycles > 0) {
if(nextBusOperation != BusOperation::None) {
_irq_request_history[0] = _irq_request_history[1];
_irq_request_history[1] = _irq_line_is_enabled && !_interruptFlag;
_interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::IRQ) | (_irq_request_history ? InterruptRequestFlags::IRQ : 0);
_irq_request_history = _irq_line_is_enabled && !_interruptFlag;
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(nextBusOperation, busAddress, busValue);
nextBusOperation = BusOperation::None;
}
@ -665,18 +688,28 @@ template <class T> class Processor {
case CyclePushPCL: push(_pc.bytes.low); break;
case CyclePushOperand: push(_operand); break;
case CyclePushA: push(_a); break;
case CycleNoWritePush:
{
uint16_t targetAddress = _s | 0x100; _s--;
read_mem(_operand, targetAddress);
}
break;
#undef push
case CycleReadFromS: throwaway_read(_s | 0x100); break;
case CycleReadFromPC: throwaway_read(_pc.full); break;
case CycleReadNMILow: read_mem(_pc.bytes.low, 0xfffa); break;
case CycleReadNMIHigh: read_mem(_pc.bytes.high, 0xfffb); break;
case CycleReadRSTLow: read_mem(_pc.bytes.low, 0xfffc); break;
case CycleReadRSTHigh: read_mem(_pc.bytes.high, 0xfffd); break;
case CycleSetIReadBRKLow: _interruptFlag = Flag::Interrupt; read_mem(_pc.bytes.low, 0xfffe); break;
case CycleReadBRKHigh: read_mem(_pc.bytes.high, 0xffff); break;
case OperationBRKPickVector:
// NMI can usurp BRK-vector operations
nextAddress.full = (_interrupt_requests & InterruptRequestFlags::NMI) ? 0xfffa : 0xfffe;
_interrupt_requests &= ~InterruptRequestFlags::NMI; // TODO: this probably doesn't happen now?
break;
case OperationNMIPickVector: nextAddress.full = 0xfffa; break;
case OperationRSTPickVector: nextAddress.full = 0xfffc; break;
case CycleReadVectorLow: read_mem(_pc.bytes.low, nextAddress.full); break;
case CycleReadVectorHigh: read_mem(_pc.bytes.high, nextAddress.full+1); break;
case OperationSetI: _interruptFlag = Flag::Interrupt; break;
case CyclePullPCL: _s++; read_mem(_pc.bytes.low, _s | 0x100); break;
case CyclePullPCH: _s++; read_mem(_pc.bytes.high, _s | 0x100); break;
@ -1171,7 +1204,7 @@ template <class T> class Processor {
*/
inline void set_reset_line(bool active)
{
_reset_line_is_enabled = active;
_interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::Reset) | (active ? InterruptRequestFlags::Reset : 0);
}
/*!
@ -1181,7 +1214,16 @@ template <class T> class Processor {
*/
inline bool get_reset_line()
{
return _reset_line_is_enabled;
return !!(_interrupt_requests & InterruptRequestFlags::Reset);
}
/*!
This emulation automatically sets itself up in power-on state at creation, which has the effect of triggering a
reset at the first opportunity. Use @c set_power_on to disable that behaviour.
*/
inline void set_power_on(bool active)
{
_interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::PowerOn) | (active ? InterruptRequestFlags::PowerOn : 0);
}
/*!
@ -1202,7 +1244,7 @@ template <class T> class Processor {
inline void set_nmi_line(bool active)
{
// NMI is edge triggered, not level
_nmi_line_is_enabled |= active;
_interrupt_requests |= (active ? InterruptRequestFlags::NMI : 0);
}
/*!

View File

@ -12,7 +12,10 @@
using namespace CPU6502;
AllRAMProcessor::AllRAMProcessor() : _timestamp(0) {}
AllRAMProcessor::AllRAMProcessor() : _timestamp(0)
{
set_power_on(false);
}
int AllRAMProcessor::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{