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 @@
-
+
@@ -1666,6 +1676,7 @@
+
@@ -1695,6 +1706,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) {