1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Resolve various type conversion errors, and reduce duplication.

This commit is contained in:
Thomas Harte 2023-02-01 14:17:49 -05:00
parent 90e8ce3253
commit 002d27d9c2
3 changed files with 72 additions and 87 deletions

View File

@ -488,7 +488,7 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
this->asked_for_write_area_ = true;
this->pixel_origin_ = this->pixel_target_ = reinterpret_cast<uint32_t *>(
this->crt_.begin_data(line_buffer.pixel_count)
this->crt_.begin_data(size_t(line_buffer.pixel_count))
);
}
@ -507,7 +507,7 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
if(end == line_buffer.next_border_column) {
const int length = line_buffer.next_border_column - line_buffer.first_pixel_output_column;
this->crt_.output_data(from_internal<personality, Clock::CRT>(length), line_buffer.pixel_count);
this->crt_.output_data(from_internal<personality, Clock::CRT>(length), size_t(line_buffer.pixel_count));
this->pixel_origin_ = this->pixel_target_ = nullptr;
this->asked_for_write_area_ = false;
}
@ -645,32 +645,11 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
if(sprites_magnified_) sprite_height_ <<= 1;
break;
case 2:
pattern_name_address_ = size_t((value & 0xf) << 10) | 0x3ff;
break;
case 3:
colour_table_address_ =
(colour_table_address_ & ~0x3fc0) |
(value << 6) |
0x3f;
break;
case 4:
pattern_generator_table_address_ = size_t((value & 0x07) << 11) | 0x7ff;
// TODO: don't mask off so many bits for, at least, the Yamahas.
break;
case 5:
sprite_attribute_table_address_ =
(sprite_attribute_table_address_ & ~0x3d80) |
((value << 7) & 0x3f80) |
0x7f;
break;
case 6:
sprite_generator_table_address_ = size_t((value & 0x07) << 11) | 0x7ff;
break;
case 2: install_field<10>(pattern_name_address_, value); break;
case 3: install_field<6>(colour_table_address_, value); break;
case 4: install_field<11>(pattern_generator_table_address_, value); break;
case 5: install_field<7>(sprite_attribute_table_address_, value); break;
case 6: install_field<11>(sprite_generator_table_address_, value); break;
case 7:
text_colour_ = value >> 4;
@ -755,11 +734,6 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
LOG("Screen mode: " << int(current_screen_mode()));
break;
case 2:
// Retain extra addressing bits.
pattern_name_address_ = size_t((value & 0x7f) << 10) | 0x3ff;
break;
case 8:
LOG("TODO: Yamaha VRAM organisation, sprite disable, etc; " << PADHEX(2) << +value);
// b7: "1 = input on colour bus, enable mouse; 1 = output on colour bus, disable mouse" [documentation clearly in error]
@ -781,19 +755,11 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
// b0: 1 = [dot clock] DLCLK is input; 0 = DLCLK is output
break;
case 10:
colour_table_address_ =
(colour_table_address_ & ~0x1c000) |
((value << 14) & 0x1c000);
// b0b2: A14A16 of the colour table.
break;
// b0b2: A14A16 of the colour table.
case 10: install_field<14>(colour_table_address_, value); break;
case 11:
sprite_attribute_table_address_ =
(sprite_attribute_table_address_ & ~0x18000) |
((value << 15) & 0x18000);
// b0b1: A15A16 of the sprite table.
break;
// b0b1: A15A16 of the sprite table.
case 11: install_field<15>(sprite_attribute_table_address_, value); break;
case 12:
LOG("TODO: Yamaha text and background blink colour; " << PADHEX(2) << +value);
@ -806,9 +772,7 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
// b4b7: display time for even page.
break;
case 14:
ram_pointer_ = (ram_pointer_ & ~0x1c000) | ((value << 14) & 0x1c000);
break;
case 14: install_field<14>(ram_pointer_, value); break;
case 15:
Storage<personality>::selected_status_ = value & 0xf;
@ -863,8 +827,8 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
case 44:
Storage<personality>::command_context_.colour = value;
Storage<personality>::command_context_.colour4bpp = (value & 0xf) | (value << 4);
Storage<personality>::command_context_.colour2bpp = (value & 0x3) | ((value & 0x3) << 2) | ((value & 0x3) << 4) | ((value & 0x3) << 6);
Storage<personality>::command_context_.colour4bpp = uint8_t((value & 0xf) | (value << 4));
Storage<personality>::command_context_.colour2bpp = uint8_t((value & 0x3) | ((value & 0x3) << 2) | ((value & 0x3) << 4) | ((value & 0x3) << 6));
// Check whether a command was blocked on this.
if(
@ -948,13 +912,12 @@ void Base<personality>::write_register(uint8_t value) {
write_phase_ = true;
// The initial write should half update the access pointer.
ram_pointer_ = (ram_pointer_ & ~0xff) | low_write_;
install_field<0>(ram_pointer_, value);
return;
}
// The RAM pointer is always set on a second write, regardless of
// whether the caller is intending to enqueue a VDP operation.
ram_pointer_ = (ram_pointer_ & ~0x3f00) | ((value << 8) & 0x3f00);
// whether the caller is intending to enqueue a VDP operation. install_field<8, 0x3f>(ram_pointer_, value);
write_phase_ = false;
if(value & 0x80) {

View File

@ -86,7 +86,7 @@ struct LineBuffer {
*/
int first_pixel_output_column = 94;
int next_border_column = 334;
size_t pixel_count = 256;
int pixel_count = 256;
// An active sprite is one that has been selected for composition onto
// this line.
@ -121,11 +121,15 @@ template <Personality personality, typename Enable = void> struct Storage {
};
template <> struct Storage<Personality::TMS9918A> {
using AddressT = uint16_t;
void begin_line(ScreenMode, bool, bool) {}
};
// Yamaha-specific storage.
template <Personality personality> struct Storage<personality, std::enable_if_t<is_yamaha_vdp(personality)>> {
using AddressT = uint32_t;
int selected_status_ = 0;
int indirect_register_ = 0;
@ -351,6 +355,8 @@ template <Personality personality> struct Storage<personality, std::enable_if_t<
// Master System-specific storage.
template <Personality personality> struct Storage<personality, std::enable_if_t<is_sega_vdp(personality)>> {
using AddressT = uint16_t;
// The SMS VDP has a programmer-set colour palette, with a dedicated patch of RAM. But the RAM is only exactly
// fast enough for the pixel clock. So when the programmer writes to it, that causes a one-pixel glitch; there
// isn't the bandwidth for the read both write to occur simultaneously. The following buffer therefore keeps
@ -379,10 +385,10 @@ template <Personality personality> struct Storage<personality, std::enable_if_t<
uint8_t latched_vertical_scroll_ = 0;
// Various resource addresses with VDP-version-specific modifications
// built int.
size_t pattern_name_address_;
size_t sprite_attribute_table_address_;
size_t sprite_generator_table_address_;
// built in.
AddressT pattern_name_address_;
AddressT sprite_attribute_table_address_;
AddressT sprite_generator_table_address_;
void begin_line(ScreenMode, bool, bool) {}
};
@ -432,6 +438,18 @@ template <Personality personality> struct Base: public Storage<personality> {
Outputs::CRT::CRT crt_;
TVStandard tv_standard_ = TVStandard::NTSC;
using AddressT = typename Storage<personality>::AddressT;
/// Mutates @c target such that @c source & @c source_mask replaces the bits that currently start
/// at @c shift bits from least significant. Subsequently ensures @c target is constrained by the
/// applicable @c memory_mask.
template <int shift, uint8_t source_mask = 0xff> void install_field(AddressT &target, uint8_t source) {
constexpr auto mask = AddressT(~(source_mask << shift));
target = (
(target & mask) |
AddressT((source & source_mask) << shift)
) & memory_mask(personality);
}
// Personality-specific metrics and converters.
ClockConverter<personality> clock_converter_;
@ -440,7 +458,7 @@ template <Personality personality> struct Base: public Storage<personality> {
std::array<uint8_t, memory_size(personality)> ram_;
// State of the DRAM/CRAM-access mechanism.
size_t ram_pointer_ = 0;
AddressT ram_pointer_ = 0;
uint8_t read_ahead_buffer_ = 0;
MemoryAccess queued_access_ = MemoryAccess::None;
int minimum_access_column_ = 0;
@ -463,11 +481,11 @@ template <Personality personality> struct Base: public Storage<personality> {
int sprite_height_ = 8;
// Programmer-specified addresses.
size_t pattern_name_address_ = 0; // i.e. address of the tile map.
size_t colour_table_address_ = 0; // address of the colour map (if applicable).
size_t pattern_generator_table_address_ = 0; // address of the tile contents.
size_t sprite_attribute_table_address_ = 0; // address of the sprite list.
size_t sprite_generator_table_address_ = 0; // address of the sprite contents.
AddressT pattern_name_address_ = memory_mask(personality); // Address of the tile map.
AddressT colour_table_address_ = memory_mask(personality); // Address of the colour map (if applicable).
AddressT pattern_generator_table_address_ = memory_mask(personality); // Address of the tile contents.
AddressT sprite_attribute_table_address_ = memory_mask(personality); // Address of the sprite list.
AddressT sprite_generator_table_address_ = memory_mask(personality); // Address of the sprite contents.
// Default colours.
uint8_t text_colour_ = 0;
@ -588,29 +606,33 @@ template <Personality personality> struct Base: public Storage<personality> {
return ScreenMode::Blank;
}
uint32_t command_address() const {
AddressT command_address() const {
if constexpr (is_yamaha_vdp(personality)) {
switch(this->screen_mode_) {
default:
case ScreenMode::YamahaGraphics4: // 256 pixels @ 4bpp
return
return AddressT(
(Storage<personality>::command_->location.v[0] >> 1) +
(Storage<personality>::command_->location.v[1] << 7);
(Storage<personality>::command_->location.v[1] << 7)
);
case ScreenMode::YamahaGraphics5: // 512 pixels @ 2bpp
return
return AddressT(
(Storage<personality>::command_->location.v[0] >> 2) +
(Storage<personality>::command_->location.v[1] << 7);
(Storage<personality>::command_->location.v[1] << 7)
);
case ScreenMode::YamahaGraphics6: // 512 pixels @ 4bpp
return
return AddressT(
(Storage<personality>::command_->location.v[0] >> 1) +
(Storage<personality>::command_->location.v[1] << 8);
(Storage<personality>::command_->location.v[1] << 8)
);
case ScreenMode::YamahaGraphics7: // 256 pixels @ 8bpp
return
return AddressT(
(Storage<personality>::command_->location.v[0] >> 0) +
(Storage<personality>::command_->location.v[1] << 8);
(Storage<personality>::command_->location.v[1] << 8)
);
}
} else {
return 0;
@ -720,7 +742,7 @@ template <Personality personality> struct Base: public Storage<personality> {
return;
}
size_t address = ram_pointer_;
AddressT address = ram_pointer_;
++ram_pointer_;
if constexpr (is_yamaha_vdp(personality)) {

View File

@ -469,7 +469,7 @@ template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer
template <Personality personality>
template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]] LineBuffer &line_buffer, [[maybe_unused]] int y, int end) {
const int rotated_name_ = pattern_name_address_ >> 1;
const AddressT rotated_name_ = pattern_name_address_ >> 1;
const uint8_t *const ram2 = &ram_[65536];
while(Storage<personality>::next_event_->offset < end) {
@ -488,10 +488,10 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]]
const int start = (y << 7) | column | 0x1'8000;
line_buffer.bitmap[column + 0] = ram_[pattern_name_address_ & (start + 0)];
line_buffer.bitmap[column + 1] = ram_[pattern_name_address_ & (start + 1)];
line_buffer.bitmap[column + 2] = ram_[pattern_name_address_ & (start + 2)];
line_buffer.bitmap[column + 3] = ram_[pattern_name_address_ & (start + 3)];
line_buffer.bitmap[column + 0] = ram_[pattern_name_address_ & AddressT(start + 0)];
line_buffer.bitmap[column + 1] = ram_[pattern_name_address_ & AddressT(start + 1)];
line_buffer.bitmap[column + 2] = ram_[pattern_name_address_ & AddressT(start + 2)];
line_buffer.bitmap[column + 3] = ram_[pattern_name_address_ & AddressT(start + 3)];
} break;
case ScreenMode::YamahaGraphics6:
@ -502,14 +502,14 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]]
const int start = (y << 7) | column | 0x1'8000;
// Fetch from alternate banks.
line_buffer.bitmap[column + 0] = ram_[rotated_name_ & (start + 0)];
line_buffer.bitmap[column + 1] = ram2[rotated_name_ & (start + 0)];
line_buffer.bitmap[column + 2] = ram_[rotated_name_ & (start + 1)];
line_buffer.bitmap[column + 3] = ram2[rotated_name_ & (start + 1)];
line_buffer.bitmap[column + 4] = ram_[rotated_name_ & (start + 2)];
line_buffer.bitmap[column + 5] = ram2[rotated_name_ & (start + 2)];
line_buffer.bitmap[column + 6] = ram_[rotated_name_ & (start + 3)];
line_buffer.bitmap[column + 7] = ram2[rotated_name_ & (start + 3)];
line_buffer.bitmap[column + 0] = ram_[rotated_name_ & AddressT(start + 0)];
line_buffer.bitmap[column + 1] = ram2[rotated_name_ & AddressT(start + 0)];
line_buffer.bitmap[column + 2] = ram_[rotated_name_ & AddressT(start + 1)];
line_buffer.bitmap[column + 3] = ram2[rotated_name_ & AddressT(start + 1)];
line_buffer.bitmap[column + 4] = ram_[rotated_name_ & AddressT(start + 2)];
line_buffer.bitmap[column + 5] = ram2[rotated_name_ & AddressT(start + 2)];
line_buffer.bitmap[column + 6] = ram_[rotated_name_ & AddressT(start + 3)];
line_buffer.bitmap[column + 7] = ram2[rotated_name_ & AddressT(start + 3)];
} break;
default: