mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Simplify 'get_next_sequence_point' -> 'next_sequence_point'.
This commit is contained in:
parent
211a6e5114
commit
8efb6a9226
@ -26,7 +26,7 @@
|
|||||||
Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a
|
Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a
|
||||||
separate @c TargetTimeScale at template declaration.
|
separate @c TargetTimeScale at template declaration.
|
||||||
|
|
||||||
If the held object implements get_next_sequence_point() then it'll be used to flush implicitly
|
If the held object implements @c next_sequence_point() then it'll be used to flush implicitly
|
||||||
as and when sequence points are hit. Callers can use will_flush() to predict these.
|
as and when sequence points are hit. Callers can use will_flush() to predict these.
|
||||||
|
|
||||||
If the held object is a subclass of ClockingHint::Source, this template will register as an
|
If the held object is a subclass of ClockingHint::Source, this template will register as an
|
||||||
@ -40,7 +40,7 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
|||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
A std::unique_ptr deleter which causes an update_sequence_point to occur on the actor supplied
|
A std::unique_ptr deleter which causes an update_sequence_point to occur on the actor supplied
|
||||||
to it at construction if it implements get_next_sequence_point(). Otherwise destruction is a no-op.
|
to it at construction if it implements @c next_sequence_point(). Otherwise destruction is a no-op.
|
||||||
|
|
||||||
**Does not delete the object.**
|
**Does not delete the object.**
|
||||||
|
|
||||||
@ -247,9 +247,9 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
|||||||
// going to be applied then do a direct max -> max translation rather than
|
// going to be applied then do a direct max -> max translation rather than
|
||||||
// allowing the arithmetic to overflow.
|
// allowing the arithmetic to overflow.
|
||||||
if constexpr (divider == 1 && std::is_same_v<LocalTimeScale, TargetTimeScale>) {
|
if constexpr (divider == 1 && std::is_same_v<LocalTimeScale, TargetTimeScale>) {
|
||||||
time_until_event_ = object_.get_next_sequence_point();
|
time_until_event_ = object_.next_sequence_point();
|
||||||
} else {
|
} else {
|
||||||
const auto time = object_.get_next_sequence_point();
|
const auto time = object_.next_sequence_point();
|
||||||
if(time == TargetTimeScale::max()) {
|
if(time == TargetTimeScale::max()) {
|
||||||
time_until_event_ = LocalTimeScale::max();
|
time_until_event_ = LocalTimeScale::max();
|
||||||
} else {
|
} else {
|
||||||
@ -272,7 +272,7 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
|
|||||||
bool did_flush_ = false;
|
bool did_flush_ = false;
|
||||||
|
|
||||||
template <typename S, typename = void> struct has_sequence_points : std::false_type {};
|
template <typename S, typename = void> struct has_sequence_points : std::false_type {};
|
||||||
template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().get_next_sequence_point()))> : std::true_type {};
|
template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().next_sequence_point()))> : std::true_type {};
|
||||||
|
|
||||||
ClockingHint::Preference clocking_preference_ = ClockingHint::Preference::JustInTime;
|
ClockingHint::Preference clocking_preference_ = ClockingHint::Preference::JustInTime;
|
||||||
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference clocking) {
|
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference clocking) {
|
||||||
|
@ -207,7 +207,7 @@ void MFP68901::run_for(HalfCycles time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HalfCycles MFP68901::get_next_sequence_point() {
|
HalfCycles MFP68901::next_sequence_point() {
|
||||||
return HalfCycles::max();
|
return HalfCycles::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class MFP68901: public ClockingHint::Source {
|
|||||||
/// so that mechanism can also be used to reduce the quantity of calls into this class.
|
/// so that mechanism can also be used to reduce the quantity of calls into this class.
|
||||||
///
|
///
|
||||||
/// @discussion TODO, alas.
|
/// @discussion TODO, alas.
|
||||||
HalfCycles get_next_sequence_point();
|
HalfCycles next_sequence_point();
|
||||||
|
|
||||||
/// Sets the current level of either of the timer event inputs — TAI and TBI in datasheet terms.
|
/// Sets the current level of either of the timer event inputs — TAI and TBI in datasheet terms.
|
||||||
void set_timer_event_input(int channel, bool value);
|
void set_timer_event_input(int channel, bool value);
|
||||||
|
@ -108,7 +108,7 @@ template <Personality personality> class TMS9918: private Base<personality> {
|
|||||||
If get_interrupt_line is true now of if get_interrupt_line would
|
If get_interrupt_line is true now of if get_interrupt_line would
|
||||||
never return true, returns HalfCycles::max().
|
never return true, returns HalfCycles::max().
|
||||||
*/
|
*/
|
||||||
HalfCycles get_next_sequence_point() const;
|
HalfCycles next_sequence_point() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the amount of time until the nominated line interrupt position is
|
Returns the amount of time until the nominated line interrupt position is
|
||||||
|
@ -1268,7 +1268,7 @@ uint8_t TMS9918<personality>::get_current_line() const {
|
|||||||
return uint8_t(source_row);
|
return uint8_t(source_row);
|
||||||
}
|
}
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
HalfCycles TMS9918<personality>::get_next_sequence_point() const {
|
HalfCycles TMS9918<personality>::next_sequence_point() const {
|
||||||
if(!this->generate_interrupts_ && !this->enable_line_interrupts_) return HalfCycles::max();
|
if(!this->generate_interrupts_ && !this->enable_line_interrupts_) return HalfCycles::max();
|
||||||
if(get_interrupt_line()) return HalfCycles::max();
|
if(get_interrupt_line()) return HalfCycles::max();
|
||||||
|
|
||||||
|
@ -1171,7 +1171,7 @@ class ConcreteMachine:
|
|||||||
machine_->update_audio();
|
machine_->update_audio();
|
||||||
}
|
}
|
||||||
~AudioUpdater() {
|
~AudioUpdater() {
|
||||||
machine_->cycles_until_audio_event_ = machine_->sound_glu_.get_next_sequence_point();
|
machine_->cycles_until_audio_event_ = machine_->sound_glu_.next_sequence_point();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
ConcreteMachine *machine_;
|
ConcreteMachine *machine_;
|
||||||
|
@ -218,7 +218,7 @@ uint8_t GLU::get_address_high() {
|
|||||||
|
|
||||||
// MARK: - Update logic.
|
// MARK: - Update logic.
|
||||||
|
|
||||||
Cycles GLU::get_next_sequence_point() const {
|
Cycles GLU::next_sequence_point() const {
|
||||||
uint32_t result = std::numeric_limits<decltype(result)>::max();
|
uint32_t result = std::numeric_limits<decltype(result)>::max();
|
||||||
|
|
||||||
for(int c = 0; c < local_.oscillator_count; c++) {
|
for(int c = 0; c < local_.oscillator_count; c++) {
|
||||||
|
@ -31,7 +31,7 @@ class GLU: public Outputs::Speaker::SampleSource {
|
|||||||
uint8_t get_address_high();
|
uint8_t get_address_high();
|
||||||
|
|
||||||
void run_for(Cycles);
|
void run_for(Cycles);
|
||||||
Cycles get_next_sequence_point() const;
|
Cycles next_sequence_point() const;
|
||||||
bool get_interrupt_line();
|
bool get_interrupt_line();
|
||||||
|
|
||||||
// SampleSource.
|
// SampleSource.
|
||||||
|
@ -191,7 +191,7 @@ void Video::advance(Cycles cycles) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycles Video::get_next_sequence_point() const {
|
Cycles Video::next_sequence_point() const {
|
||||||
const int cycles_into_row = cycles_into_frame_ % CyclesPerLine;
|
const int cycles_into_row = cycles_into_frame_ % CyclesPerLine;
|
||||||
const int row = cycles_into_frame_ / CyclesPerLine;
|
const int row = cycles_into_frame_ / CyclesPerLine;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class Video: public Apple::II::VideoSwitches<Cycles> {
|
|||||||
Outputs::Display::DisplayType get_display_type() const;
|
Outputs::Display::DisplayType get_display_type() const;
|
||||||
|
|
||||||
/// Determines the period until video might autonomously update its interrupt lines.
|
/// Determines the period until video might autonomously update its interrupt lines.
|
||||||
Cycles get_next_sequence_point() const;
|
Cycles next_sequence_point() const;
|
||||||
|
|
||||||
/// Sets the Mega II interrupt enable state — 1/4-second and VBL interrupts are
|
/// Sets the Mega II interrupt enable state — 1/4-second and VBL interrupts are
|
||||||
/// generated here.
|
/// generated here.
|
||||||
|
@ -575,7 +575,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
|
|
||||||
video_.run_for(time_until_video_event_);
|
video_.run_for(time_until_video_event_);
|
||||||
time_since_video_update_ -= time_until_video_event_;
|
time_since_video_update_ -= time_until_video_event_;
|
||||||
time_until_video_event_ = video_.get_next_sequence_point();
|
time_until_video_event_ = video_.next_sequence_point();
|
||||||
|
|
||||||
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync());
|
via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::One, !video_.vsync());
|
||||||
}
|
}
|
||||||
@ -626,7 +626,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
|
|
||||||
forceinline void update_video() {
|
forceinline void update_video() {
|
||||||
video_.run_for(time_since_video_update_.flush<HalfCycles>());
|
video_.run_for(time_since_video_update_.flush<HalfCycles>());
|
||||||
time_until_video_event_ = video_.get_next_sequence_point();
|
time_until_video_event_ = video_.next_sequence_point();
|
||||||
}
|
}
|
||||||
|
|
||||||
Inputs::Mouse &get_mouse() final {
|
Inputs::Mouse &get_mouse() final {
|
||||||
|
@ -170,7 +170,7 @@ bool Video::vsync() {
|
|||||||
return line >= 353 && line < 356;
|
return line >= 353 && line < 356;
|
||||||
}
|
}
|
||||||
|
|
||||||
HalfCycles Video::get_next_sequence_point() {
|
HalfCycles Video::next_sequence_point() {
|
||||||
const auto line = (frame_position_ / line_length).as_integral();
|
const auto line = (frame_position_ / line_length).as_integral();
|
||||||
if(line >= 353 && line < 356) {
|
if(line >= 353 && line < 356) {
|
||||||
// Currently in vsync, so get time until start of line 357,
|
// Currently in vsync, so get time until start of line 357,
|
||||||
|
@ -80,7 +80,7 @@ class Video {
|
|||||||
@returns the amount of time until there is next a transition on the
|
@returns the amount of time until there is next a transition on the
|
||||||
vsync signal.
|
vsync signal.
|
||||||
*/
|
*/
|
||||||
HalfCycles get_next_sequence_point();
|
HalfCycles next_sequence_point();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeferredAudio &audio_;
|
DeferredAudio &audio_;
|
||||||
|
@ -395,7 +395,7 @@ bool Video::display_enabled() {
|
|||||||
return public_state_.display_enable;
|
return public_state_.display_enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
HalfCycles Video::get_next_sequence_point() {
|
HalfCycles Video::next_sequence_point() {
|
||||||
// The next sequence point will be whenever display_enabled, vsync or hsync next changes.
|
// The next sequence point will be whenever display_enabled, vsync or hsync next changes.
|
||||||
|
|
||||||
// Sequence of events within a standard line:
|
// Sequence of events within a standard line:
|
||||||
|
@ -68,7 +68,7 @@ class Video {
|
|||||||
@returns the number of cycles until there is next a change in the hsync,
|
@returns the number of cycles until there is next a change in the hsync,
|
||||||
vsync or display_enable outputs.
|
vsync or display_enable outputs.
|
||||||
*/
|
*/
|
||||||
HalfCycles get_next_sequence_point();
|
HalfCycles next_sequence_point();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@returns @c true if the horizontal sync output is currently active; @c false otherwise.
|
@returns @c true if the horizontal sync output is currently active; @c false otherwise.
|
||||||
|
@ -370,7 +370,7 @@ void VideoOutput::setup_base_address() {
|
|||||||
|
|
||||||
// MARK: - Interrupts
|
// MARK: - Interrupts
|
||||||
|
|
||||||
Cycles VideoOutput::get_next_sequence_point() {
|
Cycles VideoOutput::next_sequence_point() {
|
||||||
if(output_position_ < real_time_clock_interrupt_1) {
|
if(output_position_ < real_time_clock_interrupt_1) {
|
||||||
return real_time_clock_interrupt_1 - output_position_;
|
return real_time_clock_interrupt_1 - output_position_;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ class VideoOutput {
|
|||||||
|
|
||||||
This result may be mutated by calls to @c write.
|
This result may be mutated by calls to @c write.
|
||||||
*/
|
*/
|
||||||
Cycles get_next_sequence_point();
|
Cycles next_sequence_point();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@returns a bit mask of all interrupts that have been triggered since the last call to get_interrupt().
|
@returns a bit mask of all interrupts that have been triggered since the last call to get_interrupt().
|
||||||
|
@ -315,7 +315,7 @@ void TimedInterruptSource::run_for(Cycles duration) {
|
|||||||
update_channel(1, rate_ == InterruptRate::ToneGenerator1, cycles.as<int>());
|
update_channel(1, rate_ == InterruptRate::ToneGenerator1, cycles.as<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycles TimedInterruptSource::get_next_sequence_point() const {
|
Cycles TimedInterruptSource::next_sequence_point() const {
|
||||||
// Since both the 1kHz and 50Hz timers are integer dividers of the 1Hz timer, there's no need
|
// Since both the 1kHz and 50Hz timers are integer dividers of the 1Hz timer, there's no need
|
||||||
// to factor that one in when determining the next sequence point for either of those.
|
// to factor that one in when determining the next sequence point for either of those.
|
||||||
switch(rate_) {
|
switch(rate_) {
|
||||||
|
@ -144,7 +144,7 @@ class TimedInterruptSource {
|
|||||||
|
|
||||||
/// @returns The amount of time from now until the earliest that
|
/// @returns The amount of time from now until the earliest that
|
||||||
/// @c get_new_interrupts() _might_ have new interrupts to report.
|
/// @c get_new_interrupts() _might_ have new interrupts to report.
|
||||||
Cycles get_next_sequence_point() const;
|
Cycles next_sequence_point() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr Cycles clock_rate{250000};
|
static constexpr Cycles clock_rate{250000};
|
||||||
|
@ -467,7 +467,7 @@ void Nick::set_output_type(OutputType type, bool force_flush) {
|
|||||||
|
|
||||||
// MARK: - Sequence points.
|
// MARK: - Sequence points.
|
||||||
|
|
||||||
Cycles Nick::get_next_sequence_point() const {
|
Cycles Nick::next_sequence_point() const {
|
||||||
constexpr int load_point = 16; // i.e. 16 cycles after the start of the line, the
|
constexpr int load_point = 16; // i.e. 16 cycles after the start of the line, the
|
||||||
// interrupt line may change. That is, after the
|
// interrupt line may change. That is, after the
|
||||||
// second byte of the mode line has been read.
|
// second byte of the mode line has been read.
|
||||||
|
@ -38,7 +38,7 @@ class Nick {
|
|||||||
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
||||||
|
|
||||||
/// @returns The amount of time until the next potential change in interrupt output.
|
/// @returns The amount of time until the next potential change in interrupt output.
|
||||||
Cycles get_next_sequence_point() const;
|
Cycles next_sequence_point() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@returns The current state of the interrupt line — @c true for active;
|
@returns The current state of the interrupt line — @c true for active;
|
||||||
|
@ -315,7 +315,7 @@ template <Timing timing> class Video {
|
|||||||
/*!
|
/*!
|
||||||
@returns The amount of time until the next change in the interrupt line, that being the only internally-observeable output.
|
@returns The amount of time until the next change in the interrupt line, that being the only internally-observeable output.
|
||||||
*/
|
*/
|
||||||
HalfCycles get_next_sequence_point() {
|
HalfCycles next_sequence_point() {
|
||||||
constexpr auto timings = get_timings();
|
constexpr auto timings = get_timings();
|
||||||
|
|
||||||
// Is the frame still ahead of this interrupt?
|
// Is the frame still ahead of this interrupt?
|
||||||
|
@ -124,7 +124,7 @@ struct VideoTester {
|
|||||||
display_enable = _video->display_enabled();
|
display_enable = _video->display_enabled();
|
||||||
vsync = _video->vsync();
|
vsync = _video->vsync();
|
||||||
hsync = _video->hsync();
|
hsync = _video->hsync();
|
||||||
next_event = _video->get_next_sequence_point();
|
next_event = _video->next_sequence_point();
|
||||||
} else {
|
} else {
|
||||||
NSAssert(display_enable == _video->display_enabled(), @"Unannounced change in display enabled at cycle %zu [%d before next sequence point]", c, next_event.as<int>());
|
NSAssert(display_enable == _video->display_enabled(), @"Unannounced change in display enabled at cycle %zu [%d before next sequence point]", c, next_event.as<int>());
|
||||||
NSAssert(vsync == _video->vsync(), @"Unannounced change in vsync at cycle %zu [%d before next sequence point]", c, next_event.as<int>());
|
NSAssert(vsync == _video->vsync(), @"Unannounced change in vsync at cycle %zu [%d before next sequence point]", c, next_event.as<int>());
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
int toggles = 0;
|
int toggles = 0;
|
||||||
int interrupts = 0;
|
int interrupts = 0;
|
||||||
uint8_t dividerState = _interruptSource->get_divider_state() & 1;
|
uint8_t dividerState = _interruptSource->get_divider_state() & 1;
|
||||||
int nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
int nextSequencePoint = _interruptSource->next_sequence_point().as<int>();
|
||||||
|
|
||||||
for(int c = 0; c < 250000 * 5; c++) {
|
for(int c = 0; c < 250000 * 5; c++) {
|
||||||
// Advance one cycle. Clock is 500,000 Hz.
|
// Advance one cycle. Clock is 500,000 Hz.
|
||||||
@ -55,7 +55,7 @@
|
|||||||
const uint8_t newInterrupts = _interruptSource->get_new_interrupts();
|
const uint8_t newInterrupts = _interruptSource->get_new_interrupts();
|
||||||
if(newInterrupts) {
|
if(newInterrupts) {
|
||||||
XCTAssertEqual(nextSequencePoint, 0);
|
XCTAssertEqual(nextSequencePoint, 0);
|
||||||
nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
nextSequencePoint = _interruptSource->next_sequence_point().as<int>();
|
||||||
|
|
||||||
if(newInterrupts & 0x02) {
|
if(newInterrupts & 0x02) {
|
||||||
++interrupts;
|
++interrupts;
|
||||||
@ -66,7 +66,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XCTAssertEqual(nextSequencePoint, _interruptSource->get_next_sequence_point().as<int>(), @"At cycle %d", c);
|
XCTAssertEqual(nextSequencePoint, _interruptSource->next_sequence_point().as<int>(), @"At cycle %d", c);
|
||||||
}
|
}
|
||||||
|
|
||||||
XCTAssertEqual(toggles, int(expectedInterruptsPerSecond * 5.0));
|
XCTAssertEqual(toggles, int(expectedInterruptsPerSecond * 5.0));
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
- (void)testInterruptPrediction {
|
- (void)testInterruptPrediction {
|
||||||
// Run for the number of cycles implied by the number of lines.
|
// Run for the number of cycles implied by the number of lines.
|
||||||
int next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
int next_sequence_point = _nick->next_sequence_point().as<int>();
|
||||||
bool last_interrupt_line = _nick->get_interrupt_line();
|
bool last_interrupt_line = _nick->get_interrupt_line();
|
||||||
|
|
||||||
for(int c = 0; c < _totalLines*912; c++) {
|
for(int c = 0; c < _totalLines*912; c++) {
|
||||||
@ -61,9 +61,9 @@
|
|||||||
last_interrupt_line = interrupt_line;
|
last_interrupt_line = interrupt_line;
|
||||||
|
|
||||||
if(!next_sequence_point) {
|
if(!next_sequence_point) {
|
||||||
next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
next_sequence_point = _nick->next_sequence_point().as<int>();
|
||||||
} else {
|
} else {
|
||||||
const int expected_next_sequence_point = _nick->get_next_sequence_point().as<int>();
|
const int expected_next_sequence_point = _nick->next_sequence_point().as<int>();
|
||||||
XCTAssertEqual(next_sequence_point, expected_next_sequence_point);
|
XCTAssertEqual(next_sequence_point, expected_next_sequence_point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,14 @@
|
|||||||
int c = 5;
|
int c = 5;
|
||||||
bool vsync = _video->vsync();
|
bool vsync = _video->vsync();
|
||||||
while(c--) {
|
while(c--) {
|
||||||
auto remaining_time_in_state = _video->get_next_sequence_point().as_integral();
|
auto remaining_time_in_state = _video->next_sequence_point().as_integral();
|
||||||
NSLog(@"Vsync %@ expected for %@ half-cycles", vsync ? @"on" : @"off", @(remaining_time_in_state));
|
NSLog(@"Vsync %@ expected for %@ half-cycles", vsync ? @"on" : @"off", @(remaining_time_in_state));
|
||||||
while(remaining_time_in_state--) {
|
while(remaining_time_in_state--) {
|
||||||
XCTAssertEqual(vsync, _video->vsync());
|
XCTAssertEqual(vsync, _video->vsync());
|
||||||
_video->run_for(HalfCycles(1));
|
_video->run_for(HalfCycles(1));
|
||||||
|
|
||||||
if(remaining_time_in_state)
|
if(remaining_time_in_state)
|
||||||
XCTAssertEqual(remaining_time_in_state, _video->get_next_sequence_point().as_integral());
|
XCTAssertEqual(remaining_time_in_state, _video->next_sequence_point().as_integral());
|
||||||
}
|
}
|
||||||
vsync ^= true;
|
vsync ^= true;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
|||||||
vdp.write(1, 0x8a);
|
vdp.write(1, 0x8a);
|
||||||
|
|
||||||
// Get time until interrupt.
|
// Get time until interrupt.
|
||||||
auto time_until_interrupt = vdp.get_next_sequence_point().as_integral() - 1;
|
auto time_until_interrupt = vdp.next_sequence_point().as_integral() - 1;
|
||||||
|
|
||||||
// Check that an interrupt is now scheduled.
|
// Check that an interrupt is now scheduled.
|
||||||
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() - 1, @"No interrupt scheduled");
|
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() - 1, @"No interrupt scheduled");
|
||||||
@ -55,7 +55,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
|||||||
NSAssert(!vdp.get_interrupt_line(), @"Interrupt wasn't reset by status read");
|
NSAssert(!vdp.get_interrupt_line(), @"Interrupt wasn't reset by status read");
|
||||||
|
|
||||||
// Check interrupt flag isn't set prior to the reported time.
|
// Check interrupt flag isn't set prior to the reported time.
|
||||||
time_until_interrupt = vdp.get_next_sequence_point().as_integral() - 1;
|
time_until_interrupt = vdp.next_sequence_point().as_integral() - 1;
|
||||||
vdp.run_for(HalfCycles(time_until_interrupt));
|
vdp.run_for(HalfCycles(time_until_interrupt));
|
||||||
NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early [2]");
|
NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early [2]");
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
|||||||
|
|
||||||
// Clear the pending interrupt and ask about the next one (i.e. the first one).
|
// Clear the pending interrupt and ask about the next one (i.e. the first one).
|
||||||
vdp.read(1);
|
vdp.read(1);
|
||||||
auto time_until_interrupt = vdp.get_next_sequence_point().as_integral() - 1;
|
auto time_until_interrupt = vdp.next_sequence_point().as_integral() - 1;
|
||||||
|
|
||||||
// Check that an interrupt is now scheduled.
|
// Check that an interrupt is now scheduled.
|
||||||
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() - 1, @"No interrupt scheduled");
|
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() - 1, @"No interrupt scheduled");
|
||||||
@ -116,7 +116,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
|||||||
|
|
||||||
// Now run through an entire frame...
|
// Now run through an entire frame...
|
||||||
int half_cycles = 262*228*2;
|
int half_cycles = 262*228*2;
|
||||||
auto last_time_until_interrupt = vdp.get_next_sequence_point().as_integral();
|
auto last_time_until_interrupt = vdp.next_sequence_point().as_integral();
|
||||||
while(half_cycles--) {
|
while(half_cycles--) {
|
||||||
// Validate that an interrupt happened if one was expected, and clear anything that's present.
|
// Validate that an interrupt happened if one was expected, and clear anything that's present.
|
||||||
NSAssert(vdp.get_interrupt_line() == (last_time_until_interrupt == HalfCycles::max().as_integral()), @"Unexpected interrupt state change; expected %d but got %d; position %d %d @ %d", (last_time_until_interrupt == 0), vdp.get_interrupt_line(), c, with_eof, half_cycles);
|
NSAssert(vdp.get_interrupt_line() == (last_time_until_interrupt == HalfCycles::max().as_integral()), @"Unexpected interrupt state change; expected %d but got %d; position %d %d @ %d", (last_time_until_interrupt == 0), vdp.get_interrupt_line(), c, with_eof, half_cycles);
|
||||||
@ -129,7 +129,7 @@ using VDP = TI::TMS::TMS9918<TI::TMS::Personality::SMSVDP>;
|
|||||||
vdp.run_for(HalfCycles(1));
|
vdp.run_for(HalfCycles(1));
|
||||||
|
|
||||||
// Get the time until interrupt.
|
// Get the time until interrupt.
|
||||||
auto time_until_interrupt = vdp.get_next_sequence_point().as_integral();
|
auto time_until_interrupt = vdp.next_sequence_point().as_integral();
|
||||||
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() || vdp.get_interrupt_line(), @"No interrupt scheduled; position %d %d @ %d", c, with_eof, half_cycles);
|
NSAssert(time_until_interrupt != HalfCycles::max().as_integral() || vdp.get_interrupt_line(), @"No interrupt scheduled; position %d %d @ %d", c, with_eof, half_cycles);
|
||||||
NSAssert(time_until_interrupt >= 0, @"Interrupt is scheduled in the past; position %d %d @ %d", c, with_eof, half_cycles);
|
NSAssert(time_until_interrupt >= 0, @"Interrupt is scheduled in the past; position %d %d @ %d", c, with_eof, half_cycles);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user