1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-29 12:50:28 +00:00

Makes the shifter behaviour conform to its documentation.

This commit is contained in:
Thomas Harte 2020-02-02 17:26:39 -05:00
parent 8aabf1b374
commit 085529ed72
4 changed files with 39 additions and 23 deletions

View File

@ -571,7 +571,7 @@ class ConcreteMachine:
GPIP 0: centronics busy GPIP 0: centronics busy
*/ */
mfp_->set_port_input( mfp_->set_port_input(
0x00 | // b7: Monochrome monitor detect (0 = is monochrome). 0x80 | // b7: Monochrome monitor detect (0 = is monochrome).
0x40 | // b6: RS-232 ring indicator. 0x40 | // b6: RS-232 ring indicator.
(dma_->get_interrupt_line() ? 0x00 : 0x20) | // b5: FD/HS interrupt (0 = interrupt requested). (dma_->get_interrupt_line() ? 0x00 : 0x20) | // b5: FD/HS interrupt (0 = interrupt requested).
((keyboard_acia_->get_interrupt_line() || midi_acia_->get_interrupt_line()) ? 0x00 : 0x10) | // b4: Keyboard/MIDI interrupt (0 = interrupt requested). ((keyboard_acia_->get_interrupt_line() || midi_acia_->get_interrupt_line()) ? 0x00 : 0x10) | // b4: Keyboard/MIDI interrupt (0 = interrupt requested).

View File

@ -31,7 +31,7 @@ const struct VerticalParams {
} vertical_params[3] = { } vertical_params[3] = {
{63, 263, 313}, // 47 rather than 63 on early machines. {63, 263, 313}, // 47 rather than 63 on early machines.
{34, 234, 263}, {34, 234, 263},
{51, 451, 500} // 72 Hz mode: who knows? {34, 434, 500} // Guesswork: (i) nobody ever recommends 72Hz mode for opening the top border, so it's likely to be the same as another mode; (ii) being the same as PAL feels too late.
}; };
/// @returns The correct @c VerticalParams for output at @c frequency. /// @returns The correct @c VerticalParams for output at @c frequency.
@ -121,13 +121,13 @@ const int load_delay_period = CYCLE(4); // Amount of time after DE that observe
} }
Video::Video() : Video::Video() :
// crt_(2048, 2, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4), crt_(2048, 2, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4),
crt_(896, 1, 500, 5, Outputs::Display::InputDataType::Red4Green4Blue4), // crt_(896, 1, 500, 5, Outputs::Display::InputDataType::Red4Green4Blue4),
video_stream_(crt_, palette_) { video_stream_(crt_, palette_) {
// Show a total of 260 lines; a little short for PAL but a compromise between that and the ST's // Show a total of 260 lines; a little short for PAL but a compromise between that and the ST's
// usual output height of 200 lines. // usual output height of 200 lines.
// crt_.set_visible_area(crt_.get_rect_for_area(33, 260, 440, 1700, 4.0f / 3.0f)); crt_.set_visible_area(crt_.get_rect_for_area(33, 260, 440, 1700, 4.0f / 3.0f));
} }
void Video::set_ram(uint16_t *ram, size_t size) { void Video::set_ram(uint16_t *ram, size_t size) {
@ -212,13 +212,16 @@ void Video::run_for(HalfCycles duration) {
} else if(!load_) { } else if(!load_) {
video_stream_.output(run_length, VideoStream::OutputMode::Pixels); video_stream_.output(run_length, VideoStream::OutputMode::Pixels);
} else { } else {
const int since_load = x_ - load_base_; const int start = x_ - load_base_;
const int end = start + run_length;
// There will be pixels this line, subject to the shifter pipeline. // There will be pixels this line, subject to the shifter pipeline.
// Divide into 8-[half-]cycle windows; at the start of each window fetch a word, // Divide into 8-[half-]cycle windows; at the start of each window fetch a word,
// and during the rest of the window, shift out. // and during the rest of the window, shift out.
int start_column = since_load >> 3; int start_column = start >> 3;
const int end_column = (since_load + run_length) >> 3; const int end_column = end >> 3;
const int start_offset = start & 7;
const int end_offset = end & 7;
// Rules obeyed below: // Rules obeyed below:
// //
@ -227,26 +230,29 @@ void Video::run_for(HalfCycles duration) {
// was reloaded by the fetch depends on the FIFO. // was reloaded by the fetch depends on the FIFO.
if(start_column == end_column) { if(start_column == end_column) {
if(!start_offset) {
push_latched_data();
}
video_stream_.output(run_length, VideoStream::OutputMode::Pixels); video_stream_.output(run_length, VideoStream::OutputMode::Pixels);
} else { } else {
// Continue the current column if partway across. // Continue the current column if partway across.
if(since_load&7) { if(start_offset) {
// If at least one column boundary is crossed, complete this column. // If at least one column boundary is crossed, complete this column.
video_stream_.output(8 - (since_load & 7), VideoStream::OutputMode::Pixels); video_stream_.output(8 - start_offset, VideoStream::OutputMode::Pixels);
++start_column; // This starts a new column, so latch a new word. ++start_column; // This starts a new column, so latch a new word.
push_latched_data();
} }
// Run for all columns that have their starts in this time period. // Run for all columns that have their starts in this time period.
int complete_columns = end_column - start_column; int complete_columns = end_column - start_column;
while(complete_columns--) { while(complete_columns--) {
video_stream_.output(8, VideoStream::OutputMode::Pixels);
push_latched_data(); push_latched_data();
video_stream_.output(8, VideoStream::OutputMode::Pixels);
} }
// Output the start of the next column, if necessary. // Output the start of the next column, if necessary.
if((since_load + run_length) & 7) { if(end_offset) {
video_stream_.output((since_load + run_length) & 7, VideoStream::OutputMode::Pixels); push_latched_data();
video_stream_.output(end_offset, VideoStream::OutputMode::Pixels);
} }
} }
} }
@ -574,7 +580,7 @@ void Video::VideoStream::generate(int duration, OutputMode mode, bool is_termina
case OutputMode::ColourBurst: crt_.output_default_colour_burst(duration_*2); break; case OutputMode::ColourBurst: crt_.output_default_colour_burst(duration_*2); break;
} }
// Reseed duration // Reseed duration.
duration_ = duration; duration_ = duration;
// The shifter should keep running, so throw away the proper amount of content. // The shifter should keep running, so throw away the proper amount of content.
@ -725,7 +731,7 @@ void Video::VideoStream::output_pixels(int duration) {
} }
// Check whether the limit has been reached. // Check whether the limit has been reached.
if(pixel_pointer_ == allocation_size) { if(pixel_pointer_ >= allocation_size - 32) {
flush_pixels(); flush_pixels();
} }
} }
@ -735,9 +741,9 @@ void Video::VideoStream::output_pixels(int duration) {
if(pixels) { if(pixels) {
int leftover_duration = pixels; int leftover_duration = pixels;
switch(bpp_) { switch(bpp_) {
case OutputBpp::One: leftover_duration >>= 1; break; default: leftover_duration >>= 1; break;
default: break; case OutputBpp::Two: break;
case OutputBpp::Four: leftover_duration <<= 1; break; case OutputBpp::Four: leftover_duration <<= 1; break;
} }
shift(leftover_duration); shift(leftover_duration);
crt_.output_data(leftover_duration*2); crt_.output_data(leftover_duration*2);
@ -748,9 +754,9 @@ void Video::VideoStream::flush_pixels() {
// Flush only if there's something to flush. // Flush only if there's something to flush.
if(pixel_pointer_) { if(pixel_pointer_) {
switch(bpp_) { switch(bpp_) {
case OutputBpp::One: crt_.output_data(pixel_pointer_); break; case OutputBpp::One: crt_.output_data(pixel_pointer_); break;
default: crt_.output_data(pixel_pointer_ << 1, size_t(pixel_pointer_)); break; default: crt_.output_data(pixel_pointer_ << 1, size_t(pixel_pointer_)); break;
case OutputBpp::Four: crt_.output_data(pixel_pointer_ << 2, size_t(pixel_pointer_)); break; case OutputBpp::Four: crt_.output_data(pixel_pointer_ << 2, size_t(pixel_pointer_)); break;
} }
} }

View File

@ -67,7 +67,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES" enableASanStackUseAfterReturn = "YES"

View File

@ -333,6 +333,16 @@ struct RunLength {
XCTAssertNotEqual([self currentVideoAddress], 0); XCTAssertNotEqual([self currentVideoAddress], 0);
} }
// MARK: - Tests Relating To Specific Bugs
- (void)test72LineLength {
// Set 1bpp, 72Hz.
_video->write(0x30, 0x0200);
[self syncToStartOfLine];
_video->run_for(HalfCycles(400)); // 392, 399, 406
}
// MARK: - Tests Correlating To Exact Pieces of Software // MARK: - Tests Correlating To Exact Pieces of Software
- (void)testUnionDemoScroller { - (void)testUnionDemoScroller {