1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-27 02:55:07 +00:00

Attempt text mode data collection.

This commit is contained in:
Thomas Harte 2023-02-13 22:20:47 -05:00
parent 169d7a7418
commit c1457cc5e0
2 changed files with 55 additions and 30 deletions

View File

@ -192,7 +192,8 @@ template <Personality personality> struct Base: public Storage<personality> {
ScreenMode screen_mode_, underlying_mode_;
LineBuffer line_buffers_[313];
size_t tile_offset_ = 0;
AddressT tile_offset_ = 0;
uint8_t name_[4]{};
void posit_sprite(LineBuffer &buffer, int sprite_number, int sprite_y, int screen_row);
// There is a delay between reading into the line buffer and outputting from there to the screen. That delay

View File

@ -135,16 +135,14 @@ struct TextFetcher {
if constexpr (cycle < 47 || cycle >= 167) {
base->do_external_slot(to_internal<personality, Clock::TMSMemoryWindow>(cycle));
return;
}
// For the 120 slots in between follow a three-step pattern of:
if constexpr (cycle >= 47) {
} else {
// For the 120 slots in between follow a three-step pattern of:
constexpr int offset = cycle - 47;
constexpr auto column = AddressT(offset / 3);
switch(offset % 3) {
case 0: base->tile_offset_ = base->ram_[row_base + column]; break; // (1) fetch tile name.
case 1: base->do_external_slot(to_internal<personality, Clock::TMSMemoryWindow>(cycle)); break; // (2) external slot.
case 2: line_buffer.patterns[column][0] = base->ram_[row_offset + size_t(base->tile_offset_ << 3)]; break; // (3) fetch tile pattern.
case 0: base->name_[0] = base->ram_[row_base + column]; break; // (1) fetch tile name.
case 1: base->do_external_slot(to_internal<personality, Clock::TMSMemoryWindow>(cycle)); break; // (2) external slot.
case 2: line_buffer.patterns[column][0] = base->ram_[row_offset + size_t(base->name_[0] << 3)]; break; // (3) fetch tile pattern.
}
}
}
@ -348,7 +346,7 @@ template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer
const size_t scrolled_column = (column - horizontal_offset) & 0x1f;\
const size_t address = row_info.pattern_address_base + (scrolled_column << 1); \
line_buffer.flags[column] = ram_[address+1]; \
tile_offset_ = size_t( \
tile_offset_ = uint16_t( \
(((line_buffer.flags[column]&1) << 8) | ram_[address]) << 5 \
) + row_info.sub_row[(line_buffer.flags[column]&4) >> 2]; \
}
@ -396,18 +394,21 @@ template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer
// The programmer can opt out of applying vertical scrolling to the right-hand portion of the display.
const int scrolled_row = (y + Storage<personality>::latched_vertical_scroll_) % (is_tall_mode ? 256 : 224);
struct RowInfo {
size_t pattern_address_base;
size_t sub_row[2];
AddressT pattern_address_base;
AddressT sub_row[2];
};
const RowInfo scrolled_row_info = {
(pattern_name_address & size_t(((scrolled_row & ~7) << 3) | 0x3800)) - pattern_name_offset,
{size_t((scrolled_row & 7) << 2), 28 ^ size_t((scrolled_row & 7) << 2)}
AddressT((pattern_name_address & size_t(((scrolled_row & ~7) << 3) | 0x3800)) - pattern_name_offset),
{
AddressT((scrolled_row & 7) << 2),
AddressT(28 ^ ((scrolled_row & 7) << 2))
}
};
RowInfo row_info;
if(Storage<personality>::vertical_scroll_lock_) {
row_info.pattern_address_base = (pattern_name_address & size_t(((y & ~7) << 3) | 0x3800)) - pattern_name_offset;
row_info.sub_row[0] = size_t((y & 7) << 2);
row_info.sub_row[1] = 28 ^ size_t((y & 7) << 2);
row_info.pattern_address_base = AddressT((pattern_name_address & AddressT(((y & ~7) << 3) | 0x3800)) - pattern_name_offset);
row_info.sub_row[0] = AddressT((y & 7) << 2);
row_info.sub_row[1] = 28 ^ AddressT((y & 7) << 2);
} else row_info = scrolled_row_info;
// ... and do the actual fetching, which follows this routine:
@ -463,7 +464,7 @@ template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer
// MARK: - Yamaha
template <Personality personality>
template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]] LineBuffer &line_buffer, [[maybe_unused]] int y, int end) {
template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_buffer, int y, int end) {
const AddressT rotated_name_ = pattern_name_address_ >> 1;
const uint8_t *const ram2 = &ram_[65536];
@ -476,13 +477,24 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]]
case Type::Name:
switch(mode) {
case ScreenMode::Text:
// TODO: read two new character names.
break;
case ScreenMode::Text: {
const auto column = AddressT(Storage<personality>::data_block_);
const AddressT start = pattern_name_address_ & (0x1fc00 | size_t(y >> 3) * 40);
case ScreenMode::YamahaText80:
// TODO: read four new character names.
break;
name_[0] = ram_[start + column + 0];
name_[1] = ram_[start + column + 1];
} break;
case ScreenMode::YamahaText80: {
const auto column = AddressT(Storage<personality>::data_block_);
const AddressT start = pattern_name_address_ & (0x1f800 | size_t(y >> 3) * 80);
name_[0] = ram_[start + column + 0];
name_[1] = ram_[start + column + 1];
name_[2] = ram_[start + column + 2];
name_[3] = ram_[start + column + 3];
// TODO: should 80-column mode use alternate page access?
} break;
default: break;
}
@ -491,7 +503,7 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]]
case Type::Colour:
switch(mode) {
case ScreenMode::YamahaText80:
// TODO: read a single 'colour' (i.e. a bitfield, governing colour selection for eight characters).
// TODO: read a single 'colour' (i.e. a bitfield, governing colour [/flashing?] selection for eight characters).
break;
default: break;
@ -500,13 +512,25 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha([[maybe_unused]]
case Type::Pattern:
switch(mode) {
case ScreenMode::Text:
// TODO: look up two sets of character contents, based on names from earlier.
break;
case ScreenMode::Text: {
const auto column = AddressT(Storage<personality>::data_block_);
Storage<personality>::data_block_ += 2;
case ScreenMode::YamahaText80:
// TODO: look up four sets of character contents, based on names from earlier.
break;
const AddressT start = pattern_generator_table_address_ & (0x1f800 | (y & 7));
line_buffer.patterns[column + 0][0] = ram_[start + AddressT(name_[0] << 3)];
line_buffer.patterns[column + 1][0] = ram_[start + AddressT(name_[1] << 3)];
} break;
case ScreenMode::YamahaText80: {
const auto column = AddressT(Storage<personality>::data_block_);
Storage<personality>::data_block_ += 4;
const AddressT start = pattern_generator_table_address_ & (0x1f800 | (y & 7));
line_buffer.patterns[column + 0][0] = ram_[start + AddressT(name_[0] << 3)];
line_buffer.patterns[column + 1][0] = ram_[start + AddressT(name_[1] << 3)];
line_buffer.patterns[column + 0][1] = ram_[start + AddressT(name_[2] << 3)];
line_buffer.patterns[column + 1][1] = ram_[start + AddressT(name_[3] << 3)];
} break;
default: break;
}