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

Improve get_rect_for_area, use in C16.

This commit is contained in:
Thomas Harte 2024-12-18 20:53:03 -05:00
parent 7466da5651
commit 81398d58a2
3 changed files with 49 additions and 19 deletions

View File

@ -127,7 +127,10 @@ Video::Video() :
// 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.
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,
480, 1280,
4.0f / 3.0f));
}
void Video::set_ram(uint16_t *ram, size_t size) {

View File

@ -26,7 +26,14 @@ public:
interrupts_(interrupts)
{
// TODO: perfect crop.
crt_.set_visible_area(Outputs::Display::Rect(0.075f, 0.065f, 0.85f, 0.85f));
// crt_.set_visible_area(Outputs::Display::Rect(0.075f - 0.00877193f, 0.065f, 0.85f, 0.85f));
crt_.set_visible_area(crt_.get_rect_for_area(
311 - 257 - 4,
208 + 8,
Begin40Columns - BeginSync - 8,
End40Columns + EndOfLine - Begin40Columns + 16,
4.0f / 3.0f
));
}
template <uint16_t address>

View File

@ -8,10 +8,10 @@
#include "CRT.hpp"
#include <cstdarg>
#include <cmath>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdarg>
using namespace Outputs::CRT;
@ -458,40 +458,58 @@ void CRT::output_data(int number_of_cycles, size_t number_of_samples) {
// MARK: - Getters.
Outputs::Display::Rect CRT::get_rect_for_area(int first_line_after_sync, int number_of_lines, int first_cycle_after_sync, int number_of_cycles, float aspect_ratio) const {
Outputs::Display::Rect CRT::get_rect_for_area(
int first_line_after_sync,
int number_of_lines,
int first_cycle_after_sync,
int number_of_cycles,
float aspect_ratio
) const {
assert(number_of_cycles > 0);
assert(number_of_lines > 0);
assert(first_line_after_sync >= 0);
assert(first_cycle_after_sync >= 0);
// Scale up x coordinates and add a little extra leeway to y.
first_cycle_after_sync *= time_multiplier_;
number_of_cycles *= time_multiplier_;
first_line_after_sync -= 2;
number_of_lines += 4;
// determine prima facie x extent
// Determine prima facie x extent.
const int horizontal_period = horizontal_flywheel_->get_standard_period();
const int horizontal_scan_period = horizontal_flywheel_->get_scan_period();
const int horizontal_retrace_period = horizontal_period - horizontal_scan_period;
// make sure that the requested range is visible
if(int(first_cycle_after_sync) < horizontal_retrace_period) first_cycle_after_sync = int(horizontal_retrace_period);
if(int(first_cycle_after_sync + number_of_cycles) > horizontal_scan_period) number_of_cycles = int(horizontal_scan_period - int(first_cycle_after_sync));
// Ensure requested range is within visible region.
first_cycle_after_sync = std::max(horizontal_retrace_period, first_cycle_after_sync);
number_of_cycles = std::min(horizontal_period - first_cycle_after_sync, number_of_cycles);
float start_x = float(int(first_cycle_after_sync) - horizontal_retrace_period) / float(horizontal_scan_period);
float start_x = float(first_cycle_after_sync - horizontal_retrace_period) / float(horizontal_scan_period);
float width = float(number_of_cycles) / float(horizontal_scan_period);
// determine prima facie y extent
// Determine prima facie y extent.
const int vertical_period = vertical_flywheel_->get_standard_period();
const int vertical_scan_period = vertical_flywheel_->get_scan_period();
const int vertical_retrace_period = vertical_period - vertical_scan_period;
// make sure that the requested range is visible
// if(int(first_line_after_sync) * horizontal_period < vertical_retrace_period)
// first_line_after_sync = (vertical_retrace_period + horizontal_period - 1) / horizontal_period;
// if((first_line_after_sync + number_of_lines) * horizontal_period > vertical_scan_period)
// number_of_lines = int(horizontal_scan_period - int(first_cycle_after_sync));
// Ensure range is visible.
first_line_after_sync = std::max(
first_line_after_sync * horizontal_period,
vertical_retrace_period
) / horizontal_period;
number_of_lines = std::min(
vertical_period - first_line_after_sync * horizontal_period,
number_of_lines * horizontal_period
) / horizontal_period;
float start_y = float((int(first_line_after_sync) * horizontal_period) - vertical_retrace_period) / float(vertical_scan_period);
float height = float(int(number_of_lines) * horizontal_period) / vertical_scan_period;
float start_y =
float(first_line_after_sync * horizontal_period - vertical_retrace_period) /
float(vertical_scan_period);
float height = float(number_of_lines * horizontal_period) / vertical_scan_period;
// adjust to ensure aspect ratio is correct
// Pick a zoom that includes the entire requested visible area given the aspect ratio constraints.
const float adjusted_aspect_ratio = (3.0f*aspect_ratio / 4.0f);
const float ideal_width = height * adjusted_aspect_ratio;
if(ideal_width > width) {
@ -503,6 +521,8 @@ Outputs::Display::Rect CRT::get_rect_for_area(int first_line_after_sync, int num
height = ideal_height;
}
// TODO: apply absolute clipping constraints now.
return Outputs::Display::Rect(start_x, start_y, width, height);
}