1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-05 21:32:55 +00:00

Edge further towards actual fetching.

This commit is contained in:
Thomas Harte 2023-01-23 23:19:04 -05:00
parent 6b85ee9607
commit 445b34933a
2 changed files with 59 additions and 28 deletions

View File

@ -179,6 +179,8 @@ template <Personality personality> struct Storage<personality, std::enable_if_t<
enum class Type { enum class Type {
External, External,
DataBlock, DataBlock,
SpriteY,
SpriteContents,
} type = Type::External; } type = Type::External;
constexpr Event(int offset, Type type) noexcept : constexpr Event(int offset, Type type) noexcept :
@ -190,11 +192,20 @@ template <Personality personality> struct Storage<personality, std::enable_if_t<
constexpr Event() noexcept {} constexpr Event() noexcept {}
}; };
// State that tracks fetching position within a line.
const Event *next_event_ = nullptr; const Event *next_event_ = nullptr;
int data_block_ = 0;
int sprite_block_ = 0;
/// Resets line-ephemeral state for a new line.
void begin_line([[maybe_unused]] ScreenMode mode, bool is_refresh, [[maybe_unused]] bool sprites_enabled) { void begin_line([[maybe_unused]] ScreenMode mode, bool is_refresh, [[maybe_unused]] bool sprites_enabled) {
// TODO: reinstate upon completion of the Yamaha pipeline. // TODO: reinstate upon completion of the Yamaha pipeline.
// assert(mode < ScreenMode::YamahaText80 || next_event_ == nullptr || next_event_->offset == 1368); // assert(mode < ScreenMode::YamahaText80 || next_event_ == nullptr || next_event_->offset == 1368);
data_block_ = 0;
sprite_block_ = 0;
if(is_refresh) { if(is_refresh) {
next_event_ = refresh_events; next_event_ = refresh_events;
return; return;
@ -636,6 +647,7 @@ template <Personality personality> struct Base: public Storage<personality> {
template<bool use_end> void fetch_tms_character(int start, int end); template<bool use_end> void fetch_tms_character(int start, int end);
template<bool use_end> void fetch_yamaha(int start, int end); template<bool use_end> void fetch_yamaha(int start, int end);
template<ScreenMode> void fetch_yamaha(int end);
template<bool use_end> void fetch_sms(int start, int end); template<bool use_end> void fetch_sms(int start, int end);

View File

@ -470,38 +470,57 @@ template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
// MARK: - Yamaha // MARK: - Yamaha
template <Personality personality>
template<ScreenMode mode> void Base<personality>::fetch_yamaha(int end) {
while(Storage<personality>::next_event_->offset < end) {
switch(Storage<personality>::next_event_->type) {
case Storage<personality>::Event::Type::External:
do_external_slot(Storage<personality>::next_event_->offset);
break;
case Storage<personality>::Event::Type::DataBlock: {
// Exactly how to fetch depends upon mode...
switch(mode) {
case ScreenMode::YamahaGraphics5: {
// TODO: work out start address as a function of fetch_pointer_.row, use current
// data block via data_block_, fetch data into line_buffers_[fetch_pointer_.row].bitmap.
} break;
default:
break;
}
++Storage<personality>::data_block_;
} break;
default: break;
}
++Storage<personality>::next_event_;
}
}
template <Personality personality> template <Personality personality>
template<bool use_end> void Base<personality>::fetch_yamaha([[maybe_unused]] int start, int end) { template<bool use_end> void Base<personality>::fetch_yamaha([[maybe_unused]] int start, int end) {
if constexpr (is_yamaha_vdp(personality)) { if constexpr (is_yamaha_vdp(personality)) {
/* // Dispatch according to [supported] screen mode.
Per http://map.grauw.nl/articles/vdp-vram-timing/vdp-timing.html : #define Dispatch(mode) case mode: fetch_yamaha<mode>(end); break;
switch(screen_mode_) {
The major change compared to the previous mode is that now the VDP needs to fetch extra data default: break;
for the bitmap rendering. These fetches happen in 32 blocks of 4 bytes (screen 5/6) or Dispatch(ScreenMode::Blank);
8 bytes (screen 7/8). The fetches within one block happen in burst mode. This means that Dispatch(ScreenMode::Text);
one block takes 18 cycles (screen 5/6) or 20 cycles (screen 7/8). Though later we'll see Dispatch(ScreenMode::MultiColour);
that the two spare cycles for screen 5/6 are not used for anything else, so for simplicity Dispatch(ScreenMode::ColouredText);
we can say that in all bitmap modes a bitmap-fetch-block takes 20 cycles. This is even Dispatch(ScreenMode::Graphics);
clearer if you look at the RAS signal: this signal follows the exact same pattern in all Dispatch(ScreenMode::YamahaText80);
(bitmap) screen modes, so in screen 5/6 it remains active for two cycles longer than Dispatch(ScreenMode::YamahaGraphics3);
strictly necessary. Dispatch(ScreenMode::YamahaGraphics4);
Dispatch(ScreenMode::YamahaGraphics5);
Actually before these 32 blocks there's one extra dummy block. This block has the same timing Dispatch(ScreenMode::YamahaGraphics6);
as the other blocks, but it always reads address 0x1FFFF. From an emulator point of view, Dispatch(ScreenMode::YamahaGraphics7);
these dummy reads don't matter, it only matters that at those moments no other VRAM accesses
can occur.
*/
while(Storage<personality>::next_event_->offset < end) {
switch(Storage<personality>::next_event_->type) {
case Storage<personality>::Event::Type::External:
do_external_slot(Storage<personality>::next_event_->offset);
break;
default: break;
}
++Storage<personality>::next_event_;
} }
#undef Dispatch
} }
} }