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:
parent
8aabf1b374
commit
085529ed72
@ -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).
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user