1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Sub in basic transliteration of hoglet's FPGA.

This commit is contained in:
Thomas Harte 2024-09-06 20:21:46 -04:00
parent aab2dd68b6
commit 59530a12fd
3 changed files with 93 additions and 50 deletions

View File

@ -683,7 +683,7 @@ template <bool has_scsi_bus> class ConcreteMachine:
speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide(Cycles(SoundGenerator::clock_rate_divider))); speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide(Cycles(SoundGenerator::clock_rate_divider)));
} }
inline void signal_interrupt(Interrupt interrupt) { inline void signal_interrupt(uint8_t interrupt) {
if(!interrupt) { if(!interrupt) {
return; return;
} }

View File

@ -230,54 +230,97 @@ Outputs::Display::DisplayType VideoOutput::get_display_type() const {
// } // }
//} //}
Electron::Interrupt VideoOutput::run_for(const Cycles cycles) { uint8_t VideoOutput::run_for(const Cycles cycles) {
Electron::Interrupt interrupts{}; uint8_t interrupts{};
// int number_of_cycles = int(cycles.as_integral());
// const auto start_position = output_position_; int number_of_cycles = cycles.as<int>();
// output_position_ = (output_position_ + number_of_cycles) % cycles_per_frame; while(number_of_cycles--) {
// // Horizontal and vertical counter updates.
// const auto test_range = [&](int start, int end) { const bool is_v_end = v_count == v_total();
// if( h_count += 8;
// (start < real_time_clock_interrupt_1 && end >= real_time_clock_interrupt_1) || if(h_count == h_total) {
// (start < real_time_clock_interrupt_2 && end >= real_time_clock_interrupt_2) h_count = 0;
// ) { ++v_count;
// interrupts_ = Electron::Interrupt(interrupts_ | Electron::Interrupt::RealTimeClock);
// } if(is_v_end) {
// v_count = 0;
// if( field = !field;
// (start < display_end_interrupt_1 && end >= display_end_interrupt_1) || }
// (start < display_end_interrupt_2 && end >= display_end_interrupt_2) }
// ) {
// interrupts_ = Electron::Interrupt(interrupts_ | Electron::Interrupt::DisplayEnd); // Test for interrupts.
// } if(v_count == v_rtc && ((!field && !h_count) || (field && h_count == h_half))) {
// }; interrupts |= static_cast<uint8_t>(Interrupt::RealTimeClock);
// }
// if(output_position_ >= start_position) { if(h_count == hsync_start && ((v_count == v_disp_gph && !mode_text) or (v_count == v_disp_txt && mode_text))) {
// test_range(start_position, output_position_); interrupts |= static_cast<uint8_t>(Interrupt::DisplayEnd);
// } else { }
// test_range(start_position, cycles_per_frame);
// test_range(0, output_position_); // Update syncs.
// } if(!field) {
// if(!h_count && v_count == vsync_start) {
// while(number_of_cycles) { vsync_int = true;
// int draw_action_length = screen_map_[screen_map_pointer_].length; } else if(h_count == h_half && v_count == vsync_end) {
// int time_left_in_action = std::min(number_of_cycles, draw_action_length - cycles_into_draw_action_); vsync_int = false;
// if(screen_map_[screen_map_pointer_].type == DrawAction::Pixels) output_pixels(time_left_in_action); }
// } else {
// number_of_cycles -= time_left_in_action; if(h_count == h_half && v_count == vsync_start) {
// cycles_into_draw_action_ += time_left_in_action; vsync_int = true;
// if(cycles_into_draw_action_ == draw_action_length) { } else if(!h_count && v_count == vsync_end + 1) {
// switch(screen_map_[screen_map_pointer_].type) { vsync_int = false;
// case DrawAction::Sync: crt_.output_sync(draw_action_length * crt_cycles_multiplier); break; }
// case DrawAction::ColourBurst: crt_.output_default_colour_burst(draw_action_length * crt_cycles_multiplier); break; }
// case DrawAction::Blank: crt_.output_blank(draw_action_length * crt_cycles_multiplier); break;
// case DrawAction::Pixels: end_pixel_line(); break; const auto h_sync_last = hsync_int;
// } if(h_count == hsync_start) {
// screen_map_pointer_ = (screen_map_pointer_ + 1) % screen_map_.size(); hsync_int = true;
// cycles_into_draw_action_ = 0; } else if(h_count == hsync_end) {
// if(screen_map_[screen_map_pointer_].type == DrawAction::Pixels) start_pixel_line(); hsync_int = false;
// } }
// }
// Update character row on the trailing edge of hsync.
if(h_count == hsync_end) {
if(is_v_end) {
char_row = 0;
} else {
char_row = last_line() ? 0 : char_row + 1;
}
}
// Disable the top bit of the char_row counter outside of text mode.
if(!mode_text) {
char_row &= 7;
}
// Latch video address at frame start.
if(h_count == h_reset_addr && is_v_end) {
row_addr = byte_addr = screen_base;
}
// Copy byte_addr back into row_addr if a new character row has begun.
if(hsync_int) {
if(last_line()) {
row_addr = byte_addr;
} else {
byte_addr = row_addr;
}
}
// Increment the byte address across the line.
// (slghtly pained logic here because the input clock is still at the pixel rate, not the byte rate)
if(h_count < h_active) {
if(
(!mode_40 && !(h_count & 0x7)) ||
(mode_40 && ((h_count & 0xf) == 0x8))
) {
byte_addr += 8;
if(!(byte_addr & 0b0111'1000'0000'0000)) {
byte_addr = mode_base | (byte_addr & 0x0000'0111'1111'1111);
}
}
}
}
return interrupts; return interrupts;
} }

View File

@ -47,7 +47,7 @@ class VideoOutput {
/// Produces the next @c cycles of video output. /// Produces the next @c cycles of video output.
/// ///
/// @returns a bit mask of all interrupts triggered. /// @returns a bit mask of all interrupts triggered.
Electron::Interrupt run_for(const Cycles cycles); uint8_t run_for(const Cycles cycles);
/// @returns The number of 2Mhz cycles that will pass before completion of an attempted /// @returns The number of 2Mhz cycles that will pass before completion of an attempted
/// IO [/1Mhz] access that is first signalled in the upcoming cycle. /// IO [/1Mhz] access that is first signalled in the upcoming cycle.