From 80cf3d9301c1fee98d79742f79dc4f407e594785 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 3 Sep 2015 12:28:16 -0400 Subject: [PATCH] Formally gave the 2600 responsibility for providing the code that decodes one of the things it has put into a buffer into a composite sample. --- Machines/Atari2600.cpp | 15 +++++- Machines/Atari2600.hpp | 2 + OSBindings/Mac/Clock Signal/CSAtari2600.h | 2 +- OSBindings/Mac/Clock Signal/CSAtari2600.mm | 5 ++ .../Mac/Clock Signal/CSCathodeRayView.h | 1 + .../Mac/Clock Signal/CSCathodeRayView.m | 51 +++++++++++++------ 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/Machines/Atari2600.cpp b/Machines/Atari2600.cpp index 24fba8389..5dafc6fcc 100644 --- a/Machines/Atari2600.cpp +++ b/Machines/Atari2600.cpp @@ -148,9 +148,22 @@ void Machine::get_output_pixel(uint8_t *pixel, int offset) // map that colour to separate Y and phase components pixel[0] = (outputColour << 4)&0xe0; - pixel[1] = outputColour&0xf0; + pixel[1] = outputColour&0xf0; } +const char *Machine::get_signal_decoder() +{ + return + "float sample(vec2 coordinate, float phase)\n" + "{\n" + "vec2 c = texture(texID, coordinate).rg;" + "float y = 0.1 + c.x * 0.91071428571429;\n" + "float aOffset = 6.283185308 * c.y;\n" + "return y + step(0.0625, c.y) * 0.1 * sin(phase + aOffset);\n" + "}"; +} + + // in imputing the knowledge that all we're dealing with is the rollover from 159 to 0, // this is faster than the straightforward +1)%160 per profiling #define increment_object_counter(c) _objectCounter[c] = (_objectCounter[c]+1)&~((158-_objectCounter[c]) >> 8) diff --git a/Machines/Atari2600.hpp b/Machines/Atari2600.hpp index 57718cd55..0e53f801b 100644 --- a/Machines/Atari2600.hpp +++ b/Machines/Atari2600.hpp @@ -32,6 +32,8 @@ class Machine: public CPU6502::Processor { Outputs::CRT *get_crt() { return _crt; } + const char *get_signal_decoder(); + private: uint8_t *_rom, *_romPages[4], _ram[128]; size_t _rom_size; diff --git a/OSBindings/Mac/Clock Signal/CSAtari2600.h b/OSBindings/Mac/Clock Signal/CSAtari2600.h index 004ba63a4..3f67fe2f7 100644 --- a/OSBindings/Mac/Clock Signal/CSAtari2600.h +++ b/OSBindings/Mac/Clock Signal/CSAtari2600.h @@ -15,7 +15,7 @@ @property (nonatomic, weak) CSCathodeRayView *view; - (void)runForNumberOfCycles:(int)cycles; -- (void)setROM:(NSData *)rom; +- (void)setROM:(NSData * __nonnull)rom; - (void)setState:(BOOL)state forDigitalInput:(Atari2600DigitalInput)digitalInput; - (void)setResetLineEnabled:(BOOL)enabled; diff --git a/OSBindings/Mac/Clock Signal/CSAtari2600.mm b/OSBindings/Mac/Clock Signal/CSAtari2600.mm index 98edbed40..a2b9a52f5 100644 --- a/OSBindings/Mac/Clock Signal/CSAtari2600.mm +++ b/OSBindings/Mac/Clock Signal/CSAtari2600.mm @@ -93,6 +93,11 @@ typedef NS_ENUM(NSInteger, CSAtari2600RunningState) { }); } +- (void)setView:(CSCathodeRayView *)view { + _view = view; + _view.signalDecoder = [NSString stringWithUTF8String:_atari2600.get_signal_decoder()]; +} + - (instancetype)init { self = [super init]; diff --git a/OSBindings/Mac/Clock Signal/CSCathodeRayView.h b/OSBindings/Mac/Clock Signal/CSCathodeRayView.h index a7f63ed0f..4781bdbfa 100644 --- a/OSBindings/Mac/Clock Signal/CSCathodeRayView.h +++ b/OSBindings/Mac/Clock Signal/CSCathodeRayView.h @@ -30,5 +30,6 @@ - (void)invalidate; - (BOOL)pushFrame:(CRTFrame * __nonnull)crtFrame; +- (void)setSignalDecoder:(NSString * __nonnull)signalDecoder; @end diff --git a/OSBindings/Mac/Clock Signal/CSCathodeRayView.m b/OSBindings/Mac/Clock Signal/CSCathodeRayView.m index f2494471c..6a1c53f97 100644 --- a/OSBindings/Mac/Clock Signal/CSCathodeRayView.m +++ b/OSBindings/Mac/Clock Signal/CSCathodeRayView.m @@ -10,6 +10,7 @@ @import CoreVideo; #import #import +#import @implementation CSCathodeRayView { @@ -30,6 +31,10 @@ CRTSize _textureSize; CRTFrame *_crtFrame; + + NSString *_signalDecoder; + int32_t _signalDecoderGeneration; + int32_t _compiledSignalDecoderGeneration; } - (void)prepareOpenGL @@ -52,7 +57,6 @@ // get the shader ready, set the clear colour [self.openGLContext makeCurrentContext]; glClearColor(0.0, 0.0, 0.0, 1.0); - [self prepareShader]; // Activate the display link CVDisplayLinkStart(displayLink); @@ -172,8 +176,8 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt // the main job of the vertex shader is just to map from an input area of [0,1]x[0,1], with the origin in the // top left to OpenGL's [-1,1]x[-1,1] with the origin in the lower left, and to convert input data coordinates // from integral to floating point. -const char *vertexShader = - "#version 150\n" +static NSString *const vertexShader = + @"#version 150\n" "\n" "in vec2 position;\n" "in vec2 srcCoordinates;\n" @@ -201,8 +205,8 @@ const char *vertexShader = // TODO: this should be factored out and be per project -const char *fragmentShader = - "#version 150\n" +static NSString *const fragmentShader = + @"#version 150\n" "\n" "in vec2 srcCoordinatesVarying[7];\n" "in float lateralVarying;\n" @@ -212,13 +216,7 @@ const char *fragmentShader = "uniform sampler2D texID;\n" "uniform float alpha;\n" "\n" - "float sample(vec2 coordinate, float angle)\n" - "{\n" - "vec2 c = texture(texID, coordinate).rg;" - "float y = 0.1 + c.x * 0.91071428571429;\n" - "float aOffset = 6.283185308 * c.y;\n" - "return y + step(0.0625, c.y) * 0.1 * sin(angle + aOffset);\n" - "}\n" + "%@" "\n" "void main(void)\n" "{\n" @@ -230,12 +228,12 @@ const char *fragmentShader = "angles[1] = angle + vec4(2.5132741232, 5.6548667772, 0.6283185308, 0.0);\n" "\n" "samples[0] = vec4(" - " sample(srcCoordinatesVarying[0], angles[0].x)," + " sample(srcCoordinatesVarying[0], angles[0].x)," " sample(srcCoordinatesVarying[1], angles[0].y)," " sample(srcCoordinatesVarying[2], angles[0].z)," " sample(srcCoordinatesVarying[3], angles[0].w));\n" "samples[1] = vec4(" - " sample(srcCoordinatesVarying[4], angles[1].x)," + " sample(srcCoordinatesVarying[4], angles[1].x)," " sample(srcCoordinatesVarying[5], angles[1].y)," " sample(srcCoordinatesVarying[6], angles[1].z)," " 1.0);\n" @@ -279,11 +277,27 @@ const char *fragmentShader = return shader; } +- (void)setSignalDecoder:(NSString * __nonnull)signalDecoder +{ + _signalDecoder = [signalDecoder copy]; + OSAtomicIncrement32(&_signalDecoderGeneration); +} + - (void)prepareShader { + if(_shaderProgram) + { + glDeleteProgram(_shaderProgram); + glDeleteShader(_vertexShader); + glDeleteShader(_fragmentShader); + } + + if(!_signalDecoder) + return; + _shaderProgram = glCreateProgram(); - _vertexShader = [self compileShader:vertexShader type:GL_VERTEX_SHADER]; - _fragmentShader = [self compileShader:fragmentShader type:GL_FRAGMENT_SHADER]; + _vertexShader = [self compileShader:[vertexShader UTF8String] type:GL_VERTEX_SHADER]; + _fragmentShader = [self compileShader:[[NSString stringWithFormat:fragmentShader, _signalDecoder] UTF8String] type:GL_FRAGMENT_SHADER]; glAttachShader(_shaderProgram, _vertexShader); glAttachShader(_shaderProgram, _fragmentShader); @@ -334,6 +348,11 @@ const char *fragmentShader = [self.openGLContext makeCurrentContext]; CGLLockContext([[self openGLContext] CGLContextObj]); + while(!_shaderProgram || (_signalDecoderGeneration != _compiledSignalDecoderGeneration)) { + _compiledSignalDecoderGeneration = _signalDecoderGeneration; + [self prepareShader]; + } + glClear(GL_COLOR_BUFFER_BIT); if (_crtFrame)