mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Resolve various type conversion errors, and reduce duplication.
This commit is contained in:
parent
90e8ce3253
commit
002d27d9c2
@ -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);
|
||||
// b0–b2: A14–A16 of the colour table.
|
||||
break;
|
||||
// b0–b2: A14–A16 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);
|
||||
// b0–b1: A15–A16 of the sprite table.
|
||||
break;
|
||||
// b0–b1: A15–A16 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) {
|
||||
// b4–b7: 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) {
|
||||
|
@ -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)) {
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user