optimizations, refactoring, cleanup, fixing warnings, all kinds of stuff

This commit is contained in:
Luigi Thirty 2017-07-31 21:35:34 -04:00
parent 45e5c3c658
commit 3bb4eed9d1
12 changed files with 159 additions and 136 deletions

View File

@ -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;

View File

@ -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()
}
}

View File

@ -40,17 +40,18 @@ class AppleIBitmapDisplay: NSObject, CALayerDelegate {
}
}
func putCharacterPixels(buffer: UnsafeMutablePointer<BitmapPixelsBE555.PixelData>?, charPixels: [UInt8], pixelPosition: CGPoint) {
func putGlyph(buffer: UnsafeMutablePointer<BitmapPixelsBE555.PixelData>?, 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..<CharacterGenerator.CHAR_HEIGHT {
let offsetY = AppleIBitmapDisplay.PIXEL_WIDTH * charY
let offset = baseOffset + AppleIBitmapDisplay.PIXEL_WIDTH * charY
let glyphOffsetY = (charY * 8)
for charX in 0..<8 {
buffer![baseOffset + offsetY + 7 - charX] = (charPixels[charY] & UInt8(1 << charX)) > 0 ? BitmapPixelsBE555.ARGBWhite : BitmapPixelsBE555.ARGBBlack
buffer![offset + 7 - charX] = glyph.pixels[glyphOffsetY + charX]
}
}
}

View File

@ -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)
}

View File

@ -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..<CharacterGenerator.CHAR_HEIGHT {
pixelArray[scanlineIndex] = ROM[scanlineIndex + (Int(convertedCharIndex) * CharacterGenerator.CHAR_HEIGHT)]
pixelArray[scanlineIndex] = ROM[scanlineIndex + (Int(charIndex) * CharacterGenerator.CHAR_HEIGHT)]
}
return pixelArray
var glyphPixels = [BitmapPixelsBE555.PixelData]()
for charY in 0..<CharacterGenerator.CHAR_HEIGHT {
for charX in 0..<8 {
glyphPixels.append(pixelArray[Int(charY)] & (1 << charX) > 0 ? BitmapPixelsBE555.White : BitmapPixelsBE555.Black)
}
}
return glyphPixels
}
func asciiToAppleCharIndex(ascii: UInt8) -> UInt8 {
return (ascii & 0x1f) | (((ascii ^ 0x40) & 0x40) >> 1)
}
}

View File

@ -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.")
}
}

View File

@ -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)

View File

@ -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
}

View File

@ -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?) {

View File

@ -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?) {

View File

@ -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

View File

@ -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 {}
}