mirror of
https://github.com/trudnai/Steve2.git
synced 2024-06-12 18:45:22 +00:00
Old CRT monitor effect: Pixel trail
This commit is contained in:
parent
fd3ead734b
commit
5d82b7569e
|
@ -158,6 +158,9 @@
|
|||
32A6AB0F266AF5160023257A /* paddle.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A6AB0E266AF5160023257A /* paddle.c */; };
|
||||
32A6AB10266AF5160023257A /* paddle.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A6AB0E266AF5160023257A /* paddle.c */; };
|
||||
32A6AB11266AF5160023257A /* paddle.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A6AB0E266AF5160023257A /* paddle.c */; };
|
||||
32A6AB1B266B19680023257A /* hires.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A6AA97266187570023257A /* hires.c */; };
|
||||
32A6AB25266B19680023257A /* hires.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A6AA97266187570023257A /* hires.c */; };
|
||||
32A6AB26266B196A0023257A /* hires.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A6AA97266187570023257A /* hires.c */; };
|
||||
32A9F74A2467B60B004902A1 /* speaker.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A9F7492467B60B004902A1 /* speaker.c */; };
|
||||
32A9F74B2467B60B004902A1 /* speaker.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A9F7492467B60B004902A1 /* speaker.c */; };
|
||||
32AF7C9724AD85E8002D82BF /* select_all.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 32AF7C9624AD85E8002D82BF /* select_all.png */; };
|
||||
|
@ -1455,6 +1458,7 @@
|
|||
325EB67623FBC44400C6B4A4 /* common.c in Sources */,
|
||||
32A9F74B2467B60B004902A1 /* speaker.c in Sources */,
|
||||
32A6AB11266AF5160023257A /* paddle.c in Sources */,
|
||||
32A6AB26266B196A0023257A /* hires.c in Sources */,
|
||||
325EB67823FBC45300C6B4A4 /* disk.c in Sources */,
|
||||
325EB64723FBBACF00C6B4A4 /* ViewController.swift in Sources */,
|
||||
325EB64323FBBACF00C6B4A4 /* AppDelegate.swift in Sources */,
|
||||
|
@ -1504,6 +1508,7 @@
|
|||
32799F88264B1A5700255669 /* RepeatingTimer.swift in Sources */,
|
||||
32A6AAFA266AEDF50023257A /* mmio.c in Sources */,
|
||||
32799F8A264B1A5700255669 /* MonitorView.swift in Sources */,
|
||||
32A6AB25266B19680023257A /* hires.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1529,6 +1534,7 @@
|
|||
32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */,
|
||||
32A6AAF0266AEDF40023257A /* mmio.c in Sources */,
|
||||
32C4532E233345430000EBA1 /* MonitorView.swift in Sources */,
|
||||
32A6AB1B266B19680023257A /* hires.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -33,5 +33,7 @@
|
|||
#import "disk.h"
|
||||
#import "dsk2woz.h"
|
||||
#import "mmio.h"
|
||||
#import "hires.h"
|
||||
|
||||
|
||||
#endif /* A2Mac_Bridging_Header_h */
|
||||
|
|
|
@ -83,6 +83,8 @@ class HiRes: NSView {
|
|||
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
pixelsSRGB = HiRes.context?.data?.bindMemory(to: UInt32.self, capacity: HiRes.ScreenBitmapSize)
|
||||
|
||||
super.init(coder: aDecoder)
|
||||
initHiResLineAddresses()
|
||||
clearScreen()
|
||||
|
@ -150,14 +152,14 @@ class HiRes: NSView {
|
|||
static let ScreenBitmapSize = (PixelWidth * PixelHeight * 4)
|
||||
static let context = createBitmapContext(pixelsWide: PixelWidth, PixelHeight)
|
||||
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)
|
||||
|
||||
let R = 2
|
||||
let G = 1
|
||||
let B = 0
|
||||
let A = 3
|
||||
|
||||
var blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols)
|
||||
// var blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols)
|
||||
var shadowScreen = [Int](repeating: 0, count: PageSize)
|
||||
|
||||
var was = 0;
|
||||
|
@ -196,7 +198,7 @@ class HiRes: NSView {
|
|||
|
||||
for blockVertIdx in 0 ..< HiRes.blockRows {
|
||||
for blockHorIdx in 0 ..< HiRes.blockCols / blockSize {
|
||||
if blockChanged[ blockVertIdx * HiRes.blockCols / blockSize + blockHorIdx ] {
|
||||
if blockChanged[ blockVertIdx * HiRes.blockCols / blockSize + blockHorIdx ] != 0 {
|
||||
// refresh the entire screen
|
||||
let boundingBox = CGRect(
|
||||
x: blockHorIdx * blockScreenWidth - screenBlockMargin,
|
||||
|
@ -231,17 +233,24 @@ class HiRes: NSView {
|
|||
}
|
||||
|
||||
var pixelAddr = 0
|
||||
|
||||
|
||||
var y = 0
|
||||
|
||||
blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols)
|
||||
|
||||
|
||||
// blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols)
|
||||
|
||||
if ( ViewController.current?.CRTMonitor ?? false ) {
|
||||
// do not clear the changes table
|
||||
}
|
||||
else {
|
||||
hires_clearChanges()
|
||||
}
|
||||
|
||||
for lineAddr in HiResLineAddrTbl {
|
||||
if ( height <= 0 ) {
|
||||
break
|
||||
}
|
||||
height -= 1
|
||||
|
||||
|
||||
let blockVertIdx = y / HiRes.blockHeight * HiRes.blockCols
|
||||
|
||||
for blockHorIdx in 0..<HiRes.blockCols {
|
||||
|
@ -249,24 +258,45 @@ class HiRes: NSView {
|
|||
let screenIdx = y * HiRes.blockCols + blockHorIdx
|
||||
|
||||
// get all changed blocks
|
||||
blockChanged[ blockVertIdx + blockHorIdx ] = blockChanged[ blockVertIdx + blockHorIdx ] || shadowScreen[ screenIdx ] != block
|
||||
if shadowScreen[ screenIdx ] != block {
|
||||
blockChanged[ blockVertIdx + blockHorIdx ] = 8
|
||||
}
|
||||
else if ( ViewController.current?.CRTMonitor ?? false ) {
|
||||
// slow CRT fade out effect
|
||||
if (y % HiRes.blockHeight == 0) && (blockChanged[ blockVertIdx + blockHorIdx ] > 0) {
|
||||
blockChanged[ blockVertIdx + blockHorIdx ] -= 1
|
||||
}
|
||||
}
|
||||
|
||||
shadowScreen[ screenIdx ] = block
|
||||
|
||||
for bit in stride(from: 0, through: 6, by: 1) {
|
||||
let bitMask = 1 << bit
|
||||
if (block & bitMask) != 0 {
|
||||
HiRes.pixelsSRGB[pixelAddr] = monoColor;
|
||||
pixelsSRGB[pixelAddr] = monoColor;
|
||||
}
|
||||
else if ( ViewController.current?.CRTMonitor ?? false ) {
|
||||
var srgb = pixelsSRGB[pixelAddr]
|
||||
let s = srgb >> 24 & 0xFF / 2
|
||||
let r = srgb >> 16 & 0xFF / 2
|
||||
let g = srgb >> 8 & 0xFF / 2
|
||||
let b = srgb >> 0 & 0xFF / 2
|
||||
srgb = s << 24 | r << 16 | g << 8 | b
|
||||
|
||||
pixelsSRGB[pixelAddr] = srgb;
|
||||
}
|
||||
else {
|
||||
HiRes.pixelsSRGB[pixelAddr] = color_black;
|
||||
pixelsSRGB[pixelAddr] = color_black;
|
||||
}
|
||||
|
||||
pixelAddr += 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
y += 1
|
||||
}
|
||||
|
||||
// hires_renderMono()
|
||||
|
||||
refreshChanged(blockSize: 1)
|
||||
}
|
||||
|
@ -277,18 +307,18 @@ class HiRes: NSView {
|
|||
|
||||
switch ( pixel ) {
|
||||
case 1: // purple (bits are in reverse!)
|
||||
HiRes.pixelsSRGB[colorAddr] = color_purple;
|
||||
pixelsSRGB[colorAddr] = color_purple;
|
||||
// HiRes.pixelsSRGB[colorAddr + 1] = color_purple
|
||||
if (colorAddr >= 1) && (prev != 0x03) && (prev != 0x07) && (prev != 0x00) && (prev != 0x04) {
|
||||
HiRes.pixelsSRGB[colorAddr - 1] = color_purple
|
||||
pixelsSRGB[colorAddr - 1] = color_purple
|
||||
}
|
||||
|
||||
case 2: // green
|
||||
// reducing color bleeding
|
||||
if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) {
|
||||
HiRes.pixelsSRGB[colorAddr] = color_green
|
||||
if (colorAddr > 0) && (pixelsSRGB[colorAddr - 1] != color_black) {
|
||||
pixelsSRGB[colorAddr] = color_green
|
||||
}
|
||||
HiRes.pixelsSRGB[colorAddr + 1] = color_green
|
||||
pixelsSRGB[colorAddr + 1] = color_green
|
||||
|
||||
case 3: // white 1
|
||||
// if ( colorAddr >= 2 ) && ( HiRes.pixelsSRGB[colorAddr - 2] != color_black ) {
|
||||
|
@ -297,43 +327,43 @@ class HiRes: NSView {
|
|||
// if (colorAddr >= 1) {
|
||||
// HiRes.pixelsSRGB[colorAddr - 1] = color_yellow
|
||||
// }
|
||||
HiRes.pixelsSRGB[colorAddr] = color_white
|
||||
HiRes.pixelsSRGB[colorAddr + 1] = color_white
|
||||
pixelsSRGB[colorAddr] = color_white
|
||||
pixelsSRGB[colorAddr + 1] = color_white
|
||||
|
||||
case 5: // blue
|
||||
HiRes.pixelsSRGB[colorAddr] = color_blue
|
||||
pixelsSRGB[colorAddr] = color_blue
|
||||
if (colorAddr >= 1) && (prev != 0x00) && (prev != 0x04) {
|
||||
HiRes.pixelsSRGB[colorAddr - 1] = color_blue
|
||||
pixelsSRGB[colorAddr - 1] = color_blue
|
||||
}
|
||||
|
||||
case 6: // orange
|
||||
// reducing color bleeding
|
||||
if (colorAddr > 0) && (HiRes.pixelsSRGB[colorAddr - 1] != color_black) {
|
||||
HiRes.pixelsSRGB[colorAddr] = color_orange
|
||||
if (colorAddr > 0) && (pixelsSRGB[colorAddr - 1] != color_black) {
|
||||
pixelsSRGB[colorAddr] = color_orange
|
||||
}
|
||||
HiRes.pixelsSRGB[colorAddr + 1] = color_orange
|
||||
pixelsSRGB[colorAddr + 1] = color_orange
|
||||
|
||||
case 7: // white 2
|
||||
HiRes.pixelsSRGB[colorAddr] = color_white
|
||||
HiRes.pixelsSRGB[colorAddr + 1] = color_white
|
||||
pixelsSRGB[colorAddr] = color_white
|
||||
pixelsSRGB[colorAddr + 1] = color_white
|
||||
|
||||
default: // 0x00 (black 1), 0x04 (black 2)
|
||||
HiRes.pixelsSRGB[colorAddr] = color_black
|
||||
HiRes.pixelsSRGB[colorAddr + 1] = color_black
|
||||
pixelsSRGB[colorAddr] = color_black
|
||||
pixelsSRGB[colorAddr + 1] = color_black
|
||||
break
|
||||
}
|
||||
|
||||
// white adjustment
|
||||
if ( (prev & 2) == 2 ) && ( (pixel & 1) == 1 ) {
|
||||
HiRes.pixelsSRGB[colorAddr] = color_white
|
||||
pixelsSRGB[colorAddr] = color_white
|
||||
if (colorAddr >= 1) {
|
||||
HiRes.pixelsSRGB[colorAddr - 1] = color_white
|
||||
pixelsSRGB[colorAddr - 1] = color_white
|
||||
}
|
||||
|
||||
// TODO: Need better check if extra green was created
|
||||
if (colorAddr >= 2) && (HiRes.pixelsSRGB[colorAddr - 2] == color_green ) {
|
||||
if (colorAddr < 3) || (HiRes.pixelsSRGB[colorAddr - 3] != color_green) {
|
||||
HiRes.pixelsSRGB[colorAddr - 2] = color_black
|
||||
if (colorAddr >= 2) && (pixelsSRGB[colorAddr - 2] == color_green ) {
|
||||
if (colorAddr < 3) || (pixelsSRGB[colorAddr - 3] != color_green) {
|
||||
pixelsSRGB[colorAddr - 2] = color_black
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,8 +379,8 @@ class HiRes: NSView {
|
|||
(pixel == 0x03) || (pixel == 0x07) // white
|
||||
) {
|
||||
// was the previous purple pixel promoted to white or is it still purple?
|
||||
if (colorAddr >= 2) && ( HiRes.pixelsSRGB[colorAddr - 2] == color_purple ) {
|
||||
HiRes.pixelsSRGB[colorAddr - 1] = color_purple
|
||||
if (colorAddr >= 2) && ( pixelsSRGB[colorAddr - 2] == color_purple ) {
|
||||
pixelsSRGB[colorAddr - 1] = color_purple
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +389,7 @@ class HiRes: NSView {
|
|||
(pixel == 0x05) ||
|
||||
(pixel == 0x03) || (pixel == 0x07) // white
|
||||
) {
|
||||
HiRes.pixelsSRGB[colorAddr - 1] = color_blue
|
||||
pixelsSRGB[colorAddr - 1] = color_blue
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -388,7 +418,10 @@ class HiRes: NSView {
|
|||
|
||||
var y = 0
|
||||
|
||||
blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2)
|
||||
// blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2)
|
||||
|
||||
hires_clearChanges()
|
||||
|
||||
HiRes.context?.clear( CGRect(x: 0, y: 0, width: frame.width, height: frame.height) )
|
||||
|
||||
for lineAddr in HiResLineAddrTbl {
|
||||
|
@ -415,7 +448,7 @@ class HiRes: NSView {
|
|||
let screenIdx = y * HiRes.blockCols + blockHorIdx
|
||||
|
||||
// get all changed blocks
|
||||
blockChanged[ blockVertIdx + blockHorIdx ] = blockChanged[ blockVertIdx + blockHorIdx ] || shadowScreen[ screenIdx ] != block14
|
||||
blockChanged[ blockVertIdx + blockHorIdx ] = ((blockChanged[ blockVertIdx + blockHorIdx ] != 0) || (shadowScreen[ screenIdx ] != block14)) ? 1 : 0
|
||||
shadowScreen[ screenIdx ] = block14
|
||||
|
||||
for px in 0 ... 2 {
|
||||
|
|
|
@ -39,6 +39,38 @@ typedef enum {
|
|||
} RGBA_t;
|
||||
|
||||
|
||||
// HiRes Colors for the SRGB color space
|
||||
const uint32_t color_black = 0x00000000;
|
||||
const uint32_t color_white = 0xFFEEEEEE;
|
||||
const uint32_t color_purple = 0xFFDD55FF;
|
||||
const uint32_t color_green = 0xFF2BD84A;
|
||||
const uint32_t color_blue = 0xFF5599FF;
|
||||
const uint32_t color_orange = 0xFFFF6302;
|
||||
|
||||
// for debugging only:
|
||||
const uint32_t color_turquis = 0xFF11BBBB;
|
||||
const uint32_t color_yellow = 0xFFBBBB11;
|
||||
|
||||
// default is green
|
||||
const uint32_t color_mono = 0xFF2BD84A;
|
||||
|
||||
static const int ScreenBitmapSize = (PixelWidth * PixelHeight * 4);
|
||||
|
||||
const uint8_t color_R = 2;
|
||||
const uint8_t color_G = 1;
|
||||
const uint8_t color_B = 0;
|
||||
const uint8_t color_A = 3;
|
||||
|
||||
//static uint32_t pixelsSRGB[blockRows * blockCols];
|
||||
uint32_t * pixelsSRGB;
|
||||
static uint8_t _blockChanged[blockRows * blockCols];
|
||||
uint8_t * blockChanged = _blockChanged;
|
||||
static uint8_t _shadowScreen[PageSize];
|
||||
uint8_t * shadowScreen = _shadowScreen;
|
||||
|
||||
int was = 0;
|
||||
|
||||
|
||||
void initHiResLineAddresses() {
|
||||
int i = 0;
|
||||
|
||||
|
@ -52,3 +84,68 @@ void initHiResLineAddresses() {
|
|||
}
|
||||
|
||||
|
||||
void init() {
|
||||
initHiResLineAddresses();
|
||||
}
|
||||
|
||||
|
||||
void hires_clearChanges() {
|
||||
memset(_blockChanged, 0, sizeof(_blockChanged));
|
||||
}
|
||||
|
||||
|
||||
void hires_renderMono() {
|
||||
int height = PixelHeight;
|
||||
|
||||
// do not even render it...
|
||||
if( videoMode.text == 1 ) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if( videoMode.mixed == 1 ) {
|
||||
height = MixedHeight;
|
||||
}
|
||||
if( MEMcfg.txt_page_2 == 1 ) {
|
||||
HiResBufferPointer = (uint8_t*)HiResBuffer2;
|
||||
}
|
||||
else {
|
||||
HiResBufferPointer = (uint8_t*)HiResBuffer1;
|
||||
}
|
||||
}
|
||||
|
||||
int pixelAddr = 0;
|
||||
|
||||
hires_clearChanges();
|
||||
|
||||
for( int y = 0; y < height; y++ ) {
|
||||
int lineAddr = HiResLineAddrTbl[y];
|
||||
|
||||
int blockVertIdx = y / blockHeight * blockCols;
|
||||
|
||||
for( int blockHorIdx = 0; blockHorIdx < blockCols; blockHorIdx++ ) {
|
||||
int block = HiResBufferPointer[ lineAddr + blockHorIdx ];
|
||||
int screenIdx = y * blockCols + blockHorIdx;
|
||||
|
||||
// get all changed blocks
|
||||
_blockChanged[ blockVertIdx + blockHorIdx ] |= _shadowScreen[ screenIdx ] != block;
|
||||
_shadowScreen[ screenIdx ] = block;
|
||||
|
||||
for( int bit = 0; bit <= 6; bit++ ) {
|
||||
uint8_t bitMask = 1 << bit;
|
||||
if ( (block & bitMask) ) {
|
||||
pixelsSRGB[pixelAddr] = color_mono;
|
||||
}
|
||||
else {
|
||||
pixelsSRGB[pixelAddr] = color_black;
|
||||
}
|
||||
|
||||
pixelAddr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// refreshChanged(blockSize: 1)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,4 +11,12 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
extern uint32_t * pixelsSRGB;
|
||||
extern uint8_t * blockChanged;
|
||||
extern uint8_t * shadowScreen;
|
||||
|
||||
extern void hires_clearChanges(void);
|
||||
extern void hires_renderMono(void);
|
||||
|
||||
|
||||
#endif /* hires_h */
|
||||
|
|
Loading…
Reference in New Issue
Block a user