From ac36139d0d1b8df279fbc30909a80d62fa548625 Mon Sep 17 00:00:00 2001 From: tudnai Date: Sat, 20 Jun 2020 18:46:26 -0700 Subject: [PATCH] - Removed some unused code - Color / Mono selector - Mono HiRes --- A2Mac.xcodeproj/project.pbxproj | 4 +- A2Mac/Base.lproj/Main.storyboard | 20 +- A2Mac/HiRes.swift | 717 +++++-------------------------- A2Mac/ViewController.swift | 9 +- 4 files changed, 123 insertions(+), 627 deletions(-) diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index 23985ee..ba44062 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -1414,7 +1414,7 @@ "-D_NO_INTERRUPT_CHECK_PER_STEP", "-D_NO_CLK_ABSOLUTE_PRECISE", ); - OTHER_SWIFT_FLAGS = "-DHIRES -DMETAL_NO -DHIRESDRAW -D_NO_HIRESLOW -DHIRESLOWCOLOR"; + OTHER_SWIFT_FLAGS = "-DHIRES -D_NO_METAL -D_NO_HIRESDRAW -DHIRESLOW -DHIRESLOWCOLOR"; PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -1451,7 +1451,7 @@ "-D_NO_INTERRUPT_CHECK_PER_STEP", "-D_NO_CLK_ABSOLUTE_PRECISE", ); - OTHER_SWIFT_FLAGS = "-DHIRES -DMETAL_NO -DHIRESDRAW -D_NO_HIRESLOW -DHIRESLOWCOLOR"; + OTHER_SWIFT_FLAGS = "-DHIRES -D_NO_METAL -D_NO_HIRESDRAW -DHIRESLOW -DHIRESLOWCOLOR"; PRODUCT_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h"; diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index 8bfd4bd..ef8419e 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -1388,13 +1388,13 @@ - + - + + @@ -1463,7 +1473,7 @@ diff --git a/A2Mac/HiRes.swift b/A2Mac/HiRes.swift index b5f1edd..5907458 100644 --- a/A2Mac/HiRes.swift +++ b/A2Mac/HiRes.swift @@ -31,26 +31,6 @@ class HiRes: NSView { let HiResRawPointer = UnsafeRawPointer(RAM + Page1Addr) - #if METAL_YES - var device: MTLDevice! - var metalLayer: CAMetalLayer! - var vertexBuffer: MTLBuffer! - var renderPipelineState: MTLRenderPipelineState! - var computePipelineState: MTLComputePipelineState! - var commandQueue: MTLCommandQueue! -// var timer: CADisplayLink! // iOS only! - var timer: CVDisplayLink! // MacOS only! - var defaultLibrary : MTLLibrary! - var addFunction : MTLFunction! - var mtlBufferA : MTLBuffer! - var mtlBufferB : MTLBuffer! - var mtlBufferC : MTLBuffer! - - let vertexData: [Float] = [ - 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 - ] - #endif // METAL_YES - // holds the starting addresses for each lines minus the screen page starting address var HiResLineAddrTbl = [Int](repeating: 0, count: PixelHeight) @@ -66,56 +46,6 @@ class HiRes: NSView { } } - #if METAL_YES - func initMetal() { - device = MTLCreateSystemDefaultDevice() - metalLayer = CAMetalLayer() // 1 - metalLayer.device = device // 2 - metalLayer.pixelFormat = .bgra8Unorm // 3 - metalLayer.framebufferOnly = true // 4 - metalLayer.frame = frame // 5 -// hires.layer = metalLayer // 6 - -// let dataSize = vertexData.count * MemoryLayout.size(ofValue: vertexData[0]) // 1 -// vertexBuffer = device.makeBuffer(bytes: vertexData, length: dataSize, options: []) // 2 - - // 1 - defaultLibrary = device.makeDefaultLibrary()! - addFunction = defaultLibrary.makeFunction(name: "add_arrays") - - computePipelineState = try! device.makeComputePipelineState(function: addFunction) - -// let fragmentProgram = defaultLibrary.makeFunction(name: "basic_fragment") -// let vertexProgram = defaultLibrary.makeFunction(name: "basic_vertex") - - // 2 -// let pipelineState -// let pipelineStateDescriptor = MTLRenderPipelineDescriptor() -// pipelineStateDescriptor.vertexFunction = vertexProgram -// pipelineStateDescriptor.fragmentFunction = fragmentProgram -// pipelineStateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm - - // 3 -// pipelineState = try! device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) - - commandQueue = device.makeCommandQueue() - - mtlBufferA = device.makeBuffer(bytes: HiResRawPointer, length: HiRes.PageSize, options: .storageModeShared) - mtlBufferB = device.makeBuffer(bytes: HiResRawPointer, length: HiRes.PageSize, options: .storageModeShared) - mtlBufferC = device.makeBuffer(length: HiRes.PageSize * 4, options: .storageModeShared) - - var displayLink : CVDisplayLink! - let displayID = CGMainDisplayID() - let error = CVDisplayLinkCreateWithCGDisplay(displayID, &displayLink) - -// timer = CVDisplayLink( (target: self, selector: #selector(gameloop)) -// timer.add(to: RunLoop.main, forMode: .default) - -// CVDisplayLinkSetOutputCallback(displayLink!, renderCallback as? CVDisplayLinkOutputCallback, UnsafeMutableRawPointer( Unmanaged.passUnretained(self).toOpaque() )) -// CVDisplayLinkStart(displayLink!) - - } - #endif // METAL_YES var HiResSubView = [[NSView]]() @@ -155,188 +85,13 @@ class HiRes: NSView { // create smaller box views for draw optimization createHiRes() - #if METAL_YES - initMetal() - #endif } override init(frame: CGRect) { super.init(frame: frame) } - - #if METAL_YES - func compute() { - let commandBuffer = commandQueue.makeCommandBuffer()! - let computeEncoder = commandBuffer.makeComputeCommandEncoder() - - computeEncoder?.setComputePipelineState(computePipelineState) - computeEncoder?.setBuffer(mtlBufferA, offset: 0, index: 0) - computeEncoder?.setBuffer(mtlBufferA, offset: 0, index: 1) - computeEncoder?.setBuffer(mtlBufferC, offset: 0, index: 2) - let gridSize = MTLSizeMake(HiRes.PageSize, 1, 1) - let threadGroupSize = min( computePipelineState.maxTotalThreadsPerThreadgroup, HiRes.PageSize ) - let threadgroupSize = MTLSizeMake(threadGroupSize, 1, 1) - // Encode the Compute Command to Execute the Threads - computeEncoder?.dispatchThreadgroups(gridSize, threadsPerThreadgroup: threadgroupSize) - // no more compute passes - computeEncoder?.endEncoding() - // Commit the Command Buffer to Execute Its Commands - commandBuffer.commit() - // Wait for the Calculation to Complete - commandBuffer.waitUntilCompleted() - // Alternatively, to be notified when Metal has processed all of the commands, - // add a completion handler to the command buffer (addCompletedHandler(_:)), - // or check the status of a command buffer by reading its status property - - let result = UnsafeRawBufferPointer(start: mtlBufferC.contents(), count: HiRes.PageSize) - } - - - func render() { - - guard let drawable = metalLayer?.nextDrawable() else { return } - let renderPassDescriptor = MTLRenderPassDescriptor() - renderPassDescriptor.colorAttachments[0].texture = drawable.texture - renderPassDescriptor.colorAttachments[0].loadAction = .clear - renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor( - red: 0.0, - green: 104.0/255.0, - blue: 55.0/255.0, - alpha: 1.0) - - let commandBuffer = commandQueue.makeCommandBuffer()! - - let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)! - renderEncoder.setRenderPipelineState(renderPipelineState) - renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) - renderEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) - renderEncoder.endEncoding() - - // committing buffer - commandBuffer.present(drawable) - commandBuffer.commit() - } - #endif // METAL_YES - - // @objc func gameloop() { - // autoreleasepool { - // self.render() - // } - // } - - func renderCallback(displayLink : CVDisplayLink, - const inNow : UnsafePointer, - const inOutputTime : UnsafePointer, - flagsIn : CVOptionFlags, - flagsOut : UnsafeMutablePointer, - displayLinkContext : UnsafeMutableRawPointer) -> CVReturn - { - /* It's prudent to also have a brief discussion about the CVTimeStamp. - CVTimeStamp has five properties. Three of the five are very useful - for keeping track of the current time, calculating delta time, the - frame number, and the number of frames per second. The utility of - each property is not terribly obvious from just reading the names - or the descriptions in the Developer dcumentation and has been a - mystery to many a developer. Thankfully, CaptainRedmuff on - StackOverflow asked a question that provided the equation that - calculates frames per second. From that equation, we can - extrapolate the value of each field. - - @hostTime = current time in Units of the "root". Yeah, I don't know. - The key to this field is to understand that it is in nanoseconds - (e.g. 1/1_000_000_000 of a second) not units. To convert it to - seconds divide by 1_000_000_000. Dividing by videoRefreshPeriod - and videoTimeScale in a calculation for frames per second yields - the appropriate number of frames. This works as a result of - proportionality--dividing seconds by seconds. Note that dividing - by videoTimeScale to get the time in seconds does not work like it - does for videoTime. - - framesPerSecond: - (videoTime / videoRefreshPeriod) / (videoTime / videoTimeScale) = 59 - and - (hostTime / videoRefreshPeriod) / (hostTime / videoTimeScale) = 59 - but - hostTime * videoTimeScale ≠ seconds, but Units = seconds * (Units / seconds) = Units - - @rateScalar = ratio of "rate of device in CVTimeStamp/unitOfTime" to - the "Nominal Rate". I think the "Nominal Rate" is - videoRefreshPeriod, but unfortunately, the documentation doesn't - just say videoRefreshPeriod is the Nominal rate and then define - what that means. Regardless, because this is a ratio, and the fact - that we know the value of one of the parts (e.g. Units/frame), we - then know that the "rate of the device" is frame/Units (the units of - measure need to cancel out for the ratio to be a ratio). This - makes sense in that rateScalar's definition tells us the rate is - "measured by timeStamps". Since there is a frame for every - timeStamp, the rate of the device equals CVTimeStamp/Unit or - frame/Unit. Thus, - - rateScalar = frame/Units : Units/frame - - @videoTime = the time the frame was created since computer started up. - If you turn your computer off and then turn it back on, this timer - returns to zero. The timer is paused when you put your computer to - sleep. This value is in Units not seconds. To get the number of - seconds this value represents, you have to apply videoTimeScale. - - @videoRefreshPeriod = the number of Units per frame (i.e. Units/frame) - This is useful in calculating the frame number or frames per second. - The documentation calls this the "nominal update period" and I am - pretty sure that is quivalent to the aforementioned "nominal rate". - Unfortunately, the documetation mixes naming conventions and this - inconsistency creates confusion. - - frame = videoTime / videoRefreshPeriod - - @videoTimeScale = Units/second, used to convert videoTime into seconds - and may also be used with videoRefreshPeriod to calculate the expected - framesPerSecond. I say expected, because videoTimeScale and - videoRefreshPeriod don't change while videoTime does change. Thus, - to calculate fps in the case of system slow down, one would need to - use videoTime with videoTimeScale to calculate the actual fps value. - - seconds = videoTime / videoTimeScale - - framesPerSecondConstant = videoTimeScale / videoRefreshPeriod (this value does not change if their is system slowdown) - - USE CASE 1: Time in DD:HH:mm:ss using hostTime - let rootTotalSeconds = inNow.pointee.hostTime - let rootDays = inNow.pointee.hostTime / (1_000_000_000 * 60 * 60 * 24) % 365 - let rootHours = inNow.pointee.hostTime / (1_000_000_000 * 60 * 60) % 24 - let rootMinutes = inNow.pointee.hostTime / (1_000_000_000 * 60) % 60 - let rootSeconds = inNow.pointee.hostTime / 1_000_000_000 % 60 - Swift.print("rootTotalSeconds: \(rootTotalSeconds) rootDays: \(rootDays) rootHours: \(rootHours) rootMinutes: \(rootMinutes) rootSeconds: \(rootSeconds)") - - USE CASE 2: Time in DD:HH:mm:ss using videoTime - let totalSeconds = inNow.pointee.videoTime / Int64(inNow.pointee.videoTimeScale) - let days = (totalSeconds / (60 * 60 * 24)) % 365 - let hours = (totalSeconds / (60 * 60)) % 24 - let minutes = (totalSeconds / 60) % 60 - let seconds = totalSeconds % 60 - Swift.print("totalSeconds: \(totalSeconds) Days: \(days) Hours: \(hours) Minutes: \(minutes) Seconds: \(seconds)") - - Swift.print("fps: \(Double(inNow.pointee.videoTimeScale) / Double(inNow.pointee.videoRefreshPeriod)) seconds: \(Double(inNow.pointee.videoTime) / Double(inNow.pointee.videoTimeScale))") - */ - - /* The displayLinkContext in CVDisplayLinkOutputCallback's parameter list is the - view being driven by the CVDisplayLink. In order to use the context as an - instance of SwiftOpenGLView (which has our drawView() method) we need to use - unsafeBitCast() to cast this context to a SwiftOpenGLView. - */ - -// let view = unsafeBitCast(displayLinkContext, to: SwiftOpenGLView.self) -// // Capture the current time in the currentTime property. -// view.currentTime = inNow.pointee.videoTime / Int64(inNow.pointee.videoTimeScale) -// view.drawView() - -// self.render() - - return kCVReturnSuccess - } - static func createBitmapContext(pixelsWide: Int, _ pixelsHigh: Int) -> CGContext? { let bytesPerPixel = 4 let bytesPerRow = bytesPerPixel * pixelsWide @@ -363,26 +118,6 @@ class HiRes: NSView { return context } -// override func draw(_ rect: CGRect) { -// let width = 200 -// let height = 300 -// let boundingBox = CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height)) -// let context = createBitmapContext(pixelsWide: width, height) -// -// let data = context?.data -// var currentPixel: [UInt32] = unsafeBitCast(data, to: [UInt32].self) -// -// var n = 0 -// for _ in 0.. 100 { -// return -// } -// was += 1 - - var pixelAddr = 0 - - var minX = 9999 - var minY = 9999 - var maxX = 0 - var maxY = 0 - - var x = 0 - var y = 0 - - for lineAddr in HiResLineAddrTbl { - for blockAddr in 0.. x ) { minX = x } - if ( minY > y ) { minY = y } - if ( maxX < x ) { maxX = x } - if ( maxY < y ) { maxY = y } - - pixelAddr += 4 - x += 1 - } - } - else { - pixelAddr += 4 * 7 - x += 7 - } - } - - y += 1 - x = 0 - } - - guard let image = HiRes.context?.makeImage() else { return } - let boundingBox = CGRect(x: 0, y: 0, width: CGFloat(HiRes.PixelWidth), height: CGFloat(HiRes.PixelHeight)) - currentContext!.draw (image, in: boundingBox) - } - #elseif HIRESLOWCOLOR + // let color_black : UInt32 = 0x00000000; + // let color_white : UInt32 = 0xEEEEEEEE; + // let color_purple : UInt32 = 0xFFBB11EE; + // let color_green : UInt32 = 0xFF0BBB11; + // let color_blue : UInt32 = 0xFF1155FF; + // let color_orange : UInt32 = 0xFFEE2211; - -// let color_black : UInt32 = 0x00000000; -// let color_white : UInt32 = 0xEEEEEEEE; -// let color_purple : UInt32 = 0xFFBB11EE; -// let color_green : UInt32 = 0xFF0BBB11; -// let color_blue : UInt32 = 0xFF1155FF; -// let color_orange : UInt32 = 0xFFEE2211; - // HiRes Colors for the SRGB color space let color_black : UInt32 = 0x00000000; let color_white : UInt32 = 0xFFEEEEEE; @@ -497,57 +162,117 @@ class HiRes: NSView { let color_green : UInt32 = 0xFF2BD84A; let color_blue : UInt32 = 0xFF5599FF; let color_orange : UInt32 = 0xFFFF6302; - + // for debugging only: let color_turquis : UInt32 = 0xFF11BBBB; let color_yellow : UInt32 = 0xFFBBBB11; + + + func refreshChanged( blockSize : Int ) { + // refresh changed block only + + let screenBlockMargin = 12 / blockSize + + let blockScreenWidth = Int(frame.width) / HiRes.blockCols * blockSize + let blockScreenHeigth = Int(frame.height) / HiRes.blockRows + + for blockVertIdx in 0 ..< HiRes.blockRows { + for blockHorIdx in 0 ..< HiRes.blockCols / blockSize { + if blockChanged[ blockVertIdx * HiRes.blockCols / blockSize + blockHorIdx ] { + // refresh the entire screen + let boundingBox = CGRect( + x: blockHorIdx * blockScreenWidth - screenBlockMargin, + y: Int(frame.height) - blockVertIdx * blockScreenHeigth - blockScreenHeigth - screenBlockMargin, + width: blockScreenWidth + screenBlockMargin * blockSize, + height: blockScreenHeigth + screenBlockMargin * blockSize) + + self.setNeedsDisplay( boundingBox ) + } + } + } + } + + + func UpdateMono() { + blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols) + var pixelAddr = 0 + + var y = 0 + + for lineAddr in HiResLineAddrTbl { + let blockVertIdx = y / HiRes.blockHeight * HiRes.blockCols + + for blockHorIdx in 0..= 1) && (prev != 0x03) && (prev != 0x07) && (prev != 0x00) && (prev != 0x04) { HiRes.pixelsSRGB[colorAddr - 1] = color_purple } - case 0x02: // green + case 2: // green // reducing color bleeding if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) { HiRes.pixelsSRGB[colorAddr] = color_green } HiRes.pixelsSRGB[colorAddr + 1] = color_green - case 0x03: // white 1 + case 3: // white 1 // if ( colorAddr >= 2 ) && ( HiRes.pixelsSRGB[colorAddr - 2] != color_black ) { // HiRes.pixelsSRGB[colorAddr - 1] = HiRes.pixelsSRGB[colorAddr - 2] // } // if (colorAddr >= 1) { -// HiRes.pixelsSRGB[colorAddr - 1] = color_white +// HiRes.pixelsSRGB[colorAddr - 1] = color_yellow // } HiRes.pixelsSRGB[colorAddr] = color_white HiRes.pixelsSRGB[colorAddr + 1] = color_white - case 0x05: // blue + case 5: // blue HiRes.pixelsSRGB[colorAddr] = color_blue if (colorAddr >= 1) && (prev != 0x00) && (prev != 0x04) { HiRes.pixelsSRGB[colorAddr - 1] = color_blue } - case 0x06: // orange + case 6: // orange // reducing color bleeding if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) { HiRes.pixelsSRGB[colorAddr] = color_orange } HiRes.pixelsSRGB[colorAddr + 1] = color_orange - case 0x07: // white 2 -// if ( colorAddr >= 1 ) { -// HiRes.pixelsSRGB[colorAddr - 1] = color_yellow -// } + case 7: // white 2 HiRes.pixelsSRGB[colorAddr] = color_white HiRes.pixelsSRGB[colorAddr + 1] = color_white @@ -599,7 +324,7 @@ class HiRes: NSView { } - func Update() { + func UpdateColor() { var height = HiRes.PixelHeight // do not even render it... @@ -623,7 +348,6 @@ class HiRes: NSView { var y = 0 blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2) - HiRes.context?.clear( CGRect(x: 0, y: 0, width: frame.width, height: frame.height) ) for lineAddr in HiResLineAddrTbl { @@ -633,7 +357,7 @@ class HiRes: NSView { } height -= 1 - let blockVertIdx = y / 8 * HiRes.blockCols / 2 + let blockVertIdx = y / HiRes.blockHeight * HiRes.blockCols / 2 var prev = 0 for blockHorIdx in 0 ..< HiRes.blockCols / 2 { @@ -679,30 +403,26 @@ class HiRes: NSView { // refresh changed block only - - let screenBlockMargin = 6 - - let blockScreenWidth = Int(frame.width) / HiRes.blockCols * 2 - let blockScreenHeigth = Int(frame.height) / HiRes.blockRows - - for blockVertIdx in 0 ..< HiRes.blockRows { - for blockHorIdx in 0 ..< HiRes.blockCols / 2 { - if blockChanged[ blockVertIdx * HiRes.blockCols / 2 + blockHorIdx ] { - // refresh the entire screen - let boundingBox = CGRect( - x: blockHorIdx * blockScreenWidth - screenBlockMargin, - y: Int(frame.height) - blockVertIdx * blockScreenHeigth - blockScreenHeigth - screenBlockMargin, - width: blockScreenWidth + screenBlockMargin * 2, - height: blockScreenHeigth + screenBlockMargin * 2) - - self.setNeedsDisplay( boundingBox ) - } - } - } - + refreshChanged(blockSize: 2) // needsDisplay = true // refresh the entire screen } + + + func Update() { + if ( ViewController.current?.ColorMonitor ?? true ) { + UpdateColor() + } + else { + UpdateMono() + } + } + + func fullUpdate() { + needsDisplay = true + Update() + } + override func draw(_ rect: CGRect) { guard let image = HiRes.context?.makeImage() else { return } @@ -719,249 +439,6 @@ class HiRes: NSView { currentContext?.draw(image, in: boundingBox) } - #elseif HIRESDRAWCOLOR - - let colorPalette : [NSColor] = [ - NSColor(calibratedRed: 0.0000, green: 0.000, blue: 0.000, alpha: 0.0), // black - NSColor(calibratedRed: 0.0314, green: 0.635, blue: 0.071, alpha: 1.0), // green - NSColor(calibratedRed: 0.0314, green: 0.635, blue: 0.071, alpha: 1.0), // purple - NSColor(calibratedRed: 1.0000, green: 1.000, blue: 1.000, alpha: 1.0), // white - NSColor(calibratedRed: 0.0000, green: 0.000, blue: 0.000, alpha: 0.0), // black - NSColor(calibratedRed: 0.0314, green: 0.635, blue: 0.071, alpha: 1.0), // orange - NSColor(calibratedRed: 0.0314, green: 0.635, blue: 0.071, alpha: 1.0), // blue - NSColor(calibratedRed: 1.0000, green: 1.000, blue: 1.000, alpha: 1.0), // white - ] - - let path = NSBezierPath() - - override func draw(_ rect: CGRect) { -// NSColor.green.setFill() - NSColor(calibratedRed: 0.0314, green: 0.635, blue: 0.071, alpha: 1.0).setStroke() - - path.removeAllPoints() - path.lineWidth = 0.7 - path.move(to: NSPoint(x: 0, y: 0)) - -// path.appendRect(NSRect(x: 0, y: 0, width: 10, height: 10)) - - for y in 0 ..< HiRes.PixelHeight { - var color : UInt = 0 - var lastColor : UInt = 0 - path.move(to: NSPoint(x: 0, y: y)) - - // for color screen we need to process blocks in a pair - for blockX in 0 ..< HiRes.blockCols / 2 { - - let lineAddr = HiResLineAddrTbl[y] - var x = blockX * HiRes.blockWidth * 2 - - var block0 = UInt(HiResBufferPointer[ Int(lineAddr + blockX * 2) + 0 ]) - var block1 = UInt(HiResBufferPointer[ Int(lineAddr + blockX * 2) + 1 ]) - let b70 : UInt = (block0 & 0x80) >> 5 - let b71 : UInt = (block1 & 0x80) >> 5 - - var block7 : [UInt] = [0,0,0,0,0,0,0] - var i = 0 - - for _ in 0 ... 2 { - block7[i] = b70 - block7[i] |= block0 & 3 - block0 >>= 2 - i += 1 - } - - block7[i] = b70 - block7[i] |= ((block0 & 1) << 1) | (block1 & 1) - block1 >>= 1 - i += 1 - - for _ in 0 ... 2 { - block7[i] = b71 - block7[i] |= block1 & 3 - block1 >>= 2 - i += 1 - } - - - for px in 0 ... 6 { // stride(from: 0, through: 6, by: 1) { - color = block7[px] - if (color != lastColor) { - colorPalette[Int(color)].setStroke() - path.line(to: NSPoint(x: x, y: y)) - path.stroke() - path.removeAllPoints() - lastColor = color - } - - x += 1 - } - } // x - // make sure we close the path at the end of the horizontal line - if (color != lastColor) { - path.line(to: NSPoint(x: 279, y: y)) - lastColor = color - } - } -// path.fill() - - path.stroke() - - } - #elseif HIRESDRAW - let path = NSBezierPath() - override func draw(_ rect: CGRect) { - let pixelWidth = bounds.width / CGFloat(HiRes.PixelWidth) - let pixelHeight = bounds.height / CGFloat(HiRes.PixelHeight) - - // self.hidden = videoMode.text == 1 - -// NSColor.green.setFill() -// NSColor(calibratedRed: 0.0314, green: 0.635, blue: 0.071, alpha: 1.0).setStroke() -// NSColor(calibratedRed: 0.05, green: 0.7, blue: 0.1, alpha: 1.0).setStroke() - NSColor.systemGreen.setStroke() - - path.removeAllPoints() - path.lineWidth = 0.7 * pixelHeight - path.move(to: NSPoint(x: 0, y: 0)) - -// path.appendRect(NSRect(x: 0, y: 0, width: 10, height: 10)) - - var height = HiRes.PixelHeight - - // do not even render it... - if videoMode.text == 1 { - return - } - else { - if videoMode.mixed == 1 { - height = HiRes.MixedHeight - } - if videoMode.page == 1 { - HiResBufferPointer = HiResBuffer2 - } - else { - HiResBufferPointer = HiResBuffer1 - } - } - - - for y in 0 ..< height { - var inX = false - path.move(to: NSPoint(x: 0, y: y)) - - for blockX in 0 ..< HiRes.blockCols { - - let lineAddr = HiResLineAddrTbl[y] - let block = UInt(HiResBufferPointer[ Int(lineAddr + blockX) ]) - - // if( shadowScreen[ screenIdx ] != block ) { - // shadowScreen[ screenIdx ] = block - // - var x = blockX * HiRes.blockWidth - if block != 0 && block != 0x80 { - for bit in 0 ... 6 { // stride(from: 0, through: 6, by: 1) { - let bitMask : UInt = 1 << bit - if (block & bitMask) == 0 { - if inX { - inX = false - path.line(to: NSPoint(x: CGFloat(x) * pixelWidth, y: CGFloat(192 - y) * pixelHeight )) - } - } - else { // 28CD41 - if ( inX == false ) { - inX = true - path.move(to: NSPoint(x: CGFloat(x) * pixelWidth, y: CGFloat(192 - y) * pixelHeight )) - } - } - - x += 1 - } - } - else { - // make sure we close the path if the next block is completely zero - if inX { - inX = false - path.line(to: NSPoint(x: CGFloat(x) * pixelWidth, y: CGFloat(192 - y) * pixelHeight )) - } - } - } // x - // make sure we close the path at the end of the horizontal line - if inX { - inX = false - path.line(to: NSPoint(x: 279 * pixelWidth, y: CGFloat(192 - y) * pixelHeight )) - } - } -// path.fill() - path.stroke() - - } - #elseif HIRES - override func draw(_ rect: CGRect) { - - // print("HIRESBLOCKS\n") - -// if was > 100 { -// return -// } -// was += 1 - - for blockY in 0 ..< HiRes.blockRows { - for blockX in 0 ..< HiRes.blockCols { - let blockView = HiResSubView[blockY][blockX] - - let bitmapSize = HiRes.blockWidth * HiRes.blockHeight * 4 - let context = HiRes.createBitmapContext(pixelsWide: HiRes.blockWidth, HiRes.blockHeight) - let pixels = UnsafeMutableRawBufferPointer(start: context?.data, count: bitmapSize) // UnsafeMutablePointer.allocate(capacity: byteCount) - - - var blockNeedsDisplay = false - for line in 0 ... 7 { - let y = blockY + line - let screenIdx = y * HiRes.blockCols + blockX - let pixelAddr = line - - let lineAddr = HiResLineAddrTbl[y] - let block = Int(HiResBufferPointer[ Int(lineAddr + blockX) ]) - - if( shadowScreen[ screenIdx ] != block ) { - shadowScreen[ screenIdx ] = block - - blockNeedsDisplay = true - - var x = blockX * HiRes.blockWidth - for bit in 0 ... 6 { // stride(from: 0, through: 6, by: 1) { - let bitMask = 1 << bit - if (block & bitMask) == 0 { - pixels[pixelAddr + R] = 0x00; - pixels[pixelAddr + G] = 0x00; - pixels[pixelAddr + B] = 0x00; - pixels[pixelAddr + A] = 0x00; - } - else { // 28CD41 - pixels[pixelAddr + R] = 0x08; - pixels[pixelAddr + G] = 0xA2; - pixels[pixelAddr + B] = 0x12; - pixels[pixelAddr + A] = 0x7F; - } - - x += 1 - } - } - } - - if blockNeedsDisplay { - blockView.needsDisplay = true -// print("block(\(blockX),\(blockY))") - guard let image = context?.makeImage() else { return } - let boundingBox = CGRect(x: 0, y: 0, width: CGFloat(HiRes.PixelWidth), height: CGFloat(HiRes.PixelHeight)) - currentContext!.draw(image, in: boundingBox) - } - - } - } - - } - #endif } diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index db7fce2..fadbd2e 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -55,6 +55,7 @@ class ViewController: NSViewController { @IBOutlet weak var scanLines: NSImageView! var CRTMonitor = false + var ColorMonitor = true var Keyboard2Joystick = true var Mouse2Joystick = false var MouseInterface = true @@ -689,7 +690,7 @@ class ViewController: NSViewController { self.lores.isHidden = true } - self.hires.Update() + hires.Update() } } else if ( self.savedVideoMode.text == 0 ) { @@ -982,6 +983,12 @@ class ViewController: NSViewController { @IBAction func CRTMonitorOnOff(_ sender: NSButton) { CRTMonitor = sender.state == .on scanLines.isHidden = !CRTMonitor + hires.fullUpdate() + } + + @IBAction func ColorMonitorOnOff(_ sender: NSButton) { + ColorMonitor = sender.state == .on + hires.fullUpdate() } @IBAction func Keyboard2JoystickOnOff(_ sender: NSButton) {