mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-27 15:29:34 +00:00
Merge pull request #544 from TomHarte/MSXColours
Corrects composition-time over-saturation.
This commit is contained in:
commit
224b3163f2
@ -20,7 +20,7 @@ VideoBase::VideoBase(bool is_iie, std::function<void(Cycles)> &&target) :
|
||||
crt_->set_composite_sampling_function(
|
||||
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
|
||||
"{"
|
||||
"return clamp(texture(sampler, coordinate).r, 0.0, 0.7);"
|
||||
"return clamp(texture(sampler, coordinate).r, 0.0, 1.0);"
|
||||
"}");
|
||||
|
||||
// Show only the centre 75% of the TV frame.
|
||||
|
@ -31,7 +31,7 @@ class MOS6502InterruptTests: XCTestCase {
|
||||
machine.setValue(0x4000, for: CSTestMachine6502Register.programCounter)
|
||||
}
|
||||
|
||||
func testIRQLine() {
|
||||
func testIRQLine() {
|
||||
// run for six cycles; check that no interrupt has occurred
|
||||
machine.runForNumber(ofCycles: 6)
|
||||
XCTAssert(machine.value(for: .programCounter) == 0x4003, "No interrupt should have occurred with line low")
|
||||
@ -46,9 +46,9 @@ class MOS6502InterruptTests: XCTestCase {
|
||||
XCTAssert(machine.value(for: .programCounter) != 0x1234, "Interrupt routine should not yet have begun")
|
||||
machine.runForNumber(ofCycles: 1)
|
||||
XCTAssert(machine.value(for: .programCounter) == 0x1234, "Interrupt routine should just have begun")
|
||||
}
|
||||
}
|
||||
|
||||
func testIFlagSet() {
|
||||
func testIFlagSet() {
|
||||
// enable the interrupt line, run for eleven cycles to get past the CLIP and the following NOP and into the interrupt routine
|
||||
machine.irqLine = true
|
||||
machine.runForNumber(ofCycles: 11)
|
||||
@ -57,7 +57,7 @@ class MOS6502InterruptTests: XCTestCase {
|
||||
XCTAssert(machine.value(for: .flags) & 0x04 == 0x04, "Interrupt status flag should be set")
|
||||
}
|
||||
|
||||
func testCLISEIFlagClear() {
|
||||
func testCLISEIFlagClear() {
|
||||
// set up an SEI as the second instruction, enable the IRQ line
|
||||
machine.setValue(0x78, forAddress: 0x4001)
|
||||
machine.irqLine = true
|
||||
|
@ -287,16 +287,16 @@ std::string final_path_component(const std::string &path) {
|
||||
Executes @c command and returns its STDOUT.
|
||||
*/
|
||||
std::string system_get(const char *command) {
|
||||
std::unique_ptr<FILE, decltype((pclose))> pipe(popen(command, "r"), pclose);
|
||||
if(!pipe) return "";
|
||||
std::unique_ptr<FILE, decltype((pclose))> pipe(popen(command, "r"), pclose);
|
||||
if(!pipe) return "";
|
||||
|
||||
std::string result;
|
||||
while(!feof(pipe.get())) {
|
||||
while(!feof(pipe.get())) {
|
||||
std::array<char, 256> buffer;
|
||||
if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
if(fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -240,10 +240,14 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_chroma_luma_separat
|
||||
"texture(texID, inputPositionsVarying[5]).r,"
|
||||
"texture(texID, inputPositionsVarying[6]).r"
|
||||
");"
|
||||
// calculate luminance as either the straight average of the samples, if a colour subcarrier
|
||||
// was present, or else a weighted sample around the third sample if not.
|
||||
"float luminance = mix(dot(samples, vec4(0.25)), dot(samples, vec4(0.0, 0.16, 0.66, 0.16)), step(phaseAndAmplitudeVarying.z, 0.0));"
|
||||
|
||||
// define chroma to be whatever was here, minus luma
|
||||
"float chrominance = 0.5 * (samples.z - luminance) * phaseAndAmplitudeVarying.z;"
|
||||
|
||||
// scale luminance up to the range [0, 1)
|
||||
"luminance /= (1.0 - abs(phaseAndAmplitudeVarying.y));"
|
||||
|
||||
// split choma colours here, as the most direct place, writing out
|
||||
|
@ -83,7 +83,7 @@ std::unique_ptr<OutputShader> OutputShader::make_shader(const char *fragment_met
|
||||
|
||||
"void main(void)"
|
||||
"{"
|
||||
"fragColour = vec4(pow(" << colour_expression << ", vec3(gamma)), 0.8);"//*cos(lateralVarying)
|
||||
"fragColour = vec4(pow(" << colour_expression << ", vec3(gamma)), 0.64);"//*cos(lateralVarying)
|
||||
"}";
|
||||
|
||||
return std::unique_ptr<OutputShader>(new OutputShader(vertex_shader.str(), fragment_shader.str(), {
|
||||
|
@ -239,17 +239,16 @@ void Shader::set_uniform_matrix(const std::string &name, GLint size, bool transp
|
||||
|
||||
void Shader::set_uniform_matrix(const std::string &name, GLint size, GLsizei count, bool transpose, const GLfloat *values) {
|
||||
std::size_t number_of_values = static_cast<std::size_t>(count) * static_cast<std::size_t>(size) * static_cast<std::size_t>(size);
|
||||
GLfloat *values_copy = new GLfloat[number_of_values];
|
||||
std::memcpy(values_copy, values, sizeof(*values) * number_of_values);
|
||||
std::vector<GLfloat> values_copy(number_of_values);
|
||||
std::memcpy(values_copy.data(), values, sizeof(*values) * number_of_values);
|
||||
|
||||
enqueue_function([name, size, count, transpose, values_copy, this] {
|
||||
GLboolean glTranspose = transpose ? GL_TRUE : GL_FALSE;
|
||||
switch(size) {
|
||||
case 2: glUniformMatrix2fv(location(), count, glTranspose, values_copy); break;
|
||||
case 3: glUniformMatrix3fv(location(), count, glTranspose, values_copy); break;
|
||||
case 4: glUniformMatrix4fv(location(), count, glTranspose, values_copy); break;
|
||||
case 2: glUniformMatrix2fv(location(), count, glTranspose, values_copy.data()); break;
|
||||
case 3: glUniformMatrix3fv(location(), count, glTranspose, values_copy.data()); break;
|
||||
case 4: glUniformMatrix4fv(location(), count, glTranspose, values_copy.data()); break;
|
||||
}
|
||||
delete[] values_copy;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ void NIB::set_tracks(const std::map<Track::Address, std::shared_ptr<Track>> &tra
|
||||
// Lock the file and spool out.
|
||||
std::lock_guard<std::mutex> lock_guard(file_.get_file_access_mutex());
|
||||
for(const auto &track: tracks_by_address) {
|
||||
file_.seek(file_offset(track.first), SEEK_SET);
|
||||
file_.write(track.second);
|
||||
file_.seek(file_offset(track.first), SEEK_SET);
|
||||
file_.write(track.second);
|
||||
}
|
||||
}
|
||||
|
@ -42,55 +42,55 @@ FileHolder::FileHolder(const std::string &file_name, FileMode ideal_mode)
|
||||
}
|
||||
|
||||
uint32_t FileHolder::get32le() {
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_));
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 24;
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_));
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 24;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FileHolder::get32be() {
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_)) << 24;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_));
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_)) << 24;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_));
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FileHolder::get24le() {
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_));
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_));
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FileHolder::get24be() {
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_));
|
||||
uint32_t result = static_cast<uint32_t>(std::fgetc(file_)) << 16;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_)) << 8;
|
||||
result |= static_cast<uint32_t>(std::fgetc(file_));
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t FileHolder::get16le() {
|
||||
uint16_t result = static_cast<uint16_t>(std::fgetc(file_));
|
||||
result |= static_cast<uint16_t>(static_cast<uint16_t>(std::fgetc(file_)) << 8);
|
||||
uint16_t result = static_cast<uint16_t>(std::fgetc(file_));
|
||||
result |= static_cast<uint16_t>(static_cast<uint16_t>(std::fgetc(file_)) << 8);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t FileHolder::get16be() {
|
||||
uint16_t result = static_cast<uint16_t>(static_cast<uint16_t>(std::fgetc(file_)) << 8);
|
||||
result |= static_cast<uint16_t>(std::fgetc(file_));
|
||||
uint16_t result = static_cast<uint16_t>(static_cast<uint16_t>(std::fgetc(file_)) << 8);
|
||||
result |= static_cast<uint16_t>(std::fgetc(file_));
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t FileHolder::get8() {
|
||||
return static_cast<uint8_t>(std::fgetc(file_));
|
||||
return static_cast<uint8_t>(std::fgetc(file_));
|
||||
}
|
||||
|
||||
void FileHolder::put16be(uint16_t value) {
|
||||
@ -118,7 +118,7 @@ std::vector<uint8_t> FileHolder::read(std::size_t size) {
|
||||
}
|
||||
|
||||
std::size_t FileHolder::read(uint8_t *buffer, std::size_t size) {
|
||||
return std::fread(buffer, 1, size, file_);
|
||||
return std::fread(buffer, 1, size, file_);
|
||||
}
|
||||
|
||||
std::size_t FileHolder::write(const std::vector<uint8_t> &buffer) {
|
||||
@ -126,7 +126,7 @@ std::size_t FileHolder::write(const std::vector<uint8_t> &buffer) {
|
||||
}
|
||||
|
||||
std::size_t FileHolder::write(const uint8_t *buffer, std::size_t size) {
|
||||
return std::fwrite(buffer, 1, size, file_);
|
||||
return std::fwrite(buffer, 1, size, file_);
|
||||
}
|
||||
|
||||
void FileHolder::seek(long offset, int whence) {
|
||||
@ -160,24 +160,22 @@ bool FileHolder::check_signature(const char *signature, std::size_t length) {
|
||||
}
|
||||
|
||||
std::string FileHolder::extension() {
|
||||
std::size_t pointer = name_.size() - 1;
|
||||
while(pointer > 0 && name_[pointer] != '.') pointer--;
|
||||
if(name_[pointer] == '.') pointer++;
|
||||
std::size_t pointer = name_.size() - 1;
|
||||
while(pointer > 0 && name_[pointer] != '.') pointer--;
|
||||
if(name_[pointer] == '.') pointer++;
|
||||
|
||||
std::string extension = name_.substr(pointer);
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
|
||||
return extension;
|
||||
std::string extension = name_.substr(pointer);
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
|
||||
return extension;
|
||||
}
|
||||
|
||||
void FileHolder::ensure_is_at_least_length(long length) {
|
||||
std::fseek(file_, 0, SEEK_END);
|
||||
long bytes_to_write = length - ftell(file_);
|
||||
if(bytes_to_write > 0) {
|
||||
uint8_t *empty = new uint8_t[static_cast<std::size_t>(bytes_to_write)];
|
||||
std::memset(empty, 0, static_cast<std::size_t>(bytes_to_write));
|
||||
std::fwrite(empty, sizeof(uint8_t), static_cast<std::size_t>(bytes_to_write), file_);
|
||||
delete[] empty;
|
||||
}
|
||||
std::fseek(file_, 0, SEEK_END);
|
||||
long bytes_to_write = length - ftell(file_);
|
||||
if(bytes_to_write > 0) {
|
||||
std::vector<uint8_t> empty(static_cast<std::size_t>(bytes_to_write), 0);
|
||||
std::fwrite(empty.data(), sizeof(uint8_t), static_cast<std::size_t>(bytes_to_write), file_);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileHolder::get_is_known_read_only() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user