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:
parent
6b85ee9607
commit
445b34933a
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user