<commit_before>//
//  Video.cpp
//  Clock Signal
//
//  Created by <NAME> on 04/10/2019.
//  Copyright © 2019 <NAME>. All rights reserved.
//

#include "Video.hpp"

#include <algorithm>

using namespace Atari::ST;

namespace {

struct ModeParams {
	const int lines_per_frame;

	const int first_video_line;
	const int final_video_line;

	const int line_length;

	const int end_of_blank;

	const int start_of_display_enable;
	const int end_of_display_enable;

	const int start_of_output;
	const int end_of_output;

	const int start_of_blank;

	const int start_of_hsync;
	const int end_of_hsync;
} modes[3] = {
	{313,	56, 256,	1024,		64,		116, 116+640,	116+48, 116+48+640,		904,	928, 1008	},
	{},
	{}
};

const ModeParams &mode_params_for_mode() {
	// TODO: rest of potential combinations, and accept mode as a paramter.
	return modes[0];
}

}

Video::Video() :
	crt_(1024, 1, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4) {
}

void Video::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
	crt_.set_scan_target(scan_target);
}

void Video::run_for(HalfCycles duration) {
	int integer_duration = duration.as_int();
	const auto mode_params = mode_params_for_mode();

#define Period(lower, upper, type)	\
	if(x >= lower && x < upper) {	\
		const auto target = std::min(upper, final_x);	\
		type(target - x);	\
		x = target;	\
	}

	while(integer_duration) {
		const int final_x = std::min(x + integer_duration, mode_params.line_length);
		integer_duration -= (final_x - x);

		if(y >= mode_params.first_video_line && y < mode_params.final_video_line) {
			// TODO: Prior to output: collect all necessary data, obeying start_of_display_enable and end_of_display_enable.

			Period(0, 							mode_params.end_of_blank, 		crt_.output_blank);
			Period(mode_params.end_of_blank, 	mode_params.start_of_output, 	output_border);

			if(x >= mode_params.start_of_output && x < mode_params.end_of_output) {
				const auto target = std::min(mode_params.end_of_output, final_x);
				x = target;

				if(x == mode_params.end_of_output) {
					uint16_t *colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1));
					if(colour_pointer) *colour_pointer = 0xffff;
					crt_.output_level(mode_params.end_of_output - mode_params.start_of_output);
				}
			}

			Period(mode_params.end_of_output, 	mode_params.start_of_blank, 	output_border);
			Period(mode_params.start_of_blank, 	mode_params.start_of_hsync,		crt_.output_blank);
			Period(mode_params.start_of_hsync,	mode_params.start_of_blank,		crt_.output_sync);
			Period(mode_params.start_of_blank, 	mode_params.line_length,		crt_.output_blank);
		} else {
			// Hard code the first three lines as vertical sync.
			if(y < 3) {
				Period(0,							mode_params.start_of_hsync,	crt_.output_sync);
				Period(mode_params.start_of_hsync,	mode_params.end_of_hsync,	crt_.output_blank);
				Period(mode_params.end_of_hsync,	mode_params.line_length,	crt_.output_sync);
			} else {
				Period(0, 							mode_params.end_of_blank, 		crt_.output_blank);
				Period(mode_params.end_of_blank, 	mode_params.start_of_blank, 	output_border);
				Period(mode_params.start_of_blank, 	mode_params.start_of_hsync,		crt_.output_blank);
				Period(mode_params.start_of_hsync,	mode_params.start_of_blank,		crt_.output_sync);
				Period(mode_params.start_of_blank, 	mode_params.line_length,		crt_.output_blank);<commit_msg>Corrects sync generation.<commit_after>//
//  Video.cpp
//  Clock Signal
//
//  Created by <NAME> on 04/10/2019.
//  Copyright © 2019 <NAME>. All rights reserved.
//

#include "Video.hpp"

#include <algorithm>

using namespace Atari::ST;

namespace {

struct ModeParams {
	const int lines_per_frame;

	const int first_video_line;
	const int final_video_line;

	const int line_length;

	const int end_of_blank;

	const int start_of_display_enable;
	const int end_of_display_enable;

	const int start_of_output;
	const int end_of_output;

	const int start_of_blank;

	const int start_of_hsync;
	const int end_of_hsync;
} modes[3] = {
	{313,	56, 256,	1024,		64,		116, 116+640,	116+48, 116+48+640,		904,	928, 1008	},
	{},
	{}
};

const ModeParams &mode_params_for_mode() {
	// TODO: rest of potential combinations, and accept mode as a paramter.
	return modes[0];
}

}

Video::Video() :
	crt_(1024, 1, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red4Green4Blue4) {
}

void Video::set_scan_target(Outputs::Display::ScanTarget *scan_target) {
	crt_.set_scan_target(scan_target);
}

void Video::run_for(HalfCycles duration) {
	int integer_duration = duration.as_int();
	const auto mode_params = mode_params_for_mode();

#define Period(lower, upper, type)	\
	if(x >= lower && x < upper) {	\
		const auto target = std::min(upper, final_x);	\
		type(target - x);	\
		x = target;	\
	}

	while(integer_duration) {
		const int final_x = std::min(x + integer_duration, mode_params.line_length);
		integer_duration -= (final_x - x);

		if(y >= mode_params.first_video_line && y < mode_params.final_video_line) {
			// TODO: Prior to output: collect all necessary data, obeying start_of_display_enable and end_of_display_enable.

			Period(0, 							mode_params.end_of_blank, 		crt_.output_blank);
			Period(mode_params.end_of_blank, 	mode_params.start_of_output, 	output_border);

			if(x >= mode_params.start_of_output && x < mode_params.end_of_output) {
				const auto target = std::min(mode_params.end_of_output, final_x);
				x = target;

				if(x == mode_params.end_of_output) {
					uint16_t *colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1));
					if(colour_pointer) *colour_pointer = 0xffff;
					crt_.output_level(mode_params.end_of_output - mode_params.start_of_output);
				}
			}

			Period(mode_params.end_of_output, 	mode_params.start_of_blank, 	output_border);
			Period(mode_params.start_of_blank, 	mode_params.start_of_hsync,		crt_.output_blank);
			Period(mode_params.start_of_hsync,	mode_params.end_of_hsync,		crt_.output_sync);
			Period(mode_params.end_of_hsync, 	mode_params.line_length,		crt_.output_blank);
		} else {
			// Hard code the first three lines as vertical sync.
			if(y < 3) {
				Period(0,							mode_params.start_of_hsync,	crt_.output_sync);
				Period(mode_params.start_of_hsync,	mode_params.end_of_hsync,	crt_.output_blank);
				Period(mode_params.end_of_hsync,	mode_params.line_length,	crt_.output_sync);
			} else {
				Period(0, 							mode_params.end_of_blank, 		crt_.output_blank);
				Period(mode_params.end_of_blank, 	mode_params.start_of_blank, 	output_border);
				Period(mode_params.start_of_blank, 	mode_params.start_of_hsync,		crt_.output_blank);
				Period(mode_params.start_of_hsync,	mode_params.end_of_hsync,		crt_.output_sync);
				Period(mode_params.end_of_hsync, 	mode_params.line_length,		crt_.output_blank);
{'fraction_non_alphanumeric': 0.11326048434731247, 'fraction_numerical': 0.02362669816893089, 'mean_word_length': 4.672529313232831, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1521412', 'n_tokens_mistral': 2885, 'n_tokens_neox': 2553, 'n_words': 461}