mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Started working on a shell for the Electron emulation, including factoring out the common CRT delegate -> Objective-C bridging, serial dispatch queue and frameskipping logic from the Atari 2600 shell.
This commit is contained in:
parent
22fa024546
commit
ab45c1d530
@ -9,8 +9,8 @@
|
||||
#ifndef Atari2600_cpp
|
||||
#define Atari2600_cpp
|
||||
|
||||
#include "../Processors/6502/CPU6502.hpp"
|
||||
#include "../Outputs/CRT.hpp"
|
||||
#include "../../Processors/6502/CPU6502.hpp"
|
||||
#include "../../Outputs/CRT.hpp"
|
||||
#include <stdint.h>
|
||||
#include "Atari2600Inputs.h"
|
||||
|
24
Machines/Electron/Electron.cpp
Normal file
24
Machines/Electron/Electron.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Electron.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 03/01/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Electron.hpp"
|
||||
|
||||
using namespace Electron;
|
||||
|
||||
Machine::Machine()
|
||||
{
|
||||
}
|
||||
|
||||
Machine::~Machine()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
|
||||
{
|
||||
return 1;
|
||||
}
|
32
Machines/Electron/Electron.hpp
Normal file
32
Machines/Electron/Electron.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// Electron.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 03/01/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Electron_hpp
|
||||
#define Electron_hpp
|
||||
|
||||
#include "../../Processors/6502/CPU6502.hpp"
|
||||
#include "../../Outputs/CRT.hpp"
|
||||
#include <stdint.h>
|
||||
#include "Atari2600Inputs.h"
|
||||
|
||||
namespace Electron {
|
||||
|
||||
class Machine: public CPU6502::Processor<Machine> {
|
||||
|
||||
public:
|
||||
|
||||
Machine();
|
||||
~Machine();
|
||||
|
||||
unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* Electron_hpp */
|
@ -7,9 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
4B14144E1B5883E500E04248 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B14144B1B5883E500E04248 /* CSAtari2600.mm */; };
|
||||
4B14144F1B5883E500E04248 /* CSCathodeRayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B14144D1B5883E500E04248 /* CSCathodeRayView.m */; };
|
||||
4B1414511B5885DF00E04248 /* Atari2600.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6D7F921B58822000787C9A /* Atari2600.cpp */; };
|
||||
4B14145B1B58879D00E04248 /* CPU6502.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414571B58879D00E04248 /* CPU6502.cpp */; };
|
||||
4B14145D1B5887A600E04248 /* CPU6502.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414571B58879D00E04248 /* CPU6502.cpp */; };
|
||||
4B14145E1B5887AA00E04248 /* CPU6502AllRAM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414591B58879D00E04248 /* CPU6502AllRAM.cpp */; };
|
||||
@ -17,7 +15,11 @@
|
||||
4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414611B58888700E04248 /* KlausDormannTests.swift */; };
|
||||
4B2E2D921C399B9900138695 /* ElectronDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D911C399B9900138695 /* ElectronDocument.swift */; };
|
||||
4B2E2D951C399D1200138695 /* ElectronDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E2D931C399D1200138695 /* ElectronDocument.xib */; };
|
||||
4B2E2D9A1C3A06EC00138695 /* Atari2600.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D971C3A06EC00138695 /* Atari2600.cpp */; };
|
||||
4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E2D9B1C3A070400138695 /* Electron.cpp */; };
|
||||
4B366DFC1B5C165A0026627B /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B366DFA1B5C165A0026627B /* CRT.cpp */; };
|
||||
4B55CE4B1C3B3B0C0093A61B /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B55CE4A1C3B3B0C0093A61B /* CSAtari2600.mm */; };
|
||||
4B55CE4E1C3B3BDA0093A61B /* CSMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B55CE4D1C3B3BDA0093A61B /* CSMachine.mm */; };
|
||||
4B92EACA1B7C112B00246143 /* TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* TimingTests.swift */; };
|
||||
4BB298EE1B587D8400A49093 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */; };
|
||||
4BB298EF1B587D8400A49093 /* AllSuiteA.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E11B587D8300A49093 /* AllSuiteA.bin */; };
|
||||
@ -314,8 +316,6 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
4B14144A1B5883E500E04248 /* CSAtari2600.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSAtari2600.h; sourceTree = "<group>"; };
|
||||
4B14144B1B5883E500E04248 /* CSAtari2600.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CSAtari2600.mm; sourceTree = "<group>"; };
|
||||
4B14144C1B5883E500E04248 /* CSCathodeRayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCathodeRayView.h; sourceTree = "<group>"; };
|
||||
4B14144D1B5883E500E04248 /* CSCathodeRayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSCathodeRayView.m; sourceTree = "<group>"; };
|
||||
4B1414501B58848C00E04248 /* ClockSignal-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ClockSignal-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
@ -328,12 +328,19 @@
|
||||
4B2632551B631A510082A461 /* CRTFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CRTFrame.h; path = ../../Outputs/CRTFrame.h; sourceTree = "<group>"; };
|
||||
4B2E2D911C399B9900138695 /* ElectronDocument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElectronDocument.swift; sourceTree = "<group>"; };
|
||||
4B2E2D941C399D1200138695 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ElectronDocument.xib; sourceTree = "<group>"; };
|
||||
4B2E2D971C3A06EC00138695 /* Atari2600.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Atari2600.cpp; sourceTree = "<group>"; };
|
||||
4B2E2D981C3A06EC00138695 /* Atari2600.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Atari2600.hpp; sourceTree = "<group>"; };
|
||||
4B2E2D991C3A06EC00138695 /* Atari2600Inputs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atari2600Inputs.h; sourceTree = "<group>"; };
|
||||
4B2E2D9B1C3A070400138695 /* Electron.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Electron.cpp; path = Electron/Electron.cpp; sourceTree = "<group>"; };
|
||||
4B2E2D9C1C3A070400138695 /* Electron.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Electron.hpp; path = Electron/Electron.hpp; sourceTree = "<group>"; };
|
||||
4B366DFA1B5C165A0026627B /* CRT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CRT.cpp; path = ../../Outputs/CRT.cpp; sourceTree = "<group>"; };
|
||||
4B366DFB1B5C165A0026627B /* CRT.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRT.hpp; path = ../../Outputs/CRT.hpp; sourceTree = "<group>"; };
|
||||
4B6D7F921B58822000787C9A /* Atari2600.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Atari2600.cpp; sourceTree = "<group>"; };
|
||||
4B6D7F931B58822000787C9A /* Atari2600.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Atari2600.hpp; sourceTree = "<group>"; };
|
||||
4B55CE491C3B3B0C0093A61B /* CSAtari2600.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSAtari2600.h; sourceTree = "<group>"; };
|
||||
4B55CE4A1C3B3B0C0093A61B /* CSAtari2600.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CSAtari2600.mm; sourceTree = "<group>"; };
|
||||
4B55CE4C1C3B3BDA0093A61B /* CSMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSMachine.h; sourceTree = "<group>"; };
|
||||
4B55CE4D1C3B3BDA0093A61B /* CSMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CSMachine.mm; sourceTree = "<group>"; };
|
||||
4B55CE4F1C3B78A80093A61B /* CSMachine+Subclassing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CSMachine+Subclassing.h"; sourceTree = "<group>"; };
|
||||
4B92EAC91B7C112B00246143 /* TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimingTests.swift; sourceTree = "<group>"; };
|
||||
4BA3921C1B8402B3007FBF0E /* Atari2600Inputs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Atari2600Inputs.h; sourceTree = "<group>"; };
|
||||
4BB297DF1B587D8200A49093 /* Clock SignalTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Clock SignalTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
4BB297E01B587D8300A49093 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = "<group>"; };
|
||||
4BB297E11B587D8300A49093 /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = AllSuiteA.bin; sourceTree = "<group>"; };
|
||||
@ -666,6 +673,25 @@
|
||||
name = "Test Binaries";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B2E2D961C3A06EC00138695 /* Atari2600 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B2E2D971C3A06EC00138695 /* Atari2600.cpp */,
|
||||
4B2E2D981C3A06EC00138695 /* Atari2600.hpp */,
|
||||
4B2E2D991C3A06EC00138695 /* Atari2600Inputs.h */,
|
||||
);
|
||||
path = Atari2600;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B2E2D9E1C3A070900138695 /* Electron */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B2E2D9B1C3A070400138695 /* Electron.cpp */,
|
||||
4B2E2D9C1C3A070400138695 /* Electron.hpp */,
|
||||
);
|
||||
name = Electron;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B366DFD1B5C165F0026627B /* Outputs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -676,6 +702,18 @@
|
||||
name = Outputs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B55CE481C3B3B0C0093A61B /* Wrappers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B55CE491C3B3B0C0093A61B /* CSAtari2600.h */,
|
||||
4B55CE4A1C3B3B0C0093A61B /* CSAtari2600.mm */,
|
||||
4B55CE4C1C3B3BDA0093A61B /* CSMachine.h */,
|
||||
4B55CE4D1C3B3BDA0093A61B /* CSMachine.mm */,
|
||||
4B55CE4F1C3B78A80093A61B /* CSMachine+Subclassing.h */,
|
||||
);
|
||||
path = Wrappers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -974,10 +1012,9 @@
|
||||
4BB73EA01B587A5100552FC2 /* Clock Signal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B55CE481C3B3B0C0093A61B /* Wrappers */,
|
||||
4B2E2D931C399D1200138695 /* ElectronDocument.xib */,
|
||||
4B1414501B58848C00E04248 /* ClockSignal-Bridging-Header.h */,
|
||||
4B14144A1B5883E500E04248 /* CSAtari2600.h */,
|
||||
4B14144B1B5883E500E04248 /* CSAtari2600.mm */,
|
||||
4B14144C1B5883E500E04248 /* CSCathodeRayView.h */,
|
||||
4B14144D1B5883E500E04248 /* CSCathodeRayView.m */,
|
||||
4BB73ECF1B587A6700552FC2 /* Clock Signal.entitlements */,
|
||||
@ -1020,9 +1057,8 @@
|
||||
4BB73EDC1B587CA500552FC2 /* Machines */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B6D7F921B58822000787C9A /* Atari2600.cpp */,
|
||||
4B6D7F931B58822000787C9A /* Atari2600.hpp */,
|
||||
4BA3921C1B8402B3007FBF0E /* Atari2600Inputs.h */,
|
||||
4B2E2D961C3A06EC00138695 /* Atari2600 */,
|
||||
4B2E2D9E1C3A070900138695 /* Electron */,
|
||||
);
|
||||
name = Machines;
|
||||
path = ../../Machines;
|
||||
@ -1441,10 +1477,12 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4B1414511B5885DF00E04248 /* Atari2600.cpp in Sources */,
|
||||
4B55CE4B1C3B3B0C0093A61B /* CSAtari2600.mm in Sources */,
|
||||
4B55CE4E1C3B3BDA0093A61B /* CSMachine.mm in Sources */,
|
||||
4B2E2D9D1C3A070400138695 /* Electron.cpp in Sources */,
|
||||
4B366DFC1B5C165A0026627B /* CRT.cpp in Sources */,
|
||||
4B2E2D9A1C3A06EC00138695 /* Atari2600.cpp in Sources */,
|
||||
4BB73EA41B587A5100552FC2 /* Atari2600Document.swift in Sources */,
|
||||
4B14144E1B5883E500E04248 /* CSAtari2600.mm in Sources */,
|
||||
4B2E2D921C399B9900138695 /* ElectronDocument.swift in Sources */,
|
||||
4B14145B1B58879D00E04248 /* CPU6502.cpp in Sources */,
|
||||
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */,
|
||||
|
@ -16,10 +16,10 @@ class Atari2600Document: NSDocument, CSCathodeRayViewDelegate, CSCathodeRayViewR
|
||||
|
||||
openGLView.delegate = self
|
||||
openGLView.responderDelegate = self
|
||||
atari2600!.view = openGLView!
|
||||
atari2600.view = openGLView
|
||||
|
||||
// bind the content aspect ratio to remain 4:3 from now on
|
||||
aController.window!.contentAspectRatio = NSSize(width: 4.0, height: 3.0)
|
||||
aController.window?.contentAspectRatio = NSSize(width: 4.0, height: 3.0)
|
||||
}
|
||||
|
||||
override class func autosavesInPlace() -> Bool {
|
||||
@ -32,7 +32,7 @@ class Atari2600Document: NSDocument, CSCathodeRayViewDelegate, CSCathodeRayViewR
|
||||
return "Atari2600Document"
|
||||
}
|
||||
|
||||
private var atari2600: CSAtari2600? = nil
|
||||
private var atari2600: CSAtari2600! = nil
|
||||
override func dataOfType(typeName: String) throws -> NSData {
|
||||
// Insert code here to write your document to data of the specified type. If outError != nil, ensure that you create and set an appropriate error when returning nil.
|
||||
// You can also choose to override fileWrapperOfType:error:, writeToURL:ofType:error:, or writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
|
||||
@ -41,7 +41,7 @@ class Atari2600Document: NSDocument, CSCathodeRayViewDelegate, CSCathodeRayViewR
|
||||
|
||||
override func readFromData(data: NSData, ofType typeName: String) throws {
|
||||
atari2600 = CSAtari2600()
|
||||
atari2600!.setROM(data)
|
||||
atari2600.setROM(data)
|
||||
}
|
||||
|
||||
override func close() {
|
||||
@ -66,7 +66,7 @@ class Atari2600Document: NSDocument, CSCathodeRayViewDelegate, CSCathodeRayViewR
|
||||
let cycleCount = cycleCountLow + cycleCountHigh
|
||||
if let lastCycleCount = lastCycleCount {
|
||||
let elapsedTime = cycleCount - lastCycleCount
|
||||
atari2600!.runForNumberOfCycles(Int32(elapsedTime))
|
||||
atari2600.runForNumberOfCycles(Int32(elapsedTime))
|
||||
}
|
||||
lastCycleCount = cycleCount
|
||||
}
|
||||
@ -86,21 +86,21 @@ class Atari2600Document: NSDocument, CSCathodeRayViewDelegate, CSCathodeRayViewR
|
||||
|
||||
func keyDown(event: NSEvent) {
|
||||
if let input = inputForKey(event) {
|
||||
atari2600!.setState(true, forDigitalInput: input)
|
||||
atari2600.setState(true, forDigitalInput: input)
|
||||
}
|
||||
|
||||
if event.keyCode == 36 {
|
||||
atari2600!.setResetLineEnabled(true)
|
||||
atari2600.setResetLineEnabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
func keyUp(event: NSEvent) {
|
||||
if let input = inputForKey(event) {
|
||||
atari2600!.setState(false, forDigitalInput: input)
|
||||
atari2600.setState(false, forDigitalInput: input)
|
||||
}
|
||||
|
||||
if event.keyCode == 36 {
|
||||
atari2600!.setResetLineEnabled(false)
|
||||
atari2600.setResetLineEnabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,114 +0,0 @@
|
||||
//
|
||||
// Atari2600.m
|
||||
// CLK
|
||||
//
|
||||
// Created by Thomas Harte on 14/07/2015.
|
||||
// Copyright © 2015 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CSAtari2600.h"
|
||||
#import "Atari2600.hpp"
|
||||
|
||||
@interface CSAtari2600 (Callbacks)
|
||||
- (void)crtDidEndFrame:(CRTFrame *)frame didDetectVSync:(BOOL)didDetectVSync;
|
||||
@end
|
||||
|
||||
struct Atari2600CRTDelegate: public Outputs::CRT::CRTDelegate {
|
||||
__weak CSAtari2600 *atari;
|
||||
void crt_did_end_frame(Outputs::CRT *crt, CRTFrame *frame, bool did_detect_vsync) { [atari crtDidEndFrame:frame didDetectVSync:did_detect_vsync]; }
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSAtari2600RunningState) {
|
||||
CSAtari2600RunningStateRunning,
|
||||
CSAtari2600RunningStateStopped
|
||||
};
|
||||
|
||||
@implementation CSAtari2600 {
|
||||
Atari2600::Machine _atari2600;
|
||||
Atari2600CRTDelegate _crtDelegate;
|
||||
|
||||
dispatch_queue_t _serialDispatchQueue;
|
||||
|
||||
int _frameCount;
|
||||
int _hitCount;
|
||||
BOOL _didDecideRegion;
|
||||
|
||||
NSConditionLock *_runningLock;
|
||||
}
|
||||
|
||||
- (void)crtDidEndFrame:(CRTFrame *)frame didDetectVSync:(BOOL)didDetectVSync {
|
||||
|
||||
if(!_didDecideRegion)
|
||||
{
|
||||
_frameCount++;
|
||||
_hitCount += didDetectVSync ? 1 : 0;
|
||||
|
||||
if(_frameCount > 30)
|
||||
{
|
||||
if(_hitCount < _frameCount >> 1)
|
||||
{
|
||||
_atari2600.switch_region();
|
||||
_didDecideRegion = YES;
|
||||
}
|
||||
|
||||
if(_hitCount > (_frameCount * 7) >> 3)
|
||||
{
|
||||
_didDecideRegion = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL hasReturn = [self.view pushFrame:frame];
|
||||
|
||||
if(hasReturn)
|
||||
_atari2600.get_crt()->return_frame();
|
||||
}
|
||||
|
||||
- (void)runForNumberOfCycles:(int)cycles {
|
||||
if([_runningLock tryLockWhenCondition:CSAtari2600RunningStateStopped]) {
|
||||
[_runningLock unlockWithCondition:CSAtari2600RunningStateRunning];
|
||||
dispatch_async(_serialDispatchQueue, ^{
|
||||
[_runningLock lockWhenCondition:CSAtari2600RunningStateRunning];
|
||||
_atari2600.run_for_cycles(cycles);
|
||||
[_runningLock unlockWithCondition:CSAtari2600RunningStateStopped];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setROM:(NSData *)rom {
|
||||
dispatch_async(_serialDispatchQueue, ^{
|
||||
_atari2600.set_rom(rom.length, (const uint8_t *)rom.bytes);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setState:(BOOL)state forDigitalInput:(Atari2600DigitalInput)digitalInput {
|
||||
dispatch_async(_serialDispatchQueue, ^{
|
||||
_atari2600.set_digital_input(digitalInput, state ? true : false);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setResetLineEnabled:(BOOL)enabled {
|
||||
dispatch_async(_serialDispatchQueue, ^{
|
||||
_atari2600.set_reset_line(enabled ? true : false);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setView:(CSCathodeRayView *)view {
|
||||
_view = view;
|
||||
[_view setSignalDecoder:[NSString stringWithUTF8String:_atari2600.get_signal_decoder()] type:CSCathodeRayViewSignalTypeNTSC];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_crtDelegate.atari = self;
|
||||
_atari2600.get_crt()->set_delegate(&_crtDelegate);
|
||||
_serialDispatchQueue = dispatch_queue_create("Atari 2600 queue", DISPATCH_QUEUE_SERIAL);
|
||||
_runningLock = [[NSConditionLock alloc] initWithCondition:CSAtari2600RunningStateStopped];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
@ -10,6 +10,10 @@ import Foundation
|
||||
|
||||
class ElectronDocument: NSDocument, CSCathodeRayViewResponderDelegate, CSCathodeRayViewDelegate {
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
@IBOutlet weak var openGLView: CSCathodeRayView!
|
||||
override func windowControllerDidLoadNib(aController: NSWindowController) {
|
||||
super.windowControllerDidLoadNib(aController)
|
||||
@ -27,6 +31,7 @@ class ElectronDocument: NSDocument, CSCathodeRayViewResponderDelegate, CSCathode
|
||||
}
|
||||
|
||||
override func readFromData(data: NSData, ofType typeName: String) throws {
|
||||
print("H")
|
||||
}
|
||||
|
||||
override func close() {
|
||||
|
@ -9,14 +9,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "CSCathodeRayView.h"
|
||||
#include "Atari2600Inputs.h"
|
||||
#include "CSMachine.h"
|
||||
|
||||
@interface CSAtari2600 : NSObject
|
||||
@interface CSAtari2600 : CSMachine
|
||||
|
||||
@property (nonatomic, weak) CSCathodeRayView *view;
|
||||
|
||||
- (void)runForNumberOfCycles:(int)cycles;
|
||||
- (void)setROM:(nonnull NSData *)rom;
|
||||
|
||||
- (void)setState:(BOOL)state forDigitalInput:(Atari2600DigitalInput)digitalInput;
|
||||
- (void)setResetLineEnabled:(BOOL)enabled;
|
||||
|
77
OSBindings/Mac/Clock Signal/Wrappers/CSAtari2600.mm
Normal file
77
OSBindings/Mac/Clock Signal/Wrappers/CSAtari2600.mm
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// Atari2600.m
|
||||
// CLK
|
||||
//
|
||||
// Created by Thomas Harte on 14/07/2015.
|
||||
// Copyright © 2015 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CSAtari2600.h"
|
||||
|
||||
#import "Atari2600.hpp"
|
||||
#import "CSMachine+Subclassing.h"
|
||||
|
||||
@implementation CSAtari2600 {
|
||||
Atari2600::Machine _atari2600;
|
||||
|
||||
int _frameCount;
|
||||
int _hitCount;
|
||||
BOOL _didDecideRegion;
|
||||
}
|
||||
|
||||
- (void)crt:(Outputs::CRT *)crt didEndFrame:(CRTFrame *)frame didDetectVSync:(BOOL)didDetectVSync {
|
||||
if(!_didDecideRegion)
|
||||
{
|
||||
_frameCount++;
|
||||
_hitCount += didDetectVSync ? 1 : 0;
|
||||
|
||||
if(_frameCount > 30)
|
||||
{
|
||||
if(_hitCount < _frameCount >> 1)
|
||||
{
|
||||
_atari2600.switch_region();
|
||||
_didDecideRegion = YES;
|
||||
}
|
||||
|
||||
if(_hitCount > (_frameCount * 7) >> 3)
|
||||
{
|
||||
_didDecideRegion = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[super crt:crt didEndFrame:frame didDetectVSync:didDetectVSync];
|
||||
}
|
||||
|
||||
- (void)doRunForNumberOfCycles:(int)numberOfCycles {
|
||||
_atari2600.run_for_cycles(numberOfCycles);
|
||||
}
|
||||
|
||||
- (void)setROM:(NSData *)rom {
|
||||
[self perform:^{
|
||||
_atari2600.set_rom(rom.length, (const uint8_t *)rom.bytes);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setState:(BOOL)state forDigitalInput:(Atari2600DigitalInput)digitalInput {
|
||||
[self perform:^{
|
||||
_atari2600.set_digital_input(digitalInput, state ? true : false);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setResetLineEnabled:(BOOL)enabled {
|
||||
[self perform:^{
|
||||
_atari2600.set_reset_line(enabled ? true : false);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setView:(CSCathodeRayView *)view {
|
||||
[super setView:view];
|
||||
[view setSignalDecoder:[NSString stringWithUTF8String:_atari2600.get_signal_decoder()] type:CSCathodeRayViewSignalTypeNTSC];
|
||||
}
|
||||
|
||||
- (void)setCRTDelegate:(Outputs::CRT::CRTDelegate *)delegate{
|
||||
_atari2600.get_crt()->set_delegate(delegate);
|
||||
}
|
||||
|
||||
@end
|
20
OSBindings/Mac/Clock Signal/Wrappers/CSMachine+Subclassing.h
Normal file
20
OSBindings/Mac/Clock Signal/Wrappers/CSMachine+Subclassing.h
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// CSMachine+Subclassing.h
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 04/01/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CSMachine.h"
|
||||
#include "../../../../Outputs/CRT.hpp"
|
||||
|
||||
@interface CSMachine (Subclassing)
|
||||
|
||||
- (void)setCRTDelegate:(Outputs::CRT::CRTDelegate *)delegate;
|
||||
- (void)doRunForNumberOfCycles:(int)numberOfCycles;
|
||||
- (void)crt:(Outputs::CRT *)crt didEndFrame:(CRTFrame *)frame didDetectVSync:(BOOL)didDetectVSync;
|
||||
|
||||
- (void)perform:(dispatch_block_t)action;
|
||||
|
||||
@end
|
18
OSBindings/Mac/Clock Signal/Wrappers/CSMachine.h
Normal file
18
OSBindings/Mac/Clock Signal/Wrappers/CSMachine.h
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// CSMachine.h
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 04/01/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "CSCathodeRayView.h"
|
||||
|
||||
@interface CSMachine : NSObject
|
||||
|
||||
- (void)runForNumberOfCycles:(int)numberOfCycles;
|
||||
|
||||
@property (nonatomic, weak) CSCathodeRayView *view;
|
||||
|
||||
@end
|
63
OSBindings/Mac/Clock Signal/Wrappers/CSMachine.mm
Normal file
63
OSBindings/Mac/Clock Signal/Wrappers/CSMachine.mm
Normal file
@ -0,0 +1,63 @@
|
||||
//
|
||||
// CSMachine.m
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 04/01/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CSMachine.h"
|
||||
#import "CSMachine+Subclassing.h"
|
||||
|
||||
struct CRTDelegate: public Outputs::CRT::CRTDelegate {
|
||||
__weak CSMachine *machine;
|
||||
void crt_did_end_frame(Outputs::CRT *crt, CRTFrame *frame, bool did_detect_vsync) {
|
||||
[machine crt:crt didEndFrame:frame didDetectVSync:did_detect_vsync];
|
||||
}
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSAtari2600RunningState) {
|
||||
CSMachineRunningStateRunning,
|
||||
CSMachineRunningStateStopped
|
||||
};
|
||||
|
||||
@implementation CSMachine {
|
||||
CRTDelegate _crtDelegate;
|
||||
|
||||
dispatch_queue_t _serialDispatchQueue;
|
||||
NSConditionLock *_runningLock;
|
||||
}
|
||||
|
||||
- (void)perform:(dispatch_block_t)action {
|
||||
dispatch_async(_serialDispatchQueue, action);
|
||||
}
|
||||
|
||||
- (void)crt:(Outputs::CRT *)crt didEndFrame:(CRTFrame *)frame didDetectVSync:(BOOL)didDetectVSync {
|
||||
if([self.view pushFrame:frame]) crt->return_frame();
|
||||
}
|
||||
|
||||
- (void)runForNumberOfCycles:(int)cycles {
|
||||
if([_runningLock tryLockWhenCondition:CSMachineRunningStateStopped]) {
|
||||
[_runningLock unlockWithCondition:CSMachineRunningStateRunning];
|
||||
dispatch_async(_serialDispatchQueue, ^{
|
||||
[_runningLock lockWhenCondition:CSMachineRunningStateRunning];
|
||||
[self doRunForNumberOfCycles:cycles];
|
||||
[_runningLock unlockWithCondition:CSMachineRunningStateStopped];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_crtDelegate.machine = self;
|
||||
[self setCRTDelegate:&_crtDelegate];
|
||||
_serialDispatchQueue = dispatch_queue_create("Machine queue", DISPATCH_QUEUE_SERIAL);
|
||||
_runningLock = [[NSConditionLock alloc] initWithCondition:CSMachineRunningStateStopped];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue
Block a user