mirror of
https://github.com/trudnai/Steve2.git
synced 2025-01-20 00:29:43 +00:00
- Removed some unused code
- Color / Mono selector - Mono HiRes
This commit is contained in:
parent
c467b8223c
commit
ac36139d0d
@ -1414,7 +1414,7 @@
|
|||||||
"-D_NO_INTERRUPT_CHECK_PER_STEP",
|
"-D_NO_INTERRUPT_CHECK_PER_STEP",
|
||||||
"-D_NO_CLK_ABSOLUTE_PRECISE",
|
"-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_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
@ -1451,7 +1451,7 @@
|
|||||||
"-D_NO_INTERRUPT_CHECK_PER_STEP",
|
"-D_NO_INTERRUPT_CHECK_PER_STEP",
|
||||||
"-D_NO_CLK_ABSOLUTE_PRECISE",
|
"-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_BUNDLE_IDENTIFIER = com.gamealloy.A2Mac;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "A2Mac/A2Mac-Bridging-Header.h";
|
||||||
|
@ -1388,13 +1388,13 @@
|
|||||||
</customSpacing>
|
</customSpacing>
|
||||||
</stackView>
|
</stackView>
|
||||||
<stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lVP-FP-u6x" userLabel="CPU Speed Selection">
|
<stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lVP-FP-u6x" userLabel="CPU Speed Selection">
|
||||||
<rect key="frame" x="8" y="8" width="104" height="500"/>
|
<rect key="frame" x="8" y="8" width="104" height="522"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="7yw-J0-Fmj">
|
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="7yw-J0-Fmj">
|
||||||
<rect key="frame" x="0.0" y="497" width="96" height="5"/>
|
<rect key="frame" x="0.0" y="519" width="96" height="5"/>
|
||||||
</box>
|
</box>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="isd-yh-gCV">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="isd-yh-gCV">
|
||||||
<rect key="frame" x="-2" y="475" width="98" height="18"/>
|
<rect key="frame" x="-2" y="497" width="98" height="18"/>
|
||||||
<buttonCell key="cell" type="check" title="CRT Monitor" bezelStyle="regularSquare" imagePosition="left" inset="2" id="UQ8-Nn-Kt7">
|
<buttonCell key="cell" type="check" title="CRT Monitor" bezelStyle="regularSquare" imagePosition="left" inset="2" id="UQ8-Nn-Kt7">
|
||||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
@ -1403,6 +1403,16 @@
|
|||||||
<action selector="CRTMonitorOnOff:" target="XfG-lQ-9wD" id="2V4-GI-erE"/>
|
<action selector="CRTMonitorOnOff:" target="XfG-lQ-9wD" id="2V4-GI-erE"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WzH-g6-yxF">
|
||||||
|
<rect key="frame" x="-2" y="475" width="105" height="18"/>
|
||||||
|
<buttonCell key="cell" type="check" title="Color Monitor" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="jLh-hF-6Z2">
|
||||||
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="ColorMonitorOnOff:" target="XfG-lQ-9wD" id="Aea-ZM-p6Q"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="t35-xh-L18">
|
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="t35-xh-L18">
|
||||||
<rect key="frame" x="0.0" y="466" width="96" height="5"/>
|
<rect key="frame" x="0.0" y="466" width="96" height="5"/>
|
||||||
</box>
|
</box>
|
||||||
@ -1463,7 +1473,7 @@
|
|||||||
<rect key="frame" x="0.0" y="338" width="96" height="5"/>
|
<rect key="frame" x="0.0" y="338" width="96" height="5"/>
|
||||||
</box>
|
</box>
|
||||||
<splitView hidden="YES" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ge3-qD-JO6">
|
<splitView hidden="YES" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ge3-qD-JO6">
|
||||||
<rect key="frame" x="0.0" y="477" width="104" height="23"/>
|
<rect key="frame" x="0.0" y="499" width="104" height="23"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField verticalHuggingPriority="750" fixedFrame="YES" id="SNE-lV-JXn" userLabel="SoundGap">
|
<textField verticalHuggingPriority="750" fixedFrame="YES" id="SNE-lV-JXn" userLabel="SoundGap">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="90" height="23"/>
|
<rect key="frame" x="0.0" y="0.0" width="90" height="23"/>
|
||||||
@ -1666,6 +1676,7 @@
|
|||||||
<integer value="1000"/>
|
<integer value="1000"/>
|
||||||
<integer value="1000"/>
|
<integer value="1000"/>
|
||||||
<integer value="1000"/>
|
<integer value="1000"/>
|
||||||
|
<integer value="1000"/>
|
||||||
</visibilityPriorities>
|
</visibilityPriorities>
|
||||||
<customSpacing>
|
<customSpacing>
|
||||||
<real value="3.4028234663852886e+38"/>
|
<real value="3.4028234663852886e+38"/>
|
||||||
@ -1695,6 +1706,7 @@
|
|||||||
<real value="3.4028234663852886e+38"/>
|
<real value="3.4028234663852886e+38"/>
|
||||||
<real value="3.4028234663852886e+38"/>
|
<real value="3.4028234663852886e+38"/>
|
||||||
<real value="3.4028234663852886e+38"/>
|
<real value="3.4028234663852886e+38"/>
|
||||||
|
<real value="3.4028234663852886e+38"/>
|
||||||
</customSpacing>
|
</customSpacing>
|
||||||
</stackView>
|
</stackView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
@ -31,26 +31,6 @@ class HiRes: NSView {
|
|||||||
|
|
||||||
let HiResRawPointer = UnsafeRawPointer(RAM + Page1Addr)
|
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
|
// holds the starting addresses for each lines minus the screen page starting address
|
||||||
var HiResLineAddrTbl = [Int](repeating: 0, count: PixelHeight)
|
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]]()
|
var HiResSubView = [[NSView]]()
|
||||||
|
|
||||||
@ -155,9 +85,6 @@ class HiRes: NSView {
|
|||||||
// create smaller box views for draw optimization
|
// create smaller box views for draw optimization
|
||||||
createHiRes()
|
createHiRes()
|
||||||
|
|
||||||
#if METAL_YES
|
|
||||||
initMetal()
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
@ -165,178 +92,6 @@ class HiRes: NSView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#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<CVTimeStamp>,
|
|
||||||
const inOutputTime : UnsafePointer<CVTimeStamp>,
|
|
||||||
flagsIn : CVOptionFlags,
|
|
||||||
flagsOut : UnsafeMutablePointer<CVOptionFlags>,
|
|
||||||
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? {
|
static func createBitmapContext(pixelsWide: Int, _ pixelsHigh: Int) -> CGContext? {
|
||||||
let bytesPerPixel = 4
|
let bytesPerPixel = 4
|
||||||
let bytesPerRow = bytesPerPixel * pixelsWide
|
let bytesPerRow = bytesPerPixel * pixelsWide
|
||||||
@ -363,26 +118,6 @@ class HiRes: NSView {
|
|||||||
return context
|
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..<height {
|
|
||||||
// for _ in 0..<width {
|
|
||||||
// currentPixel[n] = 0
|
|
||||||
// n += 1
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// guard let image = context?.makeImage() else { return }
|
|
||||||
// context?.draw(image, in: boundingBox)
|
|
||||||
// }
|
|
||||||
|
|
||||||
private var currentContext : CGContext? {
|
private var currentContext : CGContext? {
|
||||||
get {
|
get {
|
||||||
@ -397,98 +132,28 @@ class HiRes: NSView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HIRESLOW || HIRESLOWCOLOR
|
|
||||||
static let ScreenBitmapSize = (PixelWidth * PixelHeight * 4)
|
static let ScreenBitmapSize = (PixelWidth * PixelHeight * 4)
|
||||||
static let context = createBitmapContext(pixelsWide: PixelWidth, PixelHeight)
|
static let context = createBitmapContext(pixelsWide: PixelWidth, PixelHeight)
|
||||||
static let pixels = UnsafeMutableRawBufferPointer(start: context?.data, count: ScreenBitmapSize)
|
static let pixels = UnsafeMutableRawBufferPointer(start: context?.data, count: ScreenBitmapSize)
|
||||||
static var pixelsSRGB = pixels.bindMemory(to: UInt32.self)
|
static var pixelsSRGB = pixels.bindMemory(to: UInt32.self)
|
||||||
#endif
|
|
||||||
|
|
||||||
let R = 2
|
let R = 2
|
||||||
let G = 1
|
let G = 1
|
||||||
let B = 0
|
let B = 0
|
||||||
let A = 3
|
let A = 3
|
||||||
|
|
||||||
var blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2)
|
var blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols)
|
||||||
var shadowScreen = [Int](repeating: 0, count: PageSize)
|
var shadowScreen = [Int](repeating: 0, count: PageSize)
|
||||||
|
|
||||||
var was = 0;
|
var was = 0;
|
||||||
|
|
||||||
#if HIRESLOW
|
|
||||||
override func draw(_ rect: CGRect) {
|
|
||||||
// print("HIRESSLOW\n")
|
|
||||||
|
|
||||||
// if was > 100 {
|
// let color_black : UInt32 = 0x00000000;
|
||||||
// return
|
// let color_white : UInt32 = 0xEEEEEEEE;
|
||||||
// }
|
// let color_purple : UInt32 = 0xFFBB11EE;
|
||||||
// was += 1
|
// let color_green : UInt32 = 0xFF0BBB11;
|
||||||
|
// let color_blue : UInt32 = 0xFF1155FF;
|
||||||
var pixelAddr = 0
|
// let color_orange : UInt32 = 0xFFEE2211;
|
||||||
|
|
||||||
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..<HiRes.blockCols {
|
|
||||||
let block = Int(HiResBufferPointer[ Int(lineAddr + blockAddr) ])
|
|
||||||
let screenIdx = y * HiRes.blockCols + x
|
|
||||||
|
|
||||||
if ( shadowScreen[ screenIdx ] != block ) {
|
|
||||||
shadowScreen[ screenIdx ] = block
|
|
||||||
|
|
||||||
for bit in stride(from: 0, through: 6, by: 1) {
|
|
||||||
let bitMask = 1 << bit
|
|
||||||
if (block & bitMask) == 0 {
|
|
||||||
HiRes.pixels[pixelAddr + R] = 0x00;
|
|
||||||
HiRes.pixels[pixelAddr + G] = 0x00;
|
|
||||||
HiRes.pixels[pixelAddr + B] = 0x00;
|
|
||||||
HiRes.pixels[pixelAddr + A] = 0x00;
|
|
||||||
}
|
|
||||||
else { // 28CD41
|
|
||||||
HiRes.pixels[pixelAddr + R] = 0x08;
|
|
||||||
HiRes.pixels[pixelAddr + G] = 0xA2;
|
|
||||||
HiRes.pixels[pixelAddr + B] = 0x12;
|
|
||||||
HiRes.pixels[pixelAddr + A] = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( minX > 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;
|
|
||||||
|
|
||||||
// HiRes Colors for the SRGB color space
|
// HiRes Colors for the SRGB color space
|
||||||
let color_black : UInt32 = 0x00000000;
|
let color_black : UInt32 = 0x00000000;
|
||||||
@ -503,51 +168,111 @@ class HiRes: NSView {
|
|||||||
let color_yellow : UInt32 = 0xFFBBBB11;
|
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..<HiRes.blockCols {
|
||||||
|
let block = Int(HiResBufferPointer[ Int(lineAddr + blockHorIdx) ])
|
||||||
|
let screenIdx = y * HiRes.blockCols + blockHorIdx
|
||||||
|
|
||||||
|
// get all changed blocks
|
||||||
|
blockChanged[ blockVertIdx + blockHorIdx ] = blockChanged[ blockVertIdx + blockHorIdx ] || shadowScreen[ screenIdx ] != block
|
||||||
|
shadowScreen[ screenIdx ] = block
|
||||||
|
|
||||||
|
for bit in stride(from: 0, through: 6, by: 1) {
|
||||||
|
let bitMask = 1 << bit
|
||||||
|
if (block & bitMask) != 0 {
|
||||||
|
HiRes.pixelsSRGB[pixelAddr] = color_green;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HiRes.pixelsSRGB[pixelAddr] = color_black;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelAddr += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
y += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshChanged(blockSize: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func colorPixel ( pixelAddr : Int, pixel : Int, prev : Int ) {
|
func colorPixel ( pixelAddr : Int, pixel : Int, prev : Int ) {
|
||||||
let colorAddr = pixelAddr / 4
|
let colorAddr = pixelAddr / 4
|
||||||
|
|
||||||
switch ( pixel ) {
|
switch ( pixel ) {
|
||||||
case 0x01: // purple (bits are in reverse!)
|
case 1: // purple (bits are in reverse!)
|
||||||
HiRes.pixelsSRGB[colorAddr] = color_purple;
|
HiRes.pixelsSRGB[colorAddr] = color_purple;
|
||||||
// HiRes.pixelsSRGB[colorAddr + 1] = color_purple
|
// HiRes.pixelsSRGB[colorAddr + 1] = color_purple
|
||||||
if (colorAddr >= 1) && (prev != 0x03) && (prev != 0x07) && (prev != 0x00) && (prev != 0x04) {
|
if (colorAddr >= 1) && (prev != 0x03) && (prev != 0x07) && (prev != 0x00) && (prev != 0x04) {
|
||||||
HiRes.pixelsSRGB[colorAddr - 1] = color_purple
|
HiRes.pixelsSRGB[colorAddr - 1] = color_purple
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x02: // green
|
case 2: // green
|
||||||
// reducing color bleeding
|
// reducing color bleeding
|
||||||
if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) {
|
if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) {
|
||||||
HiRes.pixelsSRGB[colorAddr] = color_green
|
HiRes.pixelsSRGB[colorAddr] = color_green
|
||||||
}
|
}
|
||||||
HiRes.pixelsSRGB[colorAddr + 1] = 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 ) {
|
// if ( colorAddr >= 2 ) && ( HiRes.pixelsSRGB[colorAddr - 2] != color_black ) {
|
||||||
// HiRes.pixelsSRGB[colorAddr - 1] = HiRes.pixelsSRGB[colorAddr - 2]
|
// HiRes.pixelsSRGB[colorAddr - 1] = HiRes.pixelsSRGB[colorAddr - 2]
|
||||||
// }
|
// }
|
||||||
// if (colorAddr >= 1) {
|
// if (colorAddr >= 1) {
|
||||||
// HiRes.pixelsSRGB[colorAddr - 1] = color_white
|
// HiRes.pixelsSRGB[colorAddr - 1] = color_yellow
|
||||||
// }
|
// }
|
||||||
HiRes.pixelsSRGB[colorAddr] = color_white
|
HiRes.pixelsSRGB[colorAddr] = color_white
|
||||||
HiRes.pixelsSRGB[colorAddr + 1] = color_white
|
HiRes.pixelsSRGB[colorAddr + 1] = color_white
|
||||||
|
|
||||||
case 0x05: // blue
|
case 5: // blue
|
||||||
HiRes.pixelsSRGB[colorAddr] = color_blue
|
HiRes.pixelsSRGB[colorAddr] = color_blue
|
||||||
if (colorAddr >= 1) && (prev != 0x00) && (prev != 0x04) {
|
if (colorAddr >= 1) && (prev != 0x00) && (prev != 0x04) {
|
||||||
HiRes.pixelsSRGB[colorAddr - 1] = color_blue
|
HiRes.pixelsSRGB[colorAddr - 1] = color_blue
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x06: // orange
|
case 6: // orange
|
||||||
// reducing color bleeding
|
// reducing color bleeding
|
||||||
if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) {
|
if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) {
|
||||||
HiRes.pixelsSRGB[colorAddr] = color_orange
|
HiRes.pixelsSRGB[colorAddr] = color_orange
|
||||||
}
|
}
|
||||||
HiRes.pixelsSRGB[colorAddr + 1] = color_orange
|
HiRes.pixelsSRGB[colorAddr + 1] = color_orange
|
||||||
|
|
||||||
case 0x07: // white 2
|
case 7: // white 2
|
||||||
// if ( colorAddr >= 1 ) {
|
|
||||||
// HiRes.pixelsSRGB[colorAddr - 1] = color_yellow
|
|
||||||
// }
|
|
||||||
HiRes.pixelsSRGB[colorAddr] = color_white
|
HiRes.pixelsSRGB[colorAddr] = color_white
|
||||||
HiRes.pixelsSRGB[colorAddr + 1] = color_white
|
HiRes.pixelsSRGB[colorAddr + 1] = color_white
|
||||||
|
|
||||||
@ -599,7 +324,7 @@ class HiRes: NSView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func Update() {
|
func UpdateColor() {
|
||||||
var height = HiRes.PixelHeight
|
var height = HiRes.PixelHeight
|
||||||
|
|
||||||
// do not even render it...
|
// do not even render it...
|
||||||
@ -623,7 +348,6 @@ class HiRes: NSView {
|
|||||||
var y = 0
|
var y = 0
|
||||||
|
|
||||||
blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2)
|
blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2)
|
||||||
|
|
||||||
HiRes.context?.clear( CGRect(x: 0, y: 0, width: frame.width, height: frame.height) )
|
HiRes.context?.clear( CGRect(x: 0, y: 0, width: frame.width, height: frame.height) )
|
||||||
|
|
||||||
for lineAddr in HiResLineAddrTbl {
|
for lineAddr in HiResLineAddrTbl {
|
||||||
@ -633,7 +357,7 @@ class HiRes: NSView {
|
|||||||
}
|
}
|
||||||
height -= 1
|
height -= 1
|
||||||
|
|
||||||
let blockVertIdx = y / 8 * HiRes.blockCols / 2
|
let blockVertIdx = y / HiRes.blockHeight * HiRes.blockCols / 2
|
||||||
var prev = 0
|
var prev = 0
|
||||||
|
|
||||||
for blockHorIdx in 0 ..< HiRes.blockCols / 2 {
|
for blockHorIdx in 0 ..< HiRes.blockCols / 2 {
|
||||||
@ -679,31 +403,27 @@ class HiRes: NSView {
|
|||||||
|
|
||||||
|
|
||||||
// refresh changed block only
|
// refresh changed block only
|
||||||
|
refreshChanged(blockSize: 2)
|
||||||
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 )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// needsDisplay = true // refresh the entire screen
|
// 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) {
|
override func draw(_ rect: CGRect) {
|
||||||
guard let image = HiRes.context?.makeImage() else { return }
|
guard let image = HiRes.context?.makeImage() else { return }
|
||||||
|
|
||||||
@ -719,249 +439,6 @@ class HiRes: NSView {
|
|||||||
currentContext?.draw(image, in: boundingBox)
|
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<CUnsignedChar>.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
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ class ViewController: NSViewController {
|
|||||||
@IBOutlet weak var scanLines: NSImageView!
|
@IBOutlet weak var scanLines: NSImageView!
|
||||||
|
|
||||||
var CRTMonitor = false
|
var CRTMonitor = false
|
||||||
|
var ColorMonitor = true
|
||||||
var Keyboard2Joystick = true
|
var Keyboard2Joystick = true
|
||||||
var Mouse2Joystick = false
|
var Mouse2Joystick = false
|
||||||
var MouseInterface = true
|
var MouseInterface = true
|
||||||
@ -689,7 +690,7 @@ class ViewController: NSViewController {
|
|||||||
self.lores.isHidden = true
|
self.lores.isHidden = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.hires.Update()
|
hires.Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( self.savedVideoMode.text == 0 ) {
|
else if ( self.savedVideoMode.text == 0 ) {
|
||||||
@ -982,6 +983,12 @@ class ViewController: NSViewController {
|
|||||||
@IBAction func CRTMonitorOnOff(_ sender: NSButton) {
|
@IBAction func CRTMonitorOnOff(_ sender: NSButton) {
|
||||||
CRTMonitor = sender.state == .on
|
CRTMonitor = sender.state == .on
|
||||||
scanLines.isHidden = !CRTMonitor
|
scanLines.isHidden = !CRTMonitor
|
||||||
|
hires.fullUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func ColorMonitorOnOff(_ sender: NSButton) {
|
||||||
|
ColorMonitor = sender.state == .on
|
||||||
|
hires.fullUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func Keyboard2JoystickOnOff(_ sender: NSButton) {
|
@IBAction func Keyboard2JoystickOnOff(_ sender: NSButton) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user