1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

An early draft; dealing with the issue that not all cycles are necessarily consumed in a single call. Incomplete; broken. Committing for cross-machine visibility.

This commit is contained in:
Thomas Harte 2016-12-12 08:01:10 -05:00
parent be7e05e109
commit fd541e1142
3 changed files with 170 additions and 149 deletions

View File

@ -344,12 +344,13 @@ void Machine::configure_as_target(const StaticAnalyser::Target &target)
if(target.loadingCommand.length()) // TODO: and automatic loading option enabled if(target.loadingCommand.length()) // TODO: and automatic loading option enabled
{ {
set_typer_for_string(target.loadingCommand.c_str()); // set_typer_for_string(target.loadingCommand.c_str());
} }
if(target.acorn.should_hold_shift) if(target.acorn.should_hold_shift)
{ {
set_key_state(KeyShift, true); // set_key_state(KeyShift, true);
is_holding_shift_ = true; // is_holding_shift_ = true;
} }
} }
@ -403,10 +404,13 @@ inline void Machine::evaluate_interrupts()
} }
inline void Machine::update_display() inline void Machine::update_display()
{
if(cycles_since_display_update_)
{ {
video_output_->run_for_cycles((int)cycles_since_display_update_); video_output_->run_for_cycles((int)cycles_since_display_update_);
cycles_since_display_update_ = 0; cycles_since_display_update_ = 0;
} }
}
inline void Machine::queue_next_display_interrupt() inline void Machine::queue_next_display_interrupt()
{ {
@ -416,11 +420,14 @@ inline void Machine::queue_next_display_interrupt()
} }
inline void Machine::update_audio() inline void Machine::update_audio()
{
if(cycles_since_audio_update_)
{ {
unsigned int difference = cycles_since_audio_update_ / Speaker::clock_rate_divider; unsigned int difference = cycles_since_audio_update_ / Speaker::clock_rate_divider;
cycles_since_audio_update_ %= Speaker::clock_rate_divider; cycles_since_audio_update_ %= Speaker::clock_rate_divider;
speaker_->run_for_cycles(difference); speaker_->run_for_cycles(difference);
} }
}
void Machine::clear_all_keys() void Machine::clear_all_keys()
{ {

View File

@ -14,17 +14,17 @@ using namespace Electron;
#define graphics_column(v) ((((v) & 127) - first_graphics_cycle + 128) & 127) #define graphics_column(v) ((((v) & 127) - first_graphics_cycle + 128) & 127)
namespace { namespace {
static const unsigned int cycles_per_line = 128; static const int cycles_per_line = 128;
static const unsigned int lines_per_frame = 625; static const int lines_per_frame = 625;
static const int cycles_per_frame = lines_per_frame * cycles_per_line; static const int cycles_per_frame = lines_per_frame * cycles_per_line;
static const unsigned int crt_cycles_multiplier = 8; static const int crt_cycles_multiplier = 8;
static const unsigned int crt_cycles_per_line = crt_cycles_multiplier * cycles_per_line; static const int crt_cycles_per_line = crt_cycles_multiplier * cycles_per_line;
static const unsigned int field_divider_line = 312; // i.e. the line, simultaneous with which, the first field's sync ends. So if static const int field_divider_line = 312; // i.e. the line, simultaneous with which, the first field's sync ends. So if
// the first line with pixels in field 1 is the 20th in the frame, the first line // the first line with pixels in field 1 is the 20th in the frame, the first line
// with pixels in field 2 will be 20+field_divider_line // with pixels in field 2 will be 20+field_divider_line
static const unsigned int first_graphics_line = 31; static const int first_graphics_line = 31;
static const unsigned int first_graphics_cycle = 33; static const int first_graphics_cycle = 33;
static const int display_end_interrupt_line = 256; static const int display_end_interrupt_line = 256;
@ -244,31 +244,12 @@ void VideoOutput::output_pixels(unsigned int number_of_cycles)
} }
} }
void VideoOutput::run_for_cycles(int number_of_cycles) void VideoOutput::run_for_inner_frame_cycles(int number_of_cycles)
{ {
/* int target_output_position = output_position_ + number_of_cycles;
int final_line = target_output_position >> 7;
Odd field: Even field: while(output_position_ < target_output_position)
|--S--| -S-|
|--S--| |--S--|
|-S-B-| = 3 |--S--| = 2.5
|--B--| |--B--|
|--P--| |--P--|
|--B--| = 312 |--B--| = 312.5
|-B-
*/
int final_position = output_position_ + number_of_cycles;
int number_of_frames = 1 + (final_position / cycles_per_frame);
while(number_of_frames--)
{
int frame_final = number_of_frames ? cycles_per_frame : (final_position % cycles_per_frame);
int final_line = frame_final >> 7;
while(output_position_ < frame_final)
{ {
int line = output_position_ >> 7; int line = output_position_ >> 7;
@ -330,8 +311,8 @@ void VideoOutput::run_for_cycles(int number_of_cycles)
// ======================================== // ========================================
// determine how far we're going from left to right // determine how far we're going from left to right
unsigned int this_cycle = output_position_&127; int this_cycle = output_position_&127;
unsigned int final_cycle = frame_final&127; int final_cycle = target_output_position&127;
if(final_line > line) if(final_line > line)
{ {
final_cycle = 128; final_cycle = 128;
@ -389,6 +370,35 @@ void VideoOutput::run_for_cycles(int number_of_cycles)
} }
} }
} }
}
void VideoOutput::run_for_cycles(int number_of_cycles)
{
/*
Odd field: Even field:
|--S--| -S-|
|--S--| |--S--|
|-S-B-| = 3 |--S--| = 2.5
|--B--| |--B--|
|--P--| |--P--|
|--B--| = 312 |--B--| = 312.5
|-B-
*/
int cycles_at_end = unused_cycles_ + output_position_ + number_of_cycles;
unused_cycles_ = 0;
int number_of_frames = 1 + (cycles_at_end / cycles_per_frame);
while(number_of_frames--)
{
int frame_target = number_of_frames ? cycles_per_frame : (cycles_at_end % cycles_per_frame);
run_for_inner_frame_cycles(frame_target - output_position_);
// unused_cycles_ += (frame_final - output_position_);
// if(unused_cycles_)
// {
// }
output_position_ %= cycles_per_frame; output_position_ %= cycles_per_frame;
} }
@ -575,16 +585,18 @@ VideoOutput::Interrupt VideoOutput::get_next_interrupt()
#pragma mark - RAM timing #pragma mark - RAM timing
unsigned int VideoOutput::get_cycles_until_next_ram_availability(unsigned int from_time) unsigned int VideoOutput::get_cycles_until_next_ram_availability(int from_time)
{ {
unsigned int result = 0; unsigned int result = 0;
// cycles += 1 + (frame_cycles_&1); int position = output_position_ + from_time;
result += 1 + (position&1);
// if(screen_mode_ < 4) // if(screen_mode_ < 4)
// { // {
// const int current_line = graphics_line(frame_cycles_ + (frame_cycles_&1)); // const int current_line = graphics_line(position + (position&1));
// const int current_column = graphics_column(frame_cycles_ + (frame_cycles_&1)); // const int current_column = graphics_column(position + (position&1));
// if(current_line < 256 && current_column < 80 && !is_blank_line_) // if(current_line < 256 && current_column < 80 && !is_blank_line_)
// cycles += (unsigned int)(80 - current_column); // result += (unsigned int)(80 - current_column);
// } // }
return result; return result;
} }

View File

@ -28,14 +28,16 @@ class VideoOutput {
void set_register(int address, uint8_t value); void set_register(int address, uint8_t value);
unsigned int get_cycles_until_next_ram_availability(unsigned int from_time); unsigned int get_cycles_until_next_ram_availability(int from_time);
private: private:
inline void start_pixel_line(); inline void start_pixel_line();
inline void end_pixel_line(); inline void end_pixel_line();
inline void output_pixels(unsigned int number_of_cycles); inline void output_pixels(unsigned int number_of_cycles);
int output_position_; inline void run_for_inner_frame_cycles(int number_of_cycles);
int output_position_, unused_cycles_;
uint8_t palette_[16]; uint8_t palette_[16];
uint8_t screen_mode_; uint8_t screen_mode_;