mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-22 15:28:56 +00:00
Takes a shot at the vertical stuff of sprite DMA.
This commit is contained in:
parent
b489ba3d0d
commit
040ac93042
@ -269,7 +269,7 @@ template <int cycle, bool stop_if_cpu> bool Chipset::perform_cycle() {
|
|||||||
if constexpr(cycle >= 0x15 && cycle < 0x35) {
|
if constexpr(cycle >= 0x15 && cycle < 0x35) {
|
||||||
if((dma_control_ & SpritesFlag) == SpritesFlag) {
|
if((dma_control_ & SpritesFlag) == SpritesFlag) {
|
||||||
constexpr auto sprite_id = (cycle - 0x15) >> 2;
|
constexpr auto sprite_id = (cycle - 0x15) >> 2;
|
||||||
if(sprites_[sprite_id].advance(sprite_id)) {
|
if(sprites_[sprite_id].advance(y_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,6 +404,11 @@ template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
|
|||||||
|
|
||||||
// TODO: the manual is vague on when this happens. Try to find out.
|
// TODO: the manual is vague on when this happens. Try to find out.
|
||||||
copper_.reload<0>();
|
copper_.reload<0>();
|
||||||
|
|
||||||
|
// TODO: is this really how sprite DMA proceeds?
|
||||||
|
for(int c = 0; c < 8; c++) {
|
||||||
|
sprites_[c].reset_dma();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(line_cycle_ < line_length_ * 4);
|
assert(line_cycle_ < line_length_ * 4);
|
||||||
@ -936,10 +941,58 @@ void Chipset::Sprite::set_image_data(int slot, uint16_t value) {
|
|||||||
active_ |= slot == 0;
|
active_ |= slot == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chipset::Sprite::advance([[maybe_unused]] int sprite_id) {
|
bool Chipset::Sprite::advance(int y) {
|
||||||
|
switch(dma_state_) {
|
||||||
|
// i.e. stopped.
|
||||||
|
default: return false;
|
||||||
|
|
||||||
|
// FetchStart: fetch the first control word and proceed to the second.
|
||||||
|
case DMAState::FetchStart:
|
||||||
|
set_start_position(ram_[pointer_[0]]);
|
||||||
|
++pointer_[0];
|
||||||
|
dma_state_ = DMAState::FetchStopAndControl;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// FetchStopAndControl: fetch second control word and wait for V start.
|
||||||
|
case DMAState::FetchStopAndControl:
|
||||||
|
set_stop_and_control(ram_[pointer_[0]]);
|
||||||
|
++pointer_[0];
|
||||||
|
dma_state_ = DMAState::WaitingForStart;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// WaitingForStart: repeat until V start is found.
|
||||||
|
case DMAState::WaitingForStart:
|
||||||
|
if(y != v_start_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
|
||||||
|
// FetchData1: if v end is reached, stop DMA. Otherwise fetch a word
|
||||||
|
// and proceed to FetchData0.
|
||||||
|
case DMAState::FetchData1:
|
||||||
|
if(y == v_stop_) {
|
||||||
|
dma_state_ = DMAState::Stopped;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
set_image_data(1, ram_[pointer_[0]]);
|
||||||
|
++pointer_[0];
|
||||||
|
dma_state_ = DMAState::FetchData0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// FetchData0: fetch a word and proceed back to FetchData1.
|
||||||
|
case DMAState::FetchData0:
|
||||||
|
set_image_data(0, ram_[pointer_[0]]);
|
||||||
|
++pointer_[0];
|
||||||
|
dma_state_ = DMAState::FetchData1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Chipset::Sprite::reset_dma() {
|
||||||
|
dma_state_ = DMAState::FetchStart;
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Disk.
|
// MARK: - Disk.
|
||||||
|
|
||||||
void Chipset::DiskDMA::enqueue(uint16_t value, bool matches_sync) {
|
void Chipset::DiskDMA::enqueue(uint16_t value, bool matches_sync) {
|
||||||
|
@ -132,12 +132,23 @@ class Chipset: private ClockingHint::Observer {
|
|||||||
void set_stop_and_control(uint16_t value);
|
void set_stop_and_control(uint16_t value);
|
||||||
void set_image_data(int slot, uint16_t value);
|
void set_image_data(int slot, uint16_t value);
|
||||||
|
|
||||||
bool advance(int sprite_id);
|
bool advance(int y);
|
||||||
|
void reset_dma();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t v_start_ = 0, h_start_ = 0, v_stop_ = 0;
|
uint16_t v_start_ = 0, h_start_ = 0, v_stop_ = 0;
|
||||||
uint16_t data_[2]{};
|
uint16_t data_[2]{};
|
||||||
bool active_ = false, attached_ = false;
|
bool attached_ = false;
|
||||||
|
bool active_ = false;
|
||||||
|
|
||||||
|
enum class DMAState {
|
||||||
|
FetchStart,
|
||||||
|
FetchStopAndControl,
|
||||||
|
WaitingForStart,
|
||||||
|
FetchData1,
|
||||||
|
FetchData0,
|
||||||
|
Stopped
|
||||||
|
} dma_state_ = DMAState::FetchStart;
|
||||||
} sprites_[8];
|
} sprites_[8];
|
||||||
|
|
||||||
// MARK: - Raster position and state.
|
// MARK: - Raster position and state.
|
||||||
|
Loading…
Reference in New Issue
Block a user