From 16c100c5658f21bca2bd41aabfbe6837c2602c05 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Sun, 30 Jul 2017 23:23:31 -0400 Subject: [PATCH] speeding up frame rendering --- FruitMachine.xcodeproj/project.pbxproj | 6 ++- FruitMachine/AppleI/AppleI.swift | 6 +-- FruitMachine/AppleI/AppleIBitmapDisplay.swift | 48 ++++--------------- FruitMachine/AppleI/Video/BitmapPixels.swift | 23 +++++++++ FruitMachine/MainViewController.swift | 6 ++- 5 files changed, 44 insertions(+), 45 deletions(-) create mode 100644 FruitMachine/AppleI/Video/BitmapPixels.swift diff --git a/FruitMachine.xcodeproj/project.pbxproj b/FruitMachine.xcodeproj/project.pbxproj index 6ae92c3..fdff203 100644 --- a/FruitMachine.xcodeproj/project.pbxproj +++ b/FruitMachine.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 2A5BC51E1F29A4C3008C03BE /* AppleIBitmapDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5BC51D1F29A4C3008C03BE /* AppleIBitmapDisplay.swift */; }; 2A60851E1F2AFAE900E05B64 /* PIA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A60851D1F2AFAE900E05B64 /* PIA.swift */; }; 2A6D3BF21F2E6222001CBEFB /* AppleGLDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6D3BF11F2E6222001CBEFB /* AppleGLDisplay.swift */; }; + 2A91852A1F2EA84D00A9E5BE /* BitmapPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */; }; 2AA8B5F81F2A8889002B350F /* AppleI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5F71F2A8889002B350F /* AppleI.swift */; }; 2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */; }; 2AA8B5FE1F2A942C002B350F /* PIAOverrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */; }; @@ -44,6 +45,7 @@ 2A5BC51D1F29A4C3008C03BE /* AppleIBitmapDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIBitmapDisplay.swift; sourceTree = ""; }; 2A60851D1F2AFAE900E05B64 /* PIA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PIA.swift; sourceTree = ""; }; 2A6D3BF11F2E6222001CBEFB /* AppleGLDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGLDisplay.swift; sourceTree = ""; }; + 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BitmapPixels.swift; sourceTree = ""; }; 2AA8B5F71F2A8889002B350F /* AppleI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleI.swift; sourceTree = ""; }; 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Terminal.swift; sourceTree = ""; }; 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PIAOverrides.swift; sourceTree = ""; }; @@ -190,9 +192,10 @@ 2AE42E411F28663600C4900E /* Video */ = { isa = PBXGroup; children = ( + 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */, 2AE42E421F28665300C4900E /* CharacterGenerator.swift */, - 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */, 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */, + 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */, ); path = Video; sourceTree = ""; @@ -275,6 +278,7 @@ 2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */, 2A5BC51E1F29A4C3008C03BE /* AppleIBitmapDisplay.swift in Sources */, 2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */, + 2A91852A1F2EA84D00A9E5BE /* BitmapPixels.swift in Sources */, 2AE42E431F28665300C4900E /* CharacterGenerator.swift in Sources */, 2AE42E0C1F28522D00C4900E /* MemoryOverride.swift in Sources */, 2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */, diff --git a/FruitMachine/AppleI/AppleI.swift b/FruitMachine/AppleI/AppleI.swift index fe87fa9..383a595 100644 --- a/FruitMachine/AppleI/AppleI.swift +++ b/FruitMachine/AppleI/AppleI.swift @@ -14,9 +14,6 @@ class AppleI: NSObject { let cg = CharacterGenerator(romPath: "/Users/luigi/apple1/apple1.vid"); let terminal = Terminal() - //PIA 0 = KBD - //PIA 1 = DSP - //let pia = [PIA(), PIA()] let pia: [String:PIA] = [ "keyboard": PIA(), "display": PIA() @@ -78,7 +75,8 @@ class AppleI: NSObject { //update the video display for (cellNum, character) in terminal.characters.enumerated() { - emulatorViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: character), pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum)) + emulatorViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: character), + pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum)) } emulatorView.setNeedsDisplay(emulatorView.frame) diff --git a/FruitMachine/AppleI/AppleIBitmapDisplay.swift b/FruitMachine/AppleI/AppleIBitmapDisplay.swift index 7912daf..ad057ff 100644 --- a/FruitMachine/AppleI/AppleIBitmapDisplay.swift +++ b/FruitMachine/AppleI/AppleIBitmapDisplay.swift @@ -13,48 +13,19 @@ class AppleIBitmapDisplay: NSObject, CALayerDelegate { static let PIXEL_HEIGHT = 192 /* Pixel data stuff. */ - struct PixelData { - var a: UInt8 = 255 - var r: UInt8 - var g: UInt8 - var b: UInt8 - } - - let bitsPerComponent: UInt = 8 - let bitsPerPixel: UInt = 32 - let colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo: CGBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue) - /* */ - var indexedPixels: [UInt8] - var colorValues: [PixelData] - - var rgbPixels = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: AppleIBitmapDisplay.PIXEL_WIDTH*AppleIBitmapDisplay.PIXEL_HEIGHT) - - override init() - { - indexedPixels = [UInt8](repeating: 0x00, count: AppleIBitmapDisplay.PIXEL_WIDTH*AppleIBitmapDisplay.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] { - for (num, colorIndex) in pixels.enumerated() { - rgbPixels[num] = colorValues[Int(colorIndex)] - } - - return rgbPixels - } + var rgbPixels = [BitmapPixels.PixelData](repeating: BitmapPixels.ColorBlack, count: AppleIBitmapDisplay.PIXEL_WIDTH*AppleIBitmapDisplay.PIXEL_HEIGHT) func putCharacterPixels(charPixels: [UInt8], pixelPosition: CGPoint) { //Calculate the offset to reach the desired position. let baseOffset = (Int(pixelPosition.y) * AppleIBitmapDisplay.PIXEL_WIDTH) + Int(pixelPosition.x) for charY in 0.. 0 ? 1 : 0 + rgbPixels[baseOffset + offsetY + 7 - charX] = (charPixels[charY] & UInt8(1 << charX)) > 0 ? BitmapPixels.ColorWhite : BitmapPixels.ColorBlack } } } @@ -71,15 +42,14 @@ class AppleIBitmapDisplay: NSObject, CALayerDelegate { func draw(_ layer: CALayer, in ctx: CGContext) { let bounds = layer.bounds - var pixels = convertIndexedPixelsToRGB(pixels: indexedPixels) - let pixelProvider = CGDataProvider(data: NSData(bytes: &pixels, length: pixels.count * MemoryLayout.size)) + let pixelProvider = CGDataProvider(data: NSData(bytes: &rgbPixels, length: rgbPixels.count * MemoryLayout.size)) let renderedImage = CGImage(width: AppleIBitmapDisplay.PIXEL_WIDTH, height: AppleIBitmapDisplay.PIXEL_HEIGHT, - bitsPerComponent: Int(bitsPerComponent), - bitsPerPixel: Int(bitsPerPixel), - bytesPerRow: AppleIBitmapDisplay.PIXEL_WIDTH * Int(MemoryLayout.size), - space: colorSpace, + bitsPerComponent: Int(BitmapPixels.bitsPerComponent), + bitsPerPixel: Int(BitmapPixels.bitsPerPixel), + bytesPerRow: AppleIBitmapDisplay.PIXEL_WIDTH * Int(MemoryLayout.size), + space: BitmapPixels.colorSpace, bitmapInfo: bitmapInfo, provider: pixelProvider!, decode: nil, diff --git a/FruitMachine/AppleI/Video/BitmapPixels.swift b/FruitMachine/AppleI/Video/BitmapPixels.swift new file mode 100644 index 0000000..33e3e94 --- /dev/null +++ b/FruitMachine/AppleI/Video/BitmapPixels.swift @@ -0,0 +1,23 @@ +// +// BitmapPixels.swift +// FruitMachine +// +// Created by Christopher Rohl on 7/30/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +class BitmapPixels: NSObject { + //2bpp bitmap data so that we're byte-aligned for ease of use. + struct PixelData { + var data: UInt8 = 0 + } + + static let bitsPerComponent: UInt8 = 2 + static let bitsPerPixel: UInt = 8 + static let colorSpace = CGColorSpaceCreateDeviceRGB() + + static let ColorBlack = PixelData(data: 0b11000000) + static let ColorWhite = PixelData(data: 0b11111111) +} diff --git a/FruitMachine/MainViewController.swift b/FruitMachine/MainViewController.swift index a686809..37699bf 100644 --- a/FruitMachine/MainViewController.swift +++ b/FruitMachine/MainViewController.swift @@ -32,7 +32,11 @@ class MainViewController: NSViewController { //computer.emuGLView.doSetup() //self.view.addSubview(computer.emuGLView) - self.frameTimer = Timer.scheduledTimer(timeInterval: 1/60, target: self, selector: #selector(runEmulation), userInfo: nil, repeats: true) + self.frameTimer = Timer.scheduledTimer(timeInterval: 1/60, + target: self, + selector: #selector(runEmulation), + userInfo: nil, + repeats: true) } @objc func runEmulation() {