From 3bb4eed9d15ca74e9ed224c2a0acce3a7b076a88 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Mon, 31 Jul 2017 21:35:34 -0400 Subject: [PATCH] optimizations, refactoring, cleanup, fixing warnings, all kinds of stuff --- FruitMachine.xcodeproj/project.pbxproj | 6 +- FruitMachine/AppleI/AppleI.swift | 12 +- FruitMachine/AppleI/AppleIBitmapDisplay.swift | 7 +- FruitMachine/AppleI/Video/BitmapPixels.swift | 12 +- .../AppleI/Video/CharacterGenerator.swift | 37 +++- FruitMachine/M6502/CPU.swift | 29 +++- .../Debugger/DebuggerViewController.swift | 2 +- .../M6502/Memory/MemoryInterface.swift | 4 +- FruitMachine/M6502/Memory/ReadOverride.swift | 2 +- FruitMachine/M6502/Memory/WriteOverride.swift | 2 +- .../M6502/Opcodes/CPUInstructions.swift | 24 +-- FruitMachine/M6502/Opcodes/Opcodes.swift | 158 +++++++++--------- 12 files changed, 159 insertions(+), 136 deletions(-) diff --git a/FruitMachine.xcodeproj/project.pbxproj b/FruitMachine.xcodeproj/project.pbxproj index 641aeb8..9b97ff8 100644 --- a/FruitMachine.xcodeproj/project.pbxproj +++ b/FruitMachine.xcodeproj/project.pbxproj @@ -369,7 +369,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Debug; }; @@ -428,10 +428,12 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = FruitMachine/FruitMachine.entitlements; COMBINE_HIDPI_IMAGES = YES; + GENERATE_PROFILING_CODE = YES; INFOPLIST_FILE = FruitMachine/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.luigithirty.FruitMachine; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; @@ -442,10 +444,12 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = FruitMachine/FruitMachine.entitlements; COMBINE_HIDPI_IMAGES = YES; + GENERATE_PROFILING_CODE = YES; INFOPLIST_FILE = FruitMachine/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.luigithirty.FruitMachine; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; diff --git a/FruitMachine/AppleI/AppleI.swift b/FruitMachine/AppleI/AppleI.swift index d2b0708..6cc7e18 100644 --- a/FruitMachine/AppleI/AppleI.swift +++ b/FruitMachine/AppleI/AppleI.swift @@ -58,26 +58,30 @@ class AppleI: NSObject { } func runFrame() { + let startTime = CFAbsoluteTimeGetCurrent() CPU.sharedInstance.cycles = 0 CPU.sharedInstance.cyclesInBatch = AppleI.CYCLES_PER_BATCH CPU.sharedInstance.runCyclesBatch() + let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime + print("Time elapsed for runFrame: \(timeElapsed) s.") + //update the video display CVPixelBufferLockBaseAddress(emulatorViewDelegate.pixels!, CVPixelBufferLockFlags(rawValue: 0)) let pixelBase = CVPixelBufferGetBaseAddress(emulatorViewDelegate.pixels!) let buf = pixelBase?.assumingMemoryBound(to: BitmapPixelsBE555.PixelData.self) for (cellNum, character) in terminal.characters.enumerated() { - emulatorViewDelegate.putCharacterPixels(buffer: buf, - charPixels: cg.getCharacterPixels(charIndex: character), - pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum)) + emulatorViewDelegate.putGlyph(buffer: buf, + glyph: cg.glyphs[Int(cg.asciiToAppleCharIndex(ascii: character))], + pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum)) } CVPixelBufferUnlockBaseAddress(emulatorViewDelegate.pixels!, CVPixelBufferLockFlags(rawValue: 0)) emulatorView.setNeedsDisplay(emulatorView.frame) - emulatorView.display() + } } diff --git a/FruitMachine/AppleI/AppleIBitmapDisplay.swift b/FruitMachine/AppleI/AppleIBitmapDisplay.swift index 59d77b1..a10277f 100644 --- a/FruitMachine/AppleI/AppleIBitmapDisplay.swift +++ b/FruitMachine/AppleI/AppleIBitmapDisplay.swift @@ -40,17 +40,18 @@ class AppleIBitmapDisplay: NSObject, CALayerDelegate { } } - func putCharacterPixels(buffer: UnsafeMutablePointer?, charPixels: [UInt8], pixelPosition: CGPoint) { + func putGlyph(buffer: UnsafeMutablePointer?, glyph: Glyph, pixelPosition: CGPoint) { //You better have locked the buffer before getting here... //Calculate the offset to reach the desired position. let baseOffset = scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x) for charY in 0.. 0 ? BitmapPixelsBE555.ARGBWhite : BitmapPixelsBE555.ARGBBlack + buffer![offset + 7 - charX] = glyph.pixels[glyphOffsetY + charX] } } } diff --git a/FruitMachine/AppleI/Video/BitmapPixels.swift b/FruitMachine/AppleI/Video/BitmapPixels.swift index 8f4ea50..0c267ca 100644 --- a/FruitMachine/AppleI/Video/BitmapPixels.swift +++ b/FruitMachine/AppleI/Video/BitmapPixels.swift @@ -18,8 +18,8 @@ class BitmapPixels: NSObject { static let bitsPerPixel: UInt = 8 static let colorSpace = CGColorSpaceCreateDeviceRGB() - static let ColorBlack = PixelData(data: 0b11000000) - static let ColorWhite = PixelData(data: 0b11111111) + static let Black = PixelData(data: 0b11000000) + static let White = PixelData(data: 0b11111111) } class BitmapPixelsARGB32 : NSObject { @@ -34,8 +34,8 @@ class BitmapPixelsARGB32 : NSObject { static let bitsPerPixel: UInt = 32 static let colorSpace = CGColorSpaceCreateDeviceRGB() - static let ARGBWhite = PixelData(a: 255, r: 200, g: 200, b: 200) - static let ARGBBlack = PixelData(a: 255, r: 0, g: 0, b: 0) + static let White = PixelData(a: 255, r: 200, g: 200, b: 200) + static let Black = PixelData(a: 255, r: 0, g: 0, b: 0) } class BitmapPixelsBE555 : NSObject { @@ -47,6 +47,6 @@ class BitmapPixelsBE555 : NSObject { static let bitsPerPixel: UInt = 16 static let colorSpace = CGColorSpaceCreateDeviceRGB() - static let ARGBWhite = PixelData(data: 0b1111111101111111) - static let ARGBBlack = PixelData(data: 0b0000000000000000) + static let White = PixelData(data: 0b1111111101111111) + static let Black = PixelData(data: 0b0000000000000000) } diff --git a/FruitMachine/AppleI/Video/CharacterGenerator.swift b/FruitMachine/AppleI/Video/CharacterGenerator.swift index 095d087..1618bcd 100644 --- a/FruitMachine/AppleI/Video/CharacterGenerator.swift +++ b/FruitMachine/AppleI/Video/CharacterGenerator.swift @@ -10,20 +10,34 @@ import Cocoa //The character generator ROM contains 64 8x5 glyphs. +struct Glyph { + var pixels: [BitmapPixelsBE555.PixelData] = [BitmapPixelsBE555.PixelData]() + + init(inPixels: [BitmapPixelsBE555.PixelData]) { + pixels = inPixels + } +} + class CharacterGenerator: NSObject { static let CHAR_WIDTH = 5 static let CHAR_HEIGHT = 8 var ROM: [UInt8] + var glyphs: [Glyph] init(romPath: String) { ROM = [UInt8](repeating: 0xCC, count: 512) + glyphs = [Glyph](repeating: Glyph(inPixels: [BitmapPixelsBE555.PixelData]()), count: 64) super.init() loadROM(path: romPath) + + for index in 0..<64 { + glyphs[index] = Glyph(inPixels: getCharacterPixels(charIndex: UInt8(index))) + } } - func loadROM(path: String) { + private func loadROM(path: String) { do { let fileContent: NSData = try NSData(contentsOfFile: path) fileContent.getBytes(&ROM, range: NSRange(location: 0, length: 512)) @@ -32,19 +46,30 @@ class CharacterGenerator: NSObject { } } - func getCharacterPixels(charIndex: UInt8) -> [UInt8] { + private func getCharacterPixels(charIndex: UInt8) -> [BitmapPixelsBE555.PixelData] { var pixelArray = [UInt8](repeating: 0x00, count: CharacterGenerator.CHAR_HEIGHT) /* Instead of ignoring ASCII bit b6, we ignore bit b5. At the same time ASCII bit b6 must be inverted before it is fed to the character ROM. This way the entire character range from $40 to $7F will end up in the range $00 to $1F (twice of course). Now lower case characters are automatically translated into their corresponding upper case bit maps. */ - - let convertedCharIndex = (charIndex & 0x1f) | (((charIndex ^ 0x40) & 0x40) >> 1) + //Don't convert the character indexes if we're populating the glyphs array. for scanlineIndex in 0.. 0 ? BitmapPixelsBE555.White : BitmapPixelsBE555.Black) + } + } + + return glyphPixels + } + + func asciiToAppleCharIndex(ascii: UInt8) -> UInt8 { + return (ascii & 0x1f) | (((ascii ^ 0x40) & 0x40) >> 1) } } diff --git a/FruitMachine/M6502/CPU.swift b/FruitMachine/M6502/CPU.swift index b6f55c8..0539f42 100644 --- a/FruitMachine/M6502/CPU.swift +++ b/FruitMachine/M6502/CPU.swift @@ -111,7 +111,23 @@ struct StatusRegister { } } -class CPU: NSObject { +final class CPU: NSObject { + enum AddressingMode { + case accumulator + case immediate + case implied + case relative + case absolute + case zeropage + case indirect + case absolute_indexed_x + case absolute_indexed_y + case zeropage_indexed_x + case zeropage_indexed_y + case indexed_indirect + case indirect_indexed + } + let NMI_VECTOR: UInt16 = 0xFFFA let RESET_VECTOR: UInt16 = 0xFFFC let IRQ_VECTOR: UInt16 = 0xFFFE @@ -196,7 +212,7 @@ class CPU: NSObject { } - func executeNextInstruction() throws { + final func executeNextInstruction() throws { instruction_register = memoryInterface.readByte(offset: program_counter) let operation = InstructionTable[instruction_register] if(operation == nil) { @@ -241,7 +257,7 @@ class CPU: NSObject { } /* Running */ - func cpuStep() { + final func cpuStep() { do { try executeNextInstruction() } catch CPUExceptions.invalidInstruction { @@ -252,11 +268,9 @@ class CPU: NSObject { } func runCyclesBatch() { - let startTime = CFAbsoluteTimeGetCurrent() - isRunning = true - while(!outOfCycles() && isRunning) { + while(!outOfCycles()) { cpuStep() if (breakpoints.contains(program_counter)) { @@ -264,9 +278,6 @@ class CPU: NSObject { } } - - let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime - print("Time elapsed for runFrame: \(timeElapsed) s.") } } diff --git a/FruitMachine/M6502/Debugger/DebuggerViewController.swift b/FruitMachine/M6502/Debugger/DebuggerViewController.swift index 19dfdf1..19215d7 100644 --- a/FruitMachine/M6502/Debugger/DebuggerViewController.swift +++ b/FruitMachine/M6502/Debugger/DebuggerViewController.swift @@ -26,7 +26,7 @@ class DebuggerViewController: NSViewController { var disassembly: [Disassembly] = [Disassembly]() - func highlightCurrentInstruction() -> Bool { + @discardableResult func highlightCurrentInstruction() -> Bool { for (index, instruction) in disassembly.enumerated() { if(instruction.address == cpuInstance.program_counter) { debuggerTableView.selectRowIndexes(NSIndexSet(index: index) as IndexSet, byExtendingSelection: false) diff --git a/FruitMachine/M6502/Memory/MemoryInterface.swift b/FruitMachine/M6502/Memory/MemoryInterface.swift index c0fe351..ec2a2ac 100644 --- a/FruitMachine/M6502/Memory/MemoryInterface.swift +++ b/FruitMachine/M6502/Memory/MemoryInterface.swift @@ -8,7 +8,7 @@ import Cocoa -class MemoryInterface: NSObject { +final class MemoryInterface: NSObject { fileprivate var memory: [UInt8] @@ -43,7 +43,7 @@ class MemoryInterface: NSObject { if(!bypassOverrides) { for override in write_overrides { if case override.rangeStart ... override.rangeEnd = offset { - override.action(CPU.sharedInstance, value) + _ = override.action(CPU.sharedInstance, value) if(!override.doWrite) { return } diff --git a/FruitMachine/M6502/Memory/ReadOverride.swift b/FruitMachine/M6502/Memory/ReadOverride.swift index 175da3d..845d19e 100644 --- a/FruitMachine/M6502/Memory/ReadOverride.swift +++ b/FruitMachine/M6502/Memory/ReadOverride.swift @@ -11,7 +11,7 @@ import Cocoa /* A ReadOverride is special behavior that occurs when a memory address is read. Memory-mapped registers, peripherals, etc. */ -class ReadOverride: MemoryOverride { +final class ReadOverride: MemoryOverride { let doRead: Bool //do we write anyway? init(start: UInt16, end: UInt16, readAnyway: Bool, action: @escaping (AnyObject, UInt8?) -> UInt8?) { diff --git a/FruitMachine/M6502/Memory/WriteOverride.swift b/FruitMachine/M6502/Memory/WriteOverride.swift index f1b62a0..d021fb9 100644 --- a/FruitMachine/M6502/Memory/WriteOverride.swift +++ b/FruitMachine/M6502/Memory/WriteOverride.swift @@ -11,7 +11,7 @@ import Cocoa /* A ReadOverride is special behavior that occurs when a memory address is written. Memory-mapped registers, peripherals, etc. */ -class WriteOverride: MemoryOverride { +final class WriteOverride: MemoryOverride { let doWrite: Bool //do we write anyway? init(start: UInt16, end: UInt16, writeAnyway: Bool, action: @escaping (AnyObject, UInt8?) -> UInt8?) { diff --git a/FruitMachine/M6502/Opcodes/CPUInstructions.swift b/FruitMachine/M6502/Opcodes/CPUInstructions.swift index fac6cde..2392eaf 100644 --- a/FruitMachine/M6502/Opcodes/CPUInstructions.swift +++ b/FruitMachine/M6502/Opcodes/CPUInstructions.swift @@ -8,31 +8,15 @@ import Cocoa -enum AddressingMode { - case accumulator - case immediate - case implied - case relative - case absolute - case zeropage - case indirect - case absolute_indexed_x - case absolute_indexed_y - case zeropage_indexed_x - case zeropage_indexed_y - case indexed_indirect - case indirect_indexed -} - -class CPUInstruction: NSObject { +final class CPUInstruction: NSObject { let mnemonic: String //The mnemonic for this instruction. let cycles: Int //How many cycles does this instruction take? let bytes: Int //How many bytes long is this instruction? - let addressingMode: AddressingMode //The addressing mode of this instruction. + let addressingMode: CPU.AddressingMode //The addressing mode of this instruction. - let action: (CPU, AddressingMode) -> Void //A closure that describes this function's action. + let action: (CPU, CPU.AddressingMode) -> Void //A closure that describes this function's action. - init(mnemonic: String, cycles: Int, bytes: Int, addressingMode: AddressingMode, action: @escaping (CPU, AddressingMode) -> Void) { + init(mnemonic: String, cycles: Int, bytes: Int, addressingMode: CPU.AddressingMode, action: @escaping (CPU, CPU.AddressingMode) -> Void) { self.mnemonic = mnemonic self.cycles = cycles self.bytes = bytes diff --git a/FruitMachine/M6502/Opcodes/Opcodes.swift b/FruitMachine/M6502/Opcodes/Opcodes.swift index ea4586b..ed57541 100644 --- a/FruitMachine/M6502/Opcodes/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes/Opcodes.swift @@ -10,24 +10,24 @@ import Cocoa extension CPU { - func popByte() -> UInt8 { + fileprivate func popByte() -> UInt8 { stack_pointer = stack_pointer &+ 1 return memoryInterface.readByte(offset: stackPointerAsUInt16()) } - func popWord() -> UInt16 { + fileprivate func popWord() -> UInt16 { let low = popByte() let high = popByte() return (UInt16(high) << 8) | UInt16(low) } - func pushByte(data: UInt8) -> Void { + fileprivate func pushByte(data: UInt8) -> Void { memoryInterface.writeByte(offset: stackPointerAsUInt16(), value: data) stack_pointer = stack_pointer &- 1 } - func pushWord(data: UInt16) -> Void { + fileprivate func pushWord(data: UInt16) -> Void { let low = UInt8(data & 0x00FF) let high = UInt8((data & 0xFF00) >> 8) @@ -35,11 +35,11 @@ extension CPU { pushByte(data: low) } - func stackPointerAsUInt16() -> UInt16 { + fileprivate func stackPointerAsUInt16() -> UInt16 { return 0x0100 | UInt16(stack_pointer); } - func doBranch() { + fileprivate func doBranch() { let distance = Int8(bitPattern: getOperandByte()) if(distance < 0) { @@ -67,7 +67,7 @@ extension CPU { } } -func getOperandByteForAddressingMode(state: CPU, mode: AddressingMode) -> UInt8 { +private func getOperandByteForAddressingMode(state: CPU, mode: CPU.AddressingMode) -> UInt8 { switch (mode) { case .immediate: @@ -81,52 +81,46 @@ func getOperandByteForAddressingMode(state: CPU, mode: AddressingMode) -> UInt8 return state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() &+ state.index_y) & 0x00FF) case .absolute: - let word: UInt16 = state.getOperandWord() - return state.memoryInterface.readByte(offset: word) + return state.memoryInterface.readByte(offset: state.getOperandWord()) case .absolute_indexed_x: return state.memoryInterface.readByte(offset: state.getOperandWord() &+ UInt16(state.index_x)) case .absolute_indexed_y: return state.memoryInterface.readByte(offset: state.getOperandWord() &+ UInt16(state.index_y)) case .indexed_indirect: - let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.program_counter + 1)) - //read from (ZP) - let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp &+ state.index_x)) - return state.memoryInterface.readByte(offset: pointer) + return state.memoryInterface.readByte(offset: state.memoryInterface.readWord(offset: UInt16(state.memoryInterface.readByte(offset: UInt16(state.program_counter + 1)) &+ state.index_x))) case .indirect_indexed: - let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.program_counter + 1)) - let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp)) &+ UInt16(state.index_y) - return state.memoryInterface.readByte(offset: pointer) + return state.memoryInterface.readByte(offset: state.memoryInterface.readWord(offset: UInt16(state.memoryInterface.readByte(offset: UInt16(state.program_counter + 1)))) &+ UInt16(state.index_y)) default: print("Called getOperand: UInt8 on an instruction that expects a UInt16.") return 0 } } -func getOperandAddressForAddressingMode(state: CPU, mode: AddressingMode) -> UInt16 { +private func getOperandAddressForAddressingMode(state: CPU, mode: CPU.AddressingMode) -> UInt16 { //Function that will provide a 16-bit operand to instructions. //All instructions have 2 data bytes, little-endian. switch(mode) { case .zeropage: - return UInt16(0x0000 + (state.memoryInterface.readByte(offset: state.program_counter + 1))) + return UInt16(0x0000 &+ (state.memoryInterface.readByte(offset: state.program_counter &+ 1))) case .zeropage_indexed_x: - return UInt16(0x0000 + (state.memoryInterface.readByte(offset: state.program_counter + 1) &+ state.index_x)) + return UInt16(0x0000 &+ (state.memoryInterface.readByte(offset: state.program_counter &+ 1) &+ state.index_x)) case .zeropage_indexed_y: - return UInt16(0x0000 + (state.memoryInterface.readByte(offset: state.program_counter + 1) &+ state.index_y)) + return UInt16(0x0000 &+ (state.memoryInterface.readByte(offset: state.program_counter &+ 1) &+ state.index_y)) case .absolute: return state.getOperandWord() case .absolute_indexed_x: - return state.getOperandWord() + state.index_x + return state.getOperandWord() &+ UInt16(state.index_x) case .absolute_indexed_y: - return state.getOperandWord() + state.index_y + return state.getOperandWord() &+ UInt16(state.index_y) case .indexed_indirect: - let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.program_counter + 1)) + let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.program_counter &+ 1)) //read from (ZP) let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp &+ state.index_x)) return pointer case .indirect_indexed: - let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.program_counter + 1)) + let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.program_counter &+ 1)) let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp)) &+ UInt16(state.index_y) return pointer case .indirect: @@ -137,7 +131,7 @@ func getOperandAddressForAddressingMode(state: CPU, mode: AddressingMode) -> UIn } } -func hex2bcd(hex: UInt8) -> UInt8 { +fileprivate func hex2bcd(hex: UInt8) -> UInt8 { var y: UInt8 = (hex / 10) << 4 y = y | (hex % 10) return y @@ -145,7 +139,7 @@ func hex2bcd(hex: UInt8) -> UInt8 { /* */ -class Opcodes: NSObject { +final class Opcodes: NSObject { static func _Add(state: CPU, operand: UInt8, isSubtract: Bool) { if(state.accumulator == 0xFF) { @@ -167,11 +161,11 @@ class Opcodes: NSObject { state.accumulator = t8 } - static func ADC(state: CPU, addressingMode: AddressingMode) -> Void { + static func ADC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { _Add(state: state, operand: UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode)), isSubtract: false) } - static func SBC(state: CPU, addressingMode: AddressingMode) -> Void { + static func SBC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode)) var t16: UInt16 = UInt16(state.accumulator &- operand) &- UInt16((state.status_register.carry ? UInt8(0) : UInt8(1))) let t8: UInt8 = UInt8(t16 & 0xFF) @@ -190,100 +184,100 @@ class Opcodes: NSObject { state.updateNegativeFlag(value: t8) } - static func LDA(state: CPU, addressingMode: AddressingMode) -> Void { + static func LDA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.accumulator = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator) } - static func LDX(state: CPU, addressingMode: AddressingMode) -> Void { + static func LDX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_x = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.index_x) state.updateNegativeFlag(value: state.index_x) } - static func LDY(state: CPU, addressingMode: AddressingMode) -> Void { + static func LDY(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_y = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.index_y) state.updateNegativeFlag(value: state.index_y) } - static func STA(state: CPU, addressingMode: AddressingMode) -> Void { + static func STA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let address: UInt16 = getOperandAddressForAddressingMode(state: state, mode: addressingMode) state.memoryInterface.writeByte(offset: address, value: state.accumulator) } - static func STX(state: CPU, addressingMode: AddressingMode) -> Void { + static func STX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let address: UInt16 = getOperandAddressForAddressingMode(state: state, mode: addressingMode) state.memoryInterface.writeByte(offset: address, value: state.index_x) } - static func STY(state: CPU, addressingMode: AddressingMode) -> Void { + static func STY(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let address: UInt16 = getOperandAddressForAddressingMode(state: state, mode: addressingMode) state.memoryInterface.writeByte(offset: address, value: state.index_y) } //Register instructions - static func TAX(state: CPU, addressingMode: AddressingMode) -> Void { + static func TAX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_x = state.accumulator state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func TXA(state: CPU, addressingMode: AddressingMode) -> Void { + static func TXA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.accumulator = state.index_x state.updateZeroFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator); } - static func DEX(state: CPU, addressingMode: AddressingMode) -> Void { + static func DEX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_x = state.index_x &- 1 state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func INX(state: CPU, addressingMode: AddressingMode) -> Void { + static func INX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_x = state.index_x &+ 1 state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func TAY(state: CPU, addressingMode: AddressingMode) -> Void { + static func TAY(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_y = state.accumulator state.updateZeroFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y); } - static func TYA(state: CPU, addressingMode: AddressingMode) -> Void { + static func TYA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.accumulator = state.index_y state.updateZeroFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator); } - static func DEY(state: CPU, addressingMode: AddressingMode) -> Void { + static func DEY(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_y = state.index_y &- 1 state.updateZeroFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y); } - static func INY(state: CPU, addressingMode: AddressingMode) -> Void { + static func INY(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_y = state.index_y &+ 1 state.updateZeroFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y); } - static func INC(state: CPU, addressingMode: AddressingMode) -> Void { + static func INC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let address: UInt16 = getOperandAddressForAddressingMode(state: state, mode: addressingMode) var val: UInt8 = state.memoryInterface.readByte(offset: address) @@ -294,7 +288,7 @@ class Opcodes: NSObject { state.updateNegativeFlag(value: val); } - static func DEC(state: CPU, addressingMode: AddressingMode) -> Void { + static func DEC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let address: UInt16 = getOperandAddressForAddressingMode(state: state, mode: addressingMode) var val: UInt8 = state.memoryInterface.readByte(offset: address) @@ -306,7 +300,7 @@ class Opcodes: NSObject { } //CMP - static func CMP(state: CPU, addressingMode: AddressingMode) -> Void { + static func CMP(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let mem = getOperandByteForAddressingMode(state: state, mode: addressingMode) let t = state.accumulator &- mem //CMP is a subtract that doesn't affect memory @@ -315,7 +309,7 @@ class Opcodes: NSObject { state.status_register.carry = (state.accumulator >= mem) } - static func CPX(state: CPU, addressingMode: AddressingMode) -> Void { + static func CPX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let mem = getOperandByteForAddressingMode(state: state, mode: addressingMode) let t = state.index_x &- mem //CMP is a subtract that doesn't affect memory @@ -324,7 +318,7 @@ class Opcodes: NSObject { state.status_register.carry = (state.index_x >= mem) } - static func CPY(state: CPU, addressingMode: AddressingMode) -> Void { + static func CPY(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let mem = getOperandByteForAddressingMode(state: state, mode: addressingMode) let t = state.index_y &- mem //CMP is a subtract that doesn't affect memory @@ -334,21 +328,21 @@ class Opcodes: NSObject { } //Boolean operators - static func EOR(state: CPU, addressingMode: AddressingMode) -> Void { + static func EOR(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.accumulator = state.accumulator ^ getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator) } - static func AND(state: CPU, addressingMode: AddressingMode) -> Void { + static func AND(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.accumulator = state.accumulator & getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator) } - static func ORA(state: CPU, addressingMode: AddressingMode) -> Void { + static func ORA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.accumulator = state.accumulator | getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) @@ -356,7 +350,7 @@ class Opcodes: NSObject { } //Bitwise operators - static func BIT(state: CPU, addressingMode: AddressingMode) -> Void { + static func BIT(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let operand = getOperandByteForAddressingMode(state: state, mode: addressingMode) let data = state.accumulator & operand @@ -365,7 +359,7 @@ class Opcodes: NSObject { state.status_register.overflow = (operand & UInt8(0x40)) == 0x40 } - static func ASL(state: CPU, addressingMode: AddressingMode) -> Void { + static func ASL(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .accumulator) { @@ -387,7 +381,7 @@ class Opcodes: NSObject { } } - static func LSR(state: CPU, addressingMode: AddressingMode) -> Void { + static func LSR(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .accumulator) { @@ -411,7 +405,7 @@ class Opcodes: NSObject { } } - static func ROL(state: CPU, addressingMode: AddressingMode) -> Void { + static func ROL(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .accumulator) { @@ -440,7 +434,7 @@ class Opcodes: NSObject { } } - static func ROR(state: CPU, addressingMode: AddressingMode) -> Void { + static func ROR(state: CPU, addressingMode: CPU.AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .accumulator) { @@ -470,51 +464,51 @@ class Opcodes: NSObject { } //Processor flag instructions - static func CLC(state: CPU, addressingMode: AddressingMode) -> Void { + static func CLC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.carry = false } - static func SEC(state: CPU, addressingMode: AddressingMode) -> Void { + static func SEC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.carry = true } - static func CLI(state: CPU, addressingMode: AddressingMode) -> Void { + static func CLI(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.irq_disable = false } - static func SEI(state: CPU, addressingMode: AddressingMode) -> Void { + static func SEI(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.irq_disable = true } - static func CLV(state: CPU, addressingMode: AddressingMode) -> Void { + static func CLV(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.overflow = false } - static func CLD(state: CPU, addressingMode: AddressingMode) -> Void { + static func CLD(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.decimal = false } - static func SED(state: CPU, addressingMode: AddressingMode) -> Void { + static func SED(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.decimal = true } //Stack instructions - static func TXS(state: CPU, addressingMode: AddressingMode) -> Void { + static func TXS(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.stack_pointer = state.index_x } - static func TSX(state: CPU, addressingMode: AddressingMode) -> Void { + static func TSX(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.index_x = state.stack_pointer state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func PHA(state: CPU, addressingMode: AddressingMode) -> Void { + static func PHA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.pushByte(data: state.accumulator) } - static func PLA(state: CPU, addressingMode: AddressingMode) -> Void { + static func PLA(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.stack_pointer = state.stack_pointer &+ 1 state.accumulator = state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()) @@ -522,7 +516,7 @@ class Opcodes: NSObject { state.updateNegativeFlag(value: state.accumulator); } - static func PHP(state: CPU, addressingMode: AddressingMode) -> Void { + static func PHP(state: CPU, addressingMode: CPU.AddressingMode) -> Void { var sr = state.status_register sr.brk = true //PHP pushes B as true @@ -530,81 +524,81 @@ class Opcodes: NSObject { state.stack_pointer = state.stack_pointer &- 1 } - static func PLP(state: CPU, addressingMode: AddressingMode) -> Void { + static func PLP(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.stack_pointer = state.stack_pointer &+ 1 state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16())) state.status_register.brk = false //PLP sets B to 0 } - static func BPL(state: CPU, addressingMode: AddressingMode) -> Void { + static func BPL(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(!state.status_register.negative) { state.doBranch() } } - static func BMI(state: CPU, addressingMode: AddressingMode) -> Void { + static func BMI(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(state.status_register.negative) { state.doBranch() } } - static func BVC(state: CPU, addressingMode: AddressingMode) -> Void { + static func BVC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(!state.status_register.overflow) { state.doBranch() } } - static func BVS(state: CPU, addressingMode: AddressingMode) -> Void { + static func BVS(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(state.status_register.overflow) { state.doBranch() } } - static func BCC(state: CPU, addressingMode: AddressingMode) -> Void { + static func BCC(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(!state.status_register.carry) { state.doBranch() } } - static func BCS(state: CPU, addressingMode: AddressingMode) -> Void { + static func BCS(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(state.status_register.carry) { state.doBranch() } } - static func BNE(state: CPU, addressingMode: AddressingMode) -> Void { + static func BNE(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(!state.status_register.zero) { state.doBranch() } } - static func BEQ(state: CPU, addressingMode: AddressingMode) -> Void { + static func BEQ(state: CPU, addressingMode: CPU.AddressingMode) -> Void { if(state.status_register.zero) { state.doBranch() } } //Misc - static func JMP(state: CPU, addressingMode: AddressingMode) -> Void { + static func JMP(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.program_counter = getOperandAddressForAddressingMode(state: state, mode: addressingMode) - 3 } - static func JSR(state: CPU, addressingMode: AddressingMode) -> Void { + static func JSR(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.pushWord(data: state.program_counter + 2) state.program_counter = state.getOperandWord() - 3 } - static func RTS(state: CPU, addressingMode: AddressingMode) -> Void { + static func RTS(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.program_counter = state.popWord() } - static func RTI(state: CPU, addressingMode: AddressingMode) -> Void { + static func RTI(state: CPU, addressingMode: CPU.AddressingMode) -> Void { state.status_register.fromByte(state: state.popByte()) state.program_counter = state.popWord() - 1 state.status_register.brk = false //RTI sets B to 0 } - static func BRK(state: CPU, addressingMode: AddressingMode) -> Void { + static func BRK(state: CPU, addressingMode: CPU.AddressingMode) -> Void { var sr = state.status_register sr.brk = true //BRK pushes B as true state.pushWord(data: state.program_counter + 2) @@ -613,5 +607,5 @@ class Opcodes: NSObject { state.program_counter = state.memoryInterface.readWord(offset: 0xFFFE) - 1 } - static func NOP(state: CPU, addressingMode: AddressingMode) -> Void {} + static func NOP(state: CPU, addressingMode: CPU.AddressingMode) -> Void {} }