1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-29 00:29:34 +00:00

Avoid need for shortcuts.

This commit is contained in:
Thomas Harte 2023-02-17 22:34:52 -05:00
parent a123ef151c
commit b62e899039

View File

@ -52,22 +52,11 @@ template <typename AddressT, int end> constexpr AddressT top_bits() {
return AddressT(~0) - AddressT((1 << end) - 1); return AddressT(~0) - AddressT((1 << end) - 1);
} }
/// Modifies and returns @c source so that all bits above position @c bits are set; the others are unmodified. /// Modifies and returns @c source so that all bits above position @c n are set; the others are unmodified.
template <typename AddressT, int bits> constexpr AddressT n_bit(AddressT source) { template <int n, typename AddressT> constexpr AddressT bits(AddressT source = 0) {
return AddressT(source | top_bits<AddressT, bits>()); return AddressT(source | top_bits<AddressT, n>());
} }
// Various convenience functions for the above; bitsX can be used to wrap a number that is internally only X bits big.
template <typename AddressT> constexpr AddressT bits6(AddressT source = 0) { return n_bit<AddressT, 6>(source); }
template <typename AddressT> constexpr AddressT bits7(AddressT source = 0) { return n_bit<AddressT, 7>(source); }
template <typename AddressT> constexpr AddressT bits8(AddressT source = 0) { return n_bit<AddressT, 8>(source); }
template <typename AddressT> constexpr AddressT bits9(AddressT source = 0) { return n_bit<AddressT, 9>(source); }
template <typename AddressT> constexpr AddressT bits10(AddressT source = 0) { return n_bit<AddressT, 10>(source); }
template <typename AddressT> constexpr AddressT bits11(AddressT source = 0) { return n_bit<AddressT, 11>(source); }
template <typename AddressT> constexpr AddressT bits12(AddressT source = 0) { return n_bit<AddressT, 12>(source); }
template <typename AddressT> constexpr AddressT bits13(AddressT source = 0) { return n_bit<AddressT, 13>(source); }
template <typename AddressT> constexpr AddressT bits15(AddressT source = 0) { return n_bit<AddressT, 15>(source); }
// MARK: - 171-window Dispatcher. // MARK: - 171-window Dispatcher.
template <Personality personality> template <Personality personality>
@ -111,8 +100,8 @@ struct TextFetcher {
TextFetcher(Base<personality> *base, LineBuffer &buffer, int y) : TextFetcher(Base<personality> *base, LineBuffer &buffer, int y) :
base(base), base(base),
line_buffer(buffer), line_buffer(buffer),
row_base(base->pattern_name_address_ & bits10(AddressT((y >> 3) * 40))), row_base(base->pattern_name_address_ & bits<10>(AddressT((y >> 3) * 40))),
row_offset(base->pattern_generator_table_address_ & bits11(AddressT(y & 7))) {} row_offset(base->pattern_generator_table_address_ & bits<11>(AddressT(y & 7))) {}
void fetch_name(AddressT column, int slot = 0) { void fetch_name(AddressT column, int slot = 0) {
base->name_[slot] = base->ram_[row_base + column]; base->name_[slot] = base->ram_[row_base + column];
@ -137,7 +126,7 @@ struct CharacterFetcher {
tile_buffer(buffer), tile_buffer(buffer),
sprite_selection_buffer(sprite_selection_buffer), sprite_selection_buffer(sprite_selection_buffer),
y(y), y(y),
row_base(base->pattern_name_address_ & bits10(AddressT((y << 2)&~31))) row_base(base->pattern_name_address_ & bits<10>(AddressT((y << 2)&~31)))
{ {
pattern_base = base->pattern_generator_table_address_; pattern_base = base->pattern_generator_table_address_;
colour_base = base->colour_table_address_; colour_base = base->colour_table_address_;
@ -145,14 +134,14 @@ struct CharacterFetcher {
if(buffer.screen_mode == ScreenMode::Graphics) { if(buffer.screen_mode == ScreenMode::Graphics) {
// If this is high resolution mode, allow the row number to affect the pattern and colour addresses. // If this is high resolution mode, allow the row number to affect the pattern and colour addresses.
pattern_base &= bits13(AddressT(((y & 0xc0) << 5))); pattern_base &= bits<13>(AddressT(((y & 0xc0) << 5)));
colour_base &= bits13(AddressT(((y & 0xc0) << 5))); colour_base &= bits<13>(AddressT(((y & 0xc0) << 5)));
colour_base += AddressT(y & 7); colour_base += AddressT(y & 7);
colour_name_shift = 0; colour_name_shift = 0;
} else { } else {
colour_base &= bits6<AddressT>(); colour_base &= bits<6, AddressT>();
pattern_base &= bits11<AddressT>(); pattern_base &= bits<11, AddressT>();
} }
if(buffer.screen_mode == ScreenMode::MultiColour) { if(buffer.screen_mode == ScreenMode::MultiColour) {
@ -165,26 +154,26 @@ struct CharacterFetcher {
void fetch_sprite_location(int sprite) { void fetch_sprite_location(int sprite) {
tile_buffer.active_sprites[sprite].x = tile_buffer.active_sprites[sprite].x =
base->ram_[ base->ram_[
base->sprite_attribute_table_address_ & bits7(AddressT((tile_buffer.active_sprites[sprite].index << 2) | 1)) base->sprite_attribute_table_address_ & bits<7>(AddressT((tile_buffer.active_sprites[sprite].index << 2) | 1))
]; ];
} }
void fetch_sprite_pattern(int sprite) { void fetch_sprite_pattern(int sprite) {
const uint8_t name = base->ram_[ const uint8_t name = base->ram_[
base->sprite_attribute_table_address_ & bits7(AddressT((tile_buffer.active_sprites[sprite].index << 2) | 2)) base->sprite_attribute_table_address_ & bits<7>(AddressT((tile_buffer.active_sprites[sprite].index << 2) | 2))
] & (base->sprites_16x16_ ? ~3 : ~0); ] & (base->sprites_16x16_ ? ~3 : ~0);
tile_buffer.active_sprites[sprite].image[2] = base->ram_[ tile_buffer.active_sprites[sprite].image[2] = base->ram_[
base->sprite_attribute_table_address_ & bits7(AddressT((tile_buffer.active_sprites[sprite].index << 2) | 3)) base->sprite_attribute_table_address_ & bits<7>(AddressT((tile_buffer.active_sprites[sprite].index << 2) | 3))
]; ];
tile_buffer.active_sprites[sprite].x -= (tile_buffer.active_sprites[sprite].image[2] & 0x80) >> 2; tile_buffer.active_sprites[sprite].x -= (tile_buffer.active_sprites[sprite].image[2] & 0x80) >> 2;
const AddressT graphic_location = base->sprite_generator_table_address_ & bits11(AddressT((name << 3) | tile_buffer.active_sprites[sprite].row)); const AddressT graphic_location = base->sprite_generator_table_address_ & bits<11>(AddressT((name << 3) | tile_buffer.active_sprites[sprite].row));
tile_buffer.active_sprites[sprite].image[0] = base->ram_[graphic_location]; tile_buffer.active_sprites[sprite].image[0] = base->ram_[graphic_location];
tile_buffer.active_sprites[sprite].image[1] = base->ram_[graphic_location+16]; tile_buffer.active_sprites[sprite].image[1] = base->ram_[graphic_location+16];
} }
void posit_sprite(int sprite) { void posit_sprite(int sprite) {
base->posit_sprite(sprite_selection_buffer, sprite, base->ram_[base->sprite_attribute_table_address_ & bits7(AddressT(sprite << 2))], y); base->posit_sprite(sprite_selection_buffer, sprite, base->ram_[base->sprite_attribute_table_address_ & bits<7>(AddressT(sprite << 2))], y);
} }
void fetch_tile_name(int column) { void fetch_tile_name(int column) {
@ -233,11 +222,11 @@ struct SMSFetcher {
// Determine row info for the screen both (i) if vertical scrolling is applied; and (ii) if it isn't. // Determine row info for the screen both (i) if vertical scrolling is applied; and (ii) if it isn't.
// The programmer can opt out of applying vertical scrolling to the right-hand portion of the display. // The programmer can opt out of applying vertical scrolling to the right-hand portion of the display.
const int scrolled_row = (y + storage->latched_vertical_scroll_) % (is_tall_mode ? 256 : 224); const int scrolled_row = (y + storage->latched_vertical_scroll_) % (is_tall_mode ? 256 : 224);
scrolled_row_info.pattern_address_base = pattern_name_address & bits11(AddressT((scrolled_row & ~7) << 3)) - pattern_name_offset; scrolled_row_info.pattern_address_base = pattern_name_address & bits<11>(AddressT((scrolled_row & ~7) << 3)) - pattern_name_offset;
scrolled_row_info.sub_row[0] = AddressT((scrolled_row & 7) << 2); scrolled_row_info.sub_row[0] = AddressT((scrolled_row & 7) << 2);
scrolled_row_info.sub_row[1] = AddressT(28 ^ ((scrolled_row & 7) << 2)); scrolled_row_info.sub_row[1] = AddressT(28 ^ ((scrolled_row & 7) << 2));
if(storage->vertical_scroll_lock_) { if(storage->vertical_scroll_lock_) {
static_row_info.pattern_address_base = bits11(AddressT(pattern_name_address & ((y & ~7) << 3))) - pattern_name_offset; static_row_info.pattern_address_base = bits<11>(AddressT(pattern_name_address & ((y & ~7) << 3))) - pattern_name_offset;
static_row_info.sub_row[0] = AddressT((y & 7) << 2); static_row_info.sub_row[0] = AddressT((y & 7) << 2);
static_row_info.sub_row[1] = 28 ^ AddressT((y & 7) << 2); static_row_info.sub_row[1] = 28 ^ AddressT((y & 7) << 2);
} else static_row_info = scrolled_row_info; } else static_row_info = scrolled_row_info;
@ -246,15 +235,15 @@ struct SMSFetcher {
void fetch_sprite(int sprite) { void fetch_sprite(int sprite) {
tile_buffer.active_sprites[sprite].x = tile_buffer.active_sprites[sprite].x =
base->ram_[ base->ram_[
storage->sprite_attribute_table_address_ & bits7((tile_buffer.active_sprites[sprite].index << 1) | 0) storage->sprite_attribute_table_address_ & bits<7>((tile_buffer.active_sprites[sprite].index << 1) | 0)
] - (storage->shift_sprites_8px_left_ ? 8 : 0); ] - (storage->shift_sprites_8px_left_ ? 8 : 0);
const uint8_t name = base->ram_[ const uint8_t name = base->ram_[
storage->sprite_attribute_table_address_ & bits7((tile_buffer.active_sprites[sprite].index << 1) | 1) storage->sprite_attribute_table_address_ & bits<7>((tile_buffer.active_sprites[sprite].index << 1) | 1)
] & (base->sprites_16x16_ ? ~1 : ~0); ] & (base->sprites_16x16_ ? ~1 : ~0);
const AddressT graphic_location = const AddressT graphic_location =
storage->sprite_generator_table_address_ & storage->sprite_generator_table_address_ &
bits13(AddressT((name << 5) | (tile_buffer.active_sprites[sprite].row << 2))); bits<13>(AddressT((name << 5) | (tile_buffer.active_sprites[sprite].row << 2)));
tile_buffer.active_sprites[sprite].image[0] = base->ram_[graphic_location]; tile_buffer.active_sprites[sprite].image[0] = base->ram_[graphic_location];
tile_buffer.active_sprites[sprite].image[1] = base->ram_[graphic_location+1]; tile_buffer.active_sprites[sprite].image[1] = base->ram_[graphic_location+1];
tile_buffer.active_sprites[sprite].image[2] = base->ram_[graphic_location+2]; tile_buffer.active_sprites[sprite].image[2] = base->ram_[graphic_location+2];
@ -280,7 +269,7 @@ struct SMSFetcher {
} }
void posit_sprite(int sprite) { void posit_sprite(int sprite) {
base->posit_sprite(sprite_selection_buffer, sprite, base->ram_[storage->sprite_attribute_table_address_ & bits8(AddressT(sprite))], y); base->posit_sprite(sprite_selection_buffer, sprite, base->ram_[storage->sprite_attribute_table_address_ & bits<8>(AddressT(sprite))], y);
} }
Base<personality> *const base; Base<personality> *const base;
@ -521,7 +510,7 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
case ScreenMode::YamahaText80: { case ScreenMode::YamahaText80: {
const auto column = AddressT(Storage<personality>::data_block_); const auto column = AddressT(Storage<personality>::data_block_);
const auto start = pattern_name_address_ & bits12(AddressT((y >> 3) * 80)); const auto start = pattern_name_address_ & bits<12>(AddressT((y >> 3) * 80));
name_[0] = ram_[start + column + 0]; name_[0] = ram_[start + column + 0];
name_[1] = ram_[start + column + 1]; name_[1] = ram_[start + column + 1];
@ -543,7 +532,7 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
switch(mode) { switch(mode) {
case ScreenMode::YamahaText80: { case ScreenMode::YamahaText80: {
const auto column = AddressT(Storage<personality>::data_block_ >> 3); const auto column = AddressT(Storage<personality>::data_block_ >> 3);
const auto address = colour_table_address_ & bits9(AddressT((y >> 3) * 10)); const auto address = colour_table_address_ & bits<9>(AddressT((y >> 3) * 10));
line_buffer.characters.flags[column] = ram_[address + column]; line_buffer.characters.flags[column] = ram_[address + column];
} break; } break;
@ -571,7 +560,7 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
const auto column = AddressT(Storage<personality>::data_block_); const auto column = AddressT(Storage<personality>::data_block_);
Storage<personality>::data_block_ += 4; Storage<personality>::data_block_ += 4;
const auto start = pattern_generator_table_address_ & bits11(AddressT(y & 7)); const auto start = pattern_generator_table_address_ & bits<11>(AddressT(y & 7));
line_buffer.characters.shapes[column + 0] = ram_[start + AddressT(name_[0] << 3)]; line_buffer.characters.shapes[column + 0] = ram_[start + AddressT(name_[0] << 3)];
line_buffer.characters.shapes[column + 1] = ram_[start + AddressT(name_[1] << 3)]; line_buffer.characters.shapes[column + 1] = ram_[start + AddressT(name_[1] << 3)];
line_buffer.characters.shapes[column + 2] = ram_[start + AddressT(name_[2] << 3)]; line_buffer.characters.shapes[column + 2] = ram_[start + AddressT(name_[2] << 3)];
@ -632,7 +621,7 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
const int column = Storage<personality>::data_block_; const int column = Storage<personality>::data_block_;
Storage<personality>::data_block_ += 4; Storage<personality>::data_block_ += 4;
const auto start = bits15((y << 7) | column); const auto start = bits<15>((y << 7) | column);
line_buffer.bitmap[column + 0] = ram_[pattern_name_address_ & AddressT(start + 0)]; 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 + 1] = ram_[pattern_name_address_ & AddressT(start + 1)];
@ -645,7 +634,7 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
const int column = Storage<personality>::data_block_ << 1; const int column = Storage<personality>::data_block_ << 1;
Storage<personality>::data_block_ += 4; Storage<personality>::data_block_ += 4;
const auto start = bits15((y << 7) | column); const auto start = bits<15>((y << 7) | column);
// Fetch from alternate banks. // Fetch from alternate banks.
line_buffer.bitmap[column + 0] = ram_[rotated_name_ & AddressT(start + 0)]; line_buffer.bitmap[column + 0] = ram_[rotated_name_ & AddressT(start + 0)];