Old CRT monitor effect: Pixel trail

This commit is contained in:
tudnai 2021-06-06 13:17:02 -07:00
parent fd3ead734b
commit 5d82b7569e
5 changed files with 184 additions and 38 deletions

View File

@ -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;
};

View File

@ -33,5 +33,7 @@
#import "disk.h"
#import "dsk2woz.h"
#import "mmio.h"
#import "hires.h"
#endif /* A2Mac_Bridging_Header_h */

View File

@ -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 {

View File

@ -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)
}

View File

@ -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 */