diff --git a/FruitMachine/AppleI/AppleI.swift b/FruitMachine/AppleI/AppleI.swift index 9ce61cb..550916d 100644 --- a/FruitMachine/AppleI/AppleI.swift +++ b/FruitMachine/AppleI/AppleI.swift @@ -23,7 +23,7 @@ class AppleI: NSObject { ] let emulatorViewDelegate = AppleScreenViewDelegate() - let emulatorView = AppleScreenView(frame: NSMakeRect(0, 0, 400, 384)) + let emulatorView = AppleScreenView(frame: NSMakeRect(0, 0, 640, 384)) let emuScreenLayer = CALayer() static let CPU_FREQUENCY = 1000000 @@ -49,7 +49,8 @@ class AppleI: NSObject { emulatorViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: character), pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum)) } - CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/apple1.rom", offset: 0xFF00) + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/apple1.rom", offset: 0xFF00, length: 0x100) + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/basic.bin", offset: 0xE000, length: 0x1000) CPU.sharedInstance.performReset() } diff --git a/FruitMachine/AppleI/AppleScreenViewDelegate.swift b/FruitMachine/AppleI/AppleScreenViewDelegate.swift index 1fe57d5..e11eaec 100644 --- a/FruitMachine/AppleI/AppleScreenViewDelegate.swift +++ b/FruitMachine/AppleI/AppleScreenViewDelegate.swift @@ -9,8 +9,8 @@ import Cocoa class AppleScreenViewDelegate: NSObject, CALayerDelegate { - let PIXEL_WIDTH = 200 - let PIXEL_HEIGHT = 192 + static let PIXEL_WIDTH = 320 + static let PIXEL_HEIGHT = 192 /* Pixel data stuff. */ struct PixelData { @@ -19,6 +19,7 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate { var g: UInt8 var b: UInt8 } + let bitsPerComponent: UInt = 8 let bitsPerPixel: UInt = 32 let colorSpace = CGColorSpaceCreateDeviceRGB() @@ -28,17 +29,17 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate { var indexedPixels: [UInt8] var colorValues: [PixelData] + var rgbPixels = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: AppleScreenViewDelegate.PIXEL_WIDTH*AppleScreenViewDelegate.PIXEL_HEIGHT) + override init() { - indexedPixels = [UInt8](repeating: 0x00, count: 200*192) + indexedPixels = [UInt8](repeating: 0x00, count: AppleScreenViewDelegate.PIXEL_WIDTH*AppleScreenViewDelegate.PIXEL_HEIGHT) colorValues = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: 256) colorValues[1] = PixelData(a: 0, r: 200, g: 200, b: 200 ) } func convertIndexedPixelsToRGB(pixels: [UInt8]) -> [PixelData] { - var rgbPixels = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: 200*192) - for (num, colorIndex) in pixels.enumerated() { rgbPixels[num] = colorValues[Int(colorIndex)] } @@ -48,17 +49,18 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate { func putCharacterPixels(charPixels: [UInt8], pixelPosition: CGPoint) { //Calculate the offset to reach the desired position. - let baseOffset = (Int(pixelPosition.y) * PIXEL_WIDTH) + Int(pixelPosition.x) + let baseOffset = (Int(pixelPosition.y) * AppleScreenViewDelegate.PIXEL_WIDTH) + Int(pixelPosition.x) for charY in 0.. 0 ? 1 : 0 + //for charX in 0.. 0 ? 1 : 0 } } } func getPixelOffset(charCellX: Int, charCellY: Int) -> CGPoint { - return CGPoint(x: charCellX * 5, y: charCellY * 8) + return CGPoint(x: charCellX * 8, y: charCellY * 8) } func getPixelOffset(charCellIndex: Int) -> CGPoint { @@ -68,12 +70,21 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate { /* Draw the screen. */ func draw(_ layer: CALayer, in ctx: CGContext) { let bounds = layer.bounds - ctx.interpolationQuality = CGInterpolationQuality.none var pixels = convertIndexedPixelsToRGB(pixels: indexedPixels) let pixelProvider = CGDataProvider(data: NSData(bytes: &pixels, length: pixels.count * MemoryLayout.size)) - let renderedImage = CGImage(width: PIXEL_WIDTH, height: PIXEL_HEIGHT, bitsPerComponent: Int(bitsPerComponent), bitsPerPixel: Int(bitsPerPixel), bytesPerRow: PIXEL_WIDTH * Int(MemoryLayout.size), space: colorSpace, bitmapInfo: bitmapInfo, provider: pixelProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent) + let renderedImage = CGImage(width: AppleScreenViewDelegate.PIXEL_WIDTH, + height: AppleScreenViewDelegate.PIXEL_HEIGHT, + bitsPerComponent: Int(bitsPerComponent), + bitsPerPixel: Int(bitsPerPixel), + bytesPerRow: AppleScreenViewDelegate.PIXEL_WIDTH * Int(MemoryLayout.size), + space: colorSpace, + bitmapInfo: bitmapInfo, + provider: pixelProvider!, + decode: nil, + shouldInterpolate: false, + intent: CGColorRenderingIntent.defaultIntent) ctx.draw(renderedImage!, in: bounds) } diff --git a/FruitMachine/AppleI/Video/Terminal.swift b/FruitMachine/AppleI/Video/Terminal.swift index 65ed308..a5de04c 100644 --- a/FruitMachine/AppleI/Video/Terminal.swift +++ b/FruitMachine/AppleI/Video/Terminal.swift @@ -16,6 +16,7 @@ struct Cell { class Terminal: NSObject { static let CELLS_WIDTH = 40 static let CELLS_HEIGHT = 24 + static let CELLS_COUNT = CELLS_WIDTH * CELLS_HEIGHT var cursorPosition: Cell var characters: [UInt8] @@ -45,8 +46,9 @@ class Terminal: NSObject { if(cursorPosition.x == Terminal.CELLS_WIDTH) { cursorPosition.x = 0 cursorPosition.y += 1 - if(cursorPosition.y == Terminal.CELLS_HEIGHT) { - cursorPosition.y = 0 //TODO: scrolling + if(cursorPosition.y >= Terminal.CELLS_HEIGHT) { + cursorPosition.y = Terminal.CELLS_HEIGHT - 1 + scrollUp(lines: 1) } } } @@ -54,8 +56,15 @@ class Terminal: NSObject { func carriageReturn() { cursorPosition.x = 0 cursorPosition.y += 1 - if(cursorPosition.y == Terminal.CELLS_HEIGHT) { - cursorPosition.y = 0 + if(cursorPosition.y >= Terminal.CELLS_HEIGHT) { + cursorPosition.y = Terminal.CELLS_HEIGHT - 1 + scrollUp(lines: 1) } } + + func scrollUp(lines: Int) { + let scrolled = characters[Terminal.CELLS_WIDTH ..< Terminal.CELLS_COUNT] + characters = [UInt8](scrolled) + characters.append(contentsOf: [UInt8](repeating: 0x00, count: Terminal.CELLS_WIDTH)) + } } diff --git a/FruitMachine/FruitMachine.storyboard b/FruitMachine/FruitMachine.storyboard index 4668927..187096c 100644 --- a/FruitMachine/FruitMachine.storyboard +++ b/FruitMachine/FruitMachine.storyboard @@ -698,7 +698,7 @@ - + @@ -717,7 +717,7 @@ - + diff --git a/FruitMachine/M6502/Debugger/DebuggerViewController.swift b/FruitMachine/M6502/Debugger/DebuggerViewController.swift index 191f2c4..19dfdf1 100644 --- a/FruitMachine/M6502/Debugger/DebuggerViewController.swift +++ b/FruitMachine/M6502/Debugger/DebuggerViewController.swift @@ -47,6 +47,7 @@ class DebuggerViewController: NSViewController { text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString()) disassembly = cpuInstance.disassemble(fromAddress: CPU.sharedInstance.program_counter, length: 256) + debuggerTableView.reloadData() highlightCurrentInstruction() } diff --git a/FruitMachine/M6502/Memory/MemoryInterface.swift b/FruitMachine/M6502/Memory/MemoryInterface.swift index 0ca2f5f..c0fe351 100644 --- a/FruitMachine/M6502/Memory/MemoryInterface.swift +++ b/FruitMachine/M6502/Memory/MemoryInterface.swift @@ -60,10 +60,10 @@ class MemoryInterface: NSObject { return (UInt16(high) << 8) | UInt16(low) } - func loadBinary(path: String, offset: UInt16) { + func loadBinary(path: String, offset: UInt16, length: Int) { do { let fileContent: NSData = try NSData(contentsOfFile: path) - fileContent.getBytes(&memory[Int(offset)], range: NSRange(location: 0, length: 256)) + fileContent.getBytes(&memory[Int(offset)], range: NSRange(location: 0, length: length)) } catch { print(error) } diff --git a/FruitMachine/M6502/Opcodes/Opcodes.swift b/FruitMachine/M6502/Opcodes/Opcodes.swift index 1a3e82b..bb16bbd 100644 --- a/FruitMachine/M6502/Opcodes/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes/Opcodes.swift @@ -173,7 +173,7 @@ class Opcodes: NSObject { static func SBC(state: CPU, addressingMode: 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))) + var t16: UInt16 = UInt16(state.accumulator &- operand) &- UInt16((state.status_register.carry ? UInt8(0) : UInt8(1))) let t8: UInt8 = UInt8(t16 & 0xFF) state.cyclesInBatch = 0 @@ -182,7 +182,7 @@ class Opcodes: NSObject { if(state.status_register.decimal == true) { t16 = UInt16(hex2bcd(hex: state.accumulator) + hex2bcd(hex: operand) + (state.status_register.carry ? UInt8(1) : UInt8(0))) } else { - state.status_register.carry = (t16 >> 8) == 0 ? false : true + state.status_register.carry = t8 <= 127 ? true : false } state.accumulator = t8 diff --git a/FruitMachine/MainViewController.swift b/FruitMachine/MainViewController.swift index ccf1976..4aeb439 100644 --- a/FruitMachine/MainViewController.swift +++ b/FruitMachine/MainViewController.swift @@ -28,18 +28,25 @@ class MainViewController: NSViewController { self.view.addSubview(computer.emulatorView) self.frameTimer = Timer.scheduledTimer(timeInterval: 1/60, target: self, selector: #selector(runEmulation), userInfo: nil, repeats: true) - //runEmulation() } @objc func runEmulation() { computer.runFrame() + if(!CPU.sharedInstance.isRunning) { + self.frameTimer?.invalidate() + } } override func keyDown(with event: NSEvent) { let c = returnChar(theEvent: event) - computer.pia["keyboard"]?.data = UInt8((c?.asciiValue)! & 0x000000FF) + guard let ascii32 = c?.asciiValue else { + return + } + + computer.pia["keyboard"]?.data = UInt8(ascii32 & 0x000000FF) computer.pia["keyboard"]?.control |= 0x80 + } private func returnChar(theEvent: NSEvent) -> Character?{