mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Attempted to bring frequency-switching logic into the cross-platform realm. Which for now creates an issue with the OpenGL context.
This commit is contained in:
parent
51bcaea60c
commit
99a35266e1
@ -21,7 +21,9 @@ Machine::Machine() :
|
||||
rom_pages_{nullptr, nullptr, nullptr, nullptr},
|
||||
tia_input_value_{0xff, 0xff},
|
||||
cycles_since_speaker_update_(0),
|
||||
cycles_since_video_update_(0)
|
||||
cycles_since_video_update_(0),
|
||||
frame_record_pointer_(0),
|
||||
is_ntsc_(true)
|
||||
{
|
||||
set_clock_rate(NTSC_clock_rate);
|
||||
}
|
||||
@ -31,6 +33,7 @@ void Machine::setup_output(float aspect_ratio)
|
||||
tia_.reset(new TIA);
|
||||
speaker_.reset(new Speaker);
|
||||
speaker_->set_input_rate((float)(get_clock_rate() / 38.0));
|
||||
tia_->get_crt()->set_delegate(this);
|
||||
}
|
||||
|
||||
void Machine::close_output()
|
||||
@ -288,3 +291,45 @@ void Machine::synchronise()
|
||||
update_video();
|
||||
speaker_->flush();
|
||||
}
|
||||
|
||||
#pragma mark - CRT delegate
|
||||
|
||||
void Machine::crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs)
|
||||
{
|
||||
frame_records_[frame_record_pointer_].number_of_frames = number_of_frames;
|
||||
frame_records_[frame_record_pointer_].number_of_unexpected_vertical_syncs = number_of_unexpected_vertical_syncs;
|
||||
const size_t number_of_frame_records = sizeof(frame_records_) / sizeof(frame_records_[0]);
|
||||
frame_record_pointer_ = (frame_record_pointer_ + 1) % number_of_frame_records;
|
||||
|
||||
unsigned int total_number_of_frames = 0;
|
||||
unsigned int total_number_of_unexpected_vertical_syncs = 0;
|
||||
for(size_t c = 0; c < number_of_frame_records; c++)
|
||||
{
|
||||
if(!frame_records_[c].number_of_frames) return;
|
||||
total_number_of_frames += frame_records_[c].number_of_frames;
|
||||
total_number_of_unexpected_vertical_syncs += frame_records_[c].number_of_unexpected_vertical_syncs;
|
||||
}
|
||||
|
||||
if(total_number_of_unexpected_vertical_syncs >= total_number_of_frames >> 1)
|
||||
{
|
||||
for(size_t c = 0; c < number_of_frame_records; c++)
|
||||
{
|
||||
frame_records_[c].number_of_frames = 0;
|
||||
frame_records_[c].number_of_unexpected_vertical_syncs = 0;
|
||||
}
|
||||
is_ntsc_ ^= true;
|
||||
|
||||
if(is_ntsc_)
|
||||
{
|
||||
set_clock_rate(NTSC_clock_rate);
|
||||
tia_->set_output_mode(TIA::OutputMode::NTSC);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_clock_rate(PAL_clock_rate);
|
||||
tia_->set_output_mode(TIA::OutputMode::PAL);
|
||||
}
|
||||
|
||||
speaker_->set_input_rate((float)(get_clock_rate() / 38.0));
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ const unsigned int number_of_recorded_counters = 7;
|
||||
class Machine:
|
||||
public CPU6502::Processor<Machine>,
|
||||
public CRTMachine::Machine,
|
||||
public ConfigurationTarget::Machine {
|
||||
public ConfigurationTarget::Machine,
|
||||
public Outputs::CRT::Delegate {
|
||||
|
||||
public:
|
||||
Machine();
|
||||
@ -51,6 +52,9 @@ class Machine:
|
||||
virtual std::shared_ptr<Outputs::Speaker> get_speaker() { return speaker_; }
|
||||
virtual void run_for_cycles(int number_of_cycles) { CPU6502::Processor<Machine>::run_for_cycles(number_of_cycles); }
|
||||
|
||||
// to satisfy Outputs::CRT::Delegate
|
||||
virtual void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs);
|
||||
|
||||
private:
|
||||
uint8_t *rom_, *rom_pages_[4];
|
||||
size_t rom_size_;
|
||||
@ -72,6 +76,17 @@ class Machine:
|
||||
// video backlog accumulation counter
|
||||
unsigned int cycles_since_video_update_;
|
||||
void update_video();
|
||||
|
||||
// output frame rate tracker
|
||||
struct FrameRecord
|
||||
{
|
||||
unsigned int number_of_frames;
|
||||
unsigned int number_of_unexpected_vertical_syncs;
|
||||
|
||||
FrameRecord() : number_of_frames(0), number_of_unexpected_vertical_syncs(0) {}
|
||||
} frame_records_[4];
|
||||
unsigned int frame_record_pointer_;
|
||||
bool is_ntsc_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -143,17 +143,40 @@ TIA::TIA(std::function<void(uint8_t *output_buffer)> line_end_function) : TIA(fa
|
||||
|
||||
void TIA::set_output_mode(Atari2600::TIA::OutputMode output_mode)
|
||||
{
|
||||
// this is the NTSC phase offset function; see below for PAL
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint c = texture(texID, coordinate).r;"
|
||||
"uint y = c & 14u;"
|
||||
"uint iPhase = (c >> 4);"
|
||||
Outputs::CRT::DisplayType display_type;
|
||||
|
||||
if(output_mode == OutputMode::NTSC)
|
||||
{
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint c = texture(texID, coordinate).r;"
|
||||
"uint y = c & 14u;"
|
||||
"uint iPhase = (c >> 4);"
|
||||
|
||||
"float phaseOffset = 6.283185308 * float(iPhase) / 13.0 + 5.074880441076923;"
|
||||
"return mix(float(y) / 14.0, step(1, iPhase) * cos(phase + phaseOffset), amplitude);"
|
||||
"}");
|
||||
display_type = Outputs::CRT::DisplayType::NTSC60;
|
||||
}
|
||||
else
|
||||
{
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint c = texture(texID, coordinate).r;"
|
||||
"uint y = c & 14u;"
|
||||
"uint iPhase = (c >> 4);"
|
||||
|
||||
"uint direction = iPhase & 1u;"
|
||||
"float phaseOffset = float(7u - direction) + (float(direction) - 0.5) * 2.0 * float(iPhase >> 1);"
|
||||
"phaseOffset *= 6.283185308 / 12.0;"
|
||||
"return mix(float(y) / 14.0, step(4, (iPhase + 2u) & 15u) * cos(phase + phaseOffset), amplitude);"
|
||||
"}");
|
||||
display_type = Outputs::CRT::DisplayType::PAL50;
|
||||
}
|
||||
crt_->set_new_display_type(cycles_per_line * 2 + 1, display_type);
|
||||
|
||||
"float phaseOffset = 6.283185308 * float(iPhase) / 13.0 + 5.074880441076923;"
|
||||
"return mix(float(y) / 14.0, step(1, iPhase) * cos(phase + phaseOffset), amplitude);"
|
||||
"}");
|
||||
/* speaker_->set_input_rate((float)(get_clock_rate() / 38.0));*/
|
||||
}
|
||||
|
||||
@ -161,29 +184,6 @@ TIA::~TIA()
|
||||
{
|
||||
}
|
||||
|
||||
/*void Machine::switch_region()
|
||||
{
|
||||
// the PAL function
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"uint c = texture(texID, coordinate).r;"
|
||||
"uint y = c & 14u;"
|
||||
"uint iPhase = (c >> 4);"
|
||||
|
||||
"uint direction = iPhase & 1u;"
|
||||
"float phaseOffset = float(7u - direction) + (float(direction) - 0.5) * 2.0 * float(iPhase >> 1);"
|
||||
"phaseOffset *= 6.283185308 / 12.0;"
|
||||
"return mix(float(y) / 14.0, step(4, (iPhase + 2u) & 15u) * cos(phase + phaseOffset), amplitude);"
|
||||
"}");
|
||||
|
||||
crt_->set_new_timing(228, 312, Outputs::CRT::ColourSpace::YUV, 228, 1, true);
|
||||
|
||||
is_pal_region_ = true;
|
||||
speaker_->set_input_rate((float)(get_clock_rate() / 38.0));
|
||||
set_clock_rate(PAL_clock_rate);
|
||||
}*/
|
||||
|
||||
// justification for +5: "we need to wait at least 71 [clocks] before the HMOVE operation is complete";
|
||||
// which will take 16*4 + 2 = 66 cycles from the first compare, implying the first compare must be
|
||||
// in five cycles from now
|
||||
|
@ -11,42 +11,8 @@
|
||||
#include "Atari2600.hpp"
|
||||
#import "CSMachine+Subclassing.h"
|
||||
|
||||
@interface CSAtari2600 ()
|
||||
- (void)crt:(Outputs::CRT::CRT *)crt didEndBatchOfFrames:(unsigned int)numberOfFrames withUnexpectedVerticalSyncs:(unsigned int)numberOfUnexpectedSyncs;
|
||||
@end
|
||||
|
||||
struct CRTDelegate: public Outputs::CRT::Delegate {
|
||||
__weak CSAtari2600 *atari2600;
|
||||
void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs) {
|
||||
[atari2600 crt:crt didEndBatchOfFrames:number_of_frames withUnexpectedVerticalSyncs:number_of_unexpected_vertical_syncs];
|
||||
}
|
||||
};
|
||||
|
||||
@implementation CSAtari2600 {
|
||||
Atari2600::Machine _atari2600;
|
||||
CRTDelegate _crtDelegate;
|
||||
|
||||
int _frameCount;
|
||||
int _hitCount;
|
||||
BOOL _didDecideRegion;
|
||||
int _batchesReceived;
|
||||
}
|
||||
|
||||
- (void)crt:(Outputs::CRT::CRT *)crt didEndBatchOfFrames:(unsigned int)numberOfFrames withUnexpectedVerticalSyncs:(unsigned int)numberOfUnexpectedSyncs {
|
||||
if(!_didDecideRegion)
|
||||
{
|
||||
_batchesReceived++;
|
||||
if(_batchesReceived == 2)
|
||||
{
|
||||
_didDecideRegion = YES;
|
||||
if(numberOfUnexpectedSyncs >= numberOfFrames >> 1)
|
||||
{
|
||||
[self.view performWithGLContext:^{
|
||||
// _atari2600.switch_region();
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setDirection:(CSJoystickDirection)direction onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
|
||||
@ -78,8 +44,6 @@ struct CRTDelegate: public Outputs::CRT::Delegate {
|
||||
- (void)setupOutputWithAspectRatio:(float)aspectRatio {
|
||||
@synchronized(self) {
|
||||
[super setupOutputWithAspectRatio:aspectRatio];
|
||||
_atari2600.get_crt()->set_delegate(&_crtDelegate);
|
||||
_crtDelegate.atari2600 = self;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user