1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-19 14:25:35 +00:00

Merge pull request #760 from TomHarte/MoreAsserts

Throws in additional asserts.
This commit is contained in:
Thomas Harte 2020-02-20 11:19:03 -05:00 committed by GitHub
commit f0ec168ac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 45 deletions

View File

@ -34,6 +34,7 @@
#include "../../Analyser/Static/AmstradCPC/Target.hpp" #include "../../Analyser/Static/AmstradCPC/Target.hpp"
#include <array>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
@ -62,7 +63,7 @@ class InterruptTimer {
inline void signal_hsync() { inline void signal_hsync() {
// Increment the timer and if it has hit 52 then reset it and // Increment the timer and if it has hit 52 then reset it and
// set the interrupt request line to true. // set the interrupt request line to true.
timer_++; ++timer_;
if(timer_ == 52) { if(timer_ == 52) {
timer_ = 0; timer_ = 0;
interrupt_request_ = true; interrupt_request_ = true;
@ -72,7 +73,7 @@ class InterruptTimer {
// further horizontal syncs the timer should either (i) set the interrupt // further horizontal syncs the timer should either (i) set the interrupt
// line, if bit 4 is clear; or (ii) reset the timer. // line, if bit 4 is clear; or (ii) reset the timer.
if(reset_counter_) { if(reset_counter_) {
reset_counter_--; --reset_counter_;
if(!reset_counter_) { if(!reset_counter_) {
if(timer_ & 32) { if(timer_ & 32) {
interrupt_request_ = true; interrupt_request_ = true;
@ -199,12 +200,12 @@ class CRTCBusHandler {
cycles_into_hsync_ = 0; cycles_into_hsync_ = 0;
} }
bool is_hsync = (cycles_into_hsync_ >= 2 && cycles_into_hsync_ < 6); const bool is_hsync = (cycles_into_hsync_ >= 2 && cycles_into_hsync_ < 6);
bool is_colour_burst = (cycles_into_hsync_ >= 7 && cycles_into_hsync_ < 11); const bool is_colour_burst = (cycles_into_hsync_ >= 7 && cycles_into_hsync_ < 11);
// Sync is taken to override pixels, and is combined as a simple OR. // Sync is taken to override pixels, and is combined as a simple OR.
bool is_sync = is_hsync || state.vsync; const bool is_sync = is_hsync || state.vsync;
bool is_blank = !is_sync && state.hsync; const bool is_blank = !is_sync && state.hsync;
OutputMode output_mode; OutputMode output_mode;
if(is_sync) { if(is_sync) {
@ -378,7 +379,7 @@ class CRTCBusHandler {
border_ = mapped_palette_value(colour); border_ = mapped_palette_value(colour);
} else { } else {
palette_[pen_] = mapped_palette_value(colour); palette_[pen_] = mapped_palette_value(colour);
patch_mode_table(pen_); patch_mode_table(size_t(pen_));
} }
} }
@ -397,27 +398,38 @@ class CRTCBusHandler {
} }
} }
#define Mode0Colour0(c) ((c & 0x80) >> 7) | ((c & 0x20) >> 3) | ((c & 0x08) >> 2) | ((c & 0x02) << 2) #define Mode0Colour0(c) (((c & 0x80) >> 7) | ((c & 0x20) >> 3) | ((c & 0x08) >> 2) | ((c & 0x02) << 2))
#define Mode0Colour1(c) ((c & 0x40) >> 6) | ((c & 0x10) >> 2) | ((c & 0x04) >> 1) | ((c & 0x01) << 3) #define Mode0Colour1(c) (((c & 0x40) >> 6) | ((c & 0x10) >> 2) | ((c & 0x04) >> 1) | ((c & 0x01) << 3))
#define Mode1Colour0(c) ((c & 0x80) >> 7) | ((c & 0x08) >> 2) #define Mode1Colour0(c) (((c & 0x80) >> 7) | ((c & 0x08) >> 2))
#define Mode1Colour1(c) ((c & 0x40) >> 6) | ((c & 0x04) >> 1) #define Mode1Colour1(c) (((c & 0x40) >> 6) | ((c & 0x04) >> 1))
#define Mode1Colour2(c) ((c & 0x20) >> 5) | ((c & 0x02) >> 0) #define Mode1Colour2(c) (((c & 0x20) >> 5) | ((c & 0x02) >> 0))
#define Mode1Colour3(c) ((c & 0x10) >> 4) | ((c & 0x01) << 1) #define Mode1Colour3(c) (((c & 0x10) >> 4) | ((c & 0x01) << 1))
#define Mode3Colour0(c) ((c & 0x80) >> 7) | ((c & 0x08) >> 2) #define Mode3Colour0(c) (((c & 0x80) >> 7) | ((c & 0x08) >> 2))
#define Mode3Colour1(c) ((c & 0x40) >> 6) | ((c & 0x04) >> 1) #define Mode3Colour1(c) (((c & 0x40) >> 6) | ((c & 0x04) >> 1))
/*!
Creates a lookup table from palette entry to list of affected entries in the value -> pixels lookup tables.
*/
void establish_palette_hits() { void establish_palette_hits() {
for(int c = 0; c < 256; c++) { for(size_t c = 0; c < 256; c++) {
assert(Mode0Colour0(c) < mode0_palette_hits_.size());
assert(Mode0Colour1(c) < mode0_palette_hits_.size());
mode0_palette_hits_[Mode0Colour0(c)].push_back(uint8_t(c)); mode0_palette_hits_[Mode0Colour0(c)].push_back(uint8_t(c));
mode0_palette_hits_[Mode0Colour1(c)].push_back(uint8_t(c)); mode0_palette_hits_[Mode0Colour1(c)].push_back(uint8_t(c));
assert(Mode1Colour0(c) < mode1_palette_hits_.size());
assert(Mode1Colour1(c) < mode1_palette_hits_.size());
assert(Mode1Colour2(c) < mode1_palette_hits_.size());
assert(Mode1Colour3(c) < mode1_palette_hits_.size());
mode1_palette_hits_[Mode1Colour0(c)].push_back(uint8_t(c)); mode1_palette_hits_[Mode1Colour0(c)].push_back(uint8_t(c));
mode1_palette_hits_[Mode1Colour1(c)].push_back(uint8_t(c)); mode1_palette_hits_[Mode1Colour1(c)].push_back(uint8_t(c));
mode1_palette_hits_[Mode1Colour2(c)].push_back(uint8_t(c)); mode1_palette_hits_[Mode1Colour2(c)].push_back(uint8_t(c));
mode1_palette_hits_[Mode1Colour3(c)].push_back(uint8_t(c)); mode1_palette_hits_[Mode1Colour3(c)].push_back(uint8_t(c));
assert(Mode3Colour0(c) < mode3_palette_hits_.size());
assert(Mode3Colour1(c) < mode3_palette_hits_.size());
mode3_palette_hits_[Mode3Colour0(c)].push_back(uint8_t(c)); mode3_palette_hits_[Mode3Colour0(c)].push_back(uint8_t(c));
mode3_palette_hits_[Mode3Colour1(c)].push_back(uint8_t(c)); mode3_palette_hits_[Mode3Colour1(c)].push_back(uint8_t(c));
} }
@ -427,8 +439,8 @@ class CRTCBusHandler {
switch(mode_) { switch(mode_) {
case 0: case 0:
// Mode 0: abcdefgh -> [gcea] [hdfb] // Mode 0: abcdefgh -> [gcea] [hdfb]
for(int c = 0; c < 256; c++) { for(size_t c = 0; c < 256; c++) {
// prepare mode 0 // Prepare mode 0.
uint8_t *const mode0_pixels = reinterpret_cast<uint8_t *>(&mode0_output_[c]); uint8_t *const mode0_pixels = reinterpret_cast<uint8_t *>(&mode0_output_[c]);
mode0_pixels[0] = palette_[Mode0Colour0(c)]; mode0_pixels[0] = palette_[Mode0Colour0(c)];
mode0_pixels[1] = palette_[Mode0Colour1(c)]; mode0_pixels[1] = palette_[Mode0Colour1(c)];
@ -436,8 +448,8 @@ class CRTCBusHandler {
break; break;
case 1: case 1:
for(int c = 0; c < 256; c++) { for(size_t c = 0; c < 256; c++) {
// prepare mode 1 // Prepare mode 1.
uint8_t *const mode1_pixels = reinterpret_cast<uint8_t *>(&mode1_output_[c]); uint8_t *const mode1_pixels = reinterpret_cast<uint8_t *>(&mode1_output_[c]);
mode1_pixels[0] = palette_[Mode1Colour0(c)]; mode1_pixels[0] = palette_[Mode1Colour0(c)];
mode1_pixels[1] = palette_[Mode1Colour1(c)]; mode1_pixels[1] = palette_[Mode1Colour1(c)];
@ -447,8 +459,8 @@ class CRTCBusHandler {
break; break;
case 2: case 2:
for(int c = 0; c < 256; c++) { for(size_t c = 0; c < 256; c++) {
// prepare mode 2 // Prepare mode 2.
uint8_t *const mode2_pixels = reinterpret_cast<uint8_t *>(&mode2_output_[c]); uint8_t *const mode2_pixels = reinterpret_cast<uint8_t *>(&mode2_output_[c]);
mode2_pixels[0] = palette_[((c & 0x80) >> 7)]; mode2_pixels[0] = palette_[((c & 0x80) >> 7)];
mode2_pixels[1] = palette_[((c & 0x40) >> 6)]; mode2_pixels[1] = palette_[((c & 0x40) >> 6)];
@ -462,8 +474,8 @@ class CRTCBusHandler {
break; break;
case 3: case 3:
for(int c = 0; c < 256; c++) { for(size_t c = 0; c < 256; c++) {
// prepare mode 3 // Prepare mode 3.
uint8_t *const mode3_pixels = reinterpret_cast<uint8_t *>(&mode3_output_[c]); uint8_t *const mode3_pixels = reinterpret_cast<uint8_t *>(&mode3_output_[c]);
mode3_pixels[0] = palette_[Mode3Colour0(c)]; mode3_pixels[0] = palette_[Mode3Colour0(c)];
mode3_pixels[1] = palette_[Mode3Colour1(c)]; mode3_pixels[1] = palette_[Mode3Colour1(c)];
@ -472,18 +484,20 @@ class CRTCBusHandler {
} }
} }
void patch_mode_table(int pen) { void patch_mode_table(size_t pen) {
switch(mode_) { switch(mode_) {
case 0: { case 0: {
for(uint8_t c : mode0_palette_hits_[pen]) { for(uint8_t c : mode0_palette_hits_[pen]) {
assert(c < mode0_output_.size());
uint8_t *const mode0_pixels = reinterpret_cast<uint8_t *>(&mode0_output_[c]); uint8_t *const mode0_pixels = reinterpret_cast<uint8_t *>(&mode0_output_[c]);
mode0_pixels[0] = palette_[Mode0Colour0(c)]; mode0_pixels[0] = palette_[Mode0Colour0(c)];
mode0_pixels[1] = palette_[Mode0Colour1(c)]; mode0_pixels[1] = palette_[Mode0Colour1(c)];
} }
} break; } break;
case 1: case 1:
if(pen > 3) return; if(pen >= mode1_palette_hits_.size()) return;
for(uint8_t c : mode1_palette_hits_[pen]) { for(uint8_t c : mode1_palette_hits_[pen]) {
assert(c < mode1_output_.size());
uint8_t *const mode1_pixels = reinterpret_cast<uint8_t *>(&mode1_output_[c]); uint8_t *const mode1_pixels = reinterpret_cast<uint8_t *>(&mode1_output_[c]);
mode1_pixels[0] = palette_[Mode1Colour0(c)]; mode1_pixels[0] = palette_[Mode1Colour0(c)];
mode1_pixels[1] = palette_[Mode1Colour1(c)]; mode1_pixels[1] = palette_[Mode1Colour1(c)];
@ -498,9 +512,10 @@ class CRTCBusHandler {
build_mode_table(); build_mode_table();
break; break;
case 3: case 3:
if(pen > 3) return; if(pen >= mode3_palette_hits_.size()) return;
// Same argument applies here as to case 1, as the unused bits aren't masked out. // Same argument applies here as to case 1, as the unused bits aren't masked out.
for(uint8_t c : mode3_palette_hits_[pen]) { for(uint8_t c : mode3_palette_hits_[pen]) {
assert(c < mode3_output_.size());
uint8_t *const mode3_pixels = reinterpret_cast<uint8_t *>(&mode3_output_[c]); uint8_t *const mode3_pixels = reinterpret_cast<uint8_t *>(&mode3_output_[c]);
mode3_pixels[0] = palette_[Mode3Colour0(c)]; mode3_pixels[0] = palette_[Mode3Colour0(c)];
mode3_pixels[1] = palette_[Mode3Colour1(c)]; mode3_pixels[1] = palette_[Mode3Colour1(c)];
@ -556,14 +571,14 @@ class CRTCBusHandler {
int next_mode_ = 2, mode_ = 2; int next_mode_ = 2, mode_ = 2;
int pixel_divider_ = 1; int pixel_divider_ = 1;
uint16_t mode0_output_[256]; std::array<uint16_t, 256> mode0_output_;
uint32_t mode1_output_[256]; std::array<uint32_t, 256> mode1_output_;
uint64_t mode2_output_[256]; std::array<uint64_t, 256> mode2_output_;
uint16_t mode3_output_[256]; std::array<uint16_t, 256> mode3_output_;
std::vector<uint8_t> mode0_palette_hits_[16]; std::array<std::vector<uint8_t>, 16> mode0_palette_hits_;
std::vector<uint8_t> mode1_palette_hits_[4]; std::array<std::vector<uint8_t>, 4> mode1_palette_hits_;
std::vector<uint8_t> mode3_palette_hits_[4]; std::array<std::vector<uint8_t>, 4> mode3_palette_hits_;
int pen_ = 0; int pen_ = 0;
uint8_t palette_[16]; uint8_t palette_[16];
@ -837,18 +852,18 @@ template <bool has_fdc> class ConcreteMachine:
for(std::size_t index = 0; index < roms.size(); ++index) { for(std::size_t index = 0; index < roms.size(); ++index) {
auto &data = roms[index]; auto &data = roms[index];
if(!data) throw ROMMachine::Error::MissingROMs; if(!data) throw ROMMachine::Error::MissingROMs;
roms_[int(index)] = std::move(*data); roms_[index] = std::move(*data);
roms_[int(index)].resize(16384); roms_[index].resize(16384);
} }
// Establish default memory map // Establish default memory map
upper_rom_is_paged_ = true; upper_rom_is_paged_ = true;
upper_rom_ = ROMType::BASIC; upper_rom_ = ROMType::BASIC;
write_pointers_[0] = &ram_[0]; write_pointers_[0] = &ram_[0x0000];
write_pointers_[1] = &ram_[16384]; write_pointers_[1] = &ram_[0x4000];
write_pointers_[2] = &ram_[32768]; write_pointers_[2] = &ram_[0x8000];
write_pointers_[3] = &ram_[49152]; write_pointers_[3] = &ram_[0xc000];
read_pointers_[0] = roms_[ROMType::OS].data(); read_pointers_[0] = roms_[ROMType::OS].data();
read_pointers_[1] = write_pointers_[1]; read_pointers_[1] = write_pointers_[1];
@ -874,7 +889,7 @@ template <bool has_fdc> class ConcreteMachine:
// will do as it's safe to conclude that nobody else has touched video RAM // will do as it's safe to conclude that nobody else has touched video RAM
// during that whole window // during that whole window
crtc_counter_ += cycle.length; crtc_counter_ += cycle.length;
Cycles crtc_cycles = crtc_counter_.divide_cycles(Cycles(4)); const Cycles crtc_cycles = crtc_counter_.divide_cycles(Cycles(4));
if(crtc_cycles > Cycles(0)) crtc_.run_for(crtc_cycles); if(crtc_cycles > Cycles(0)) crtc_.run_for(crtc_cycles);
// Check whether that prompted a change in the interrupt line. If so then date // Check whether that prompted a change in the interrupt line. If so then date
@ -1142,8 +1157,8 @@ template <bool has_fdc> class ConcreteMachine:
case 3: case 3:
// Perform RAM paging, if 128kb is permitted. // Perform RAM paging, if 128kb is permitted.
if(has_128k_) { if(has_128k_) {
bool adjust_low_read_pointer = read_pointers_[0] == write_pointers_[0]; const bool adjust_low_read_pointer = read_pointers_[0] == write_pointers_[0];
bool adjust_high_read_pointer = read_pointers_[3] == write_pointers_[3]; const bool adjust_high_read_pointer = read_pointers_[3] == write_pointers_[3];
#define RAM_BANK(x) &ram_[x * 16384] #define RAM_BANK(x) &ram_[x * 16384]
#define RAM_CONFIG(a, b, c, d) write_pointers_[0] = RAM_BANK(a); write_pointers_[1] = RAM_BANK(b); write_pointers_[2] = RAM_BANK(c); write_pointers_[3] = RAM_BANK(d); #define RAM_CONFIG(a, b, c, d) write_pointers_[0] = RAM_BANK(a); write_pointers_[1] = RAM_BANK(b); write_pointers_[2] = RAM_BANK(c); write_pointers_[3] = RAM_BANK(d);
switch(value & 7) { switch(value & 7) {
@ -1195,8 +1210,6 @@ template <bool has_fdc> class ConcreteMachine:
HalfCycles crtc_counter_; HalfCycles crtc_counter_;
HalfCycles half_cycles_since_ay_update_; HalfCycles half_cycles_since_ay_update_;
uint8_t ram_[128 * 1024];
bool fdc_is_sleeping_; bool fdc_is_sleeping_;
bool tape_player_is_sleeping_; bool tape_player_is_sleeping_;
bool has_128k_; bool has_128k_;
@ -1214,6 +1227,8 @@ template <bool has_fdc> class ConcreteMachine:
KeyboardState key_state_; KeyboardState key_state_;
AmstradCPC::KeyboardMapper keyboard_mapper_; AmstradCPC::KeyboardMapper keyboard_mapper_;
uint8_t ram_[128 * 1024];
}; };
} }

View File

@ -218,6 +218,8 @@ uint8_t *ScanTarget::begin_data(size_t required_length, size_t required_alignmen
// Everything checks out, note expectation of a future end_data and return the pointer. // Everything checks out, note expectation of a future end_data and return the pointer.
data_is_allocated_ = true; data_is_allocated_ = true;
vended_write_area_pointer_ = write_pointers_.write_area = TextureAddress(aligned_start_x, output_y); vended_write_area_pointer_ = write_pointers_.write_area = TextureAddress(aligned_start_x, output_y);
assert(write_pointers_.write_area >= 1 && ((size_t(write_pointers_.write_area) + required_length + 1) * data_type_size_) <= write_area_texture_.size());
return &write_area_texture_[size_t(write_pointers_.write_area) * data_type_size_]; return &write_area_texture_[size_t(write_pointers_.write_area) * data_type_size_];
// Note state at exit: // Note state at exit: