mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 00:30:31 +00:00
Added a single-slot queue for player objects to defer drawing, thereby deferring pixel lookup. Which I think is correct. Though more slots might be needed.
This commit is contained in:
parent
77ed4ddc05
commit
8c9062857c
@ -659,6 +659,8 @@ template<class T> void TIA::draw_object(T &object, const uint8_t collision_ident
|
|||||||
{
|
{
|
||||||
int first_pixel = first_pixel_cycle - 4 + (horizontal_blank_extend_ ? 8 : 0);
|
int first_pixel = first_pixel_cycle - 4 + (horizontal_blank_extend_ ? 8 : 0);
|
||||||
|
|
||||||
|
object.dequeue_pixels(collision_buffer_, collision_identity, end - first_pixel_cycle);
|
||||||
|
|
||||||
// movement works across the entire screen, so do work that falls outside of the pixel area
|
// movement works across the entire screen, so do work that falls outside of the pixel area
|
||||||
if(start < first_pixel)
|
if(start < first_pixel)
|
||||||
{
|
{
|
||||||
@ -673,7 +675,7 @@ template<class T> void TIA::draw_object(T &object, const uint8_t collision_ident
|
|||||||
// perform the visible part of the line, if any
|
// perform the visible part of the line, if any
|
||||||
if(start < 224)
|
if(start < 224)
|
||||||
{
|
{
|
||||||
draw_object_visible<T>(object, collision_identity, start - first_pixel_cycle + 4, std::min(end - first_pixel_cycle + 4, 160));
|
draw_object_visible<T>(object, collision_identity, start - first_pixel_cycle + 4, std::min(end - first_pixel_cycle + 4, 160), end - first_pixel_cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// move further if required
|
// move further if required
|
||||||
@ -683,7 +685,7 @@ template<class T> void TIA::draw_object(T &object, const uint8_t collision_ident
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> void TIA::draw_object_visible(T &object, const uint8_t collision_identity, int start, int end)
|
template<class T> void TIA::draw_object_visible(T &object, const uint8_t collision_identity, int start, int end, int time_now)
|
||||||
{
|
{
|
||||||
// perform a miniature event loop on (i) triggering draws; (ii) drawing; and (iii) motion
|
// perform a miniature event loop on (i) triggering draws; (ii) drawing; and (iii) motion
|
||||||
int next_motion_time = object.motion_time - first_pixel_cycle + 4;
|
int next_motion_time = object.motion_time - first_pixel_cycle + 4;
|
||||||
@ -723,7 +725,22 @@ template<class T> void TIA::draw_object_visible(T &object, const uint8_t collisi
|
|||||||
// an appropriate solution would probably be to capture the drawing request into a queue and honour them outside
|
// an appropriate solution would probably be to capture the drawing request into a queue and honour them outside
|
||||||
// this loop, clipped to the real output parameters. Assuming all state consumed by draw_pixels is captured,
|
// this loop, clipped to the real output parameters. Assuming all state consumed by draw_pixels is captured,
|
||||||
// and mutated now then also queueing resets and skips shouldn't be necessary.
|
// and mutated now then also queueing resets and skips shouldn't be necessary.
|
||||||
object.enqueue_pixels(&collision_buffer_[start], length, collision_identity);
|
if(next_event_time > time_now)
|
||||||
|
{
|
||||||
|
if(start < time_now)
|
||||||
|
{
|
||||||
|
object.output_pixels(&collision_buffer_[start], time_now - start, collision_identity);
|
||||||
|
object.enqueue_pixels(time_now, next_event_time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object.enqueue_pixels(start, next_event_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object.output_pixels(&collision_buffer_[start], length, collision_identity);
|
||||||
|
}
|
||||||
|
|
||||||
// the next interesting event is after next_event_time cycles, so progress
|
// the next interesting event is after next_event_time cycles, so progress
|
||||||
object.position = (object.position + length) % 160;
|
object.position = (object.position + length) % 160;
|
||||||
|
@ -133,7 +133,7 @@ class TIA {
|
|||||||
// output twice.
|
// output twice.
|
||||||
|
|
||||||
// objects
|
// objects
|
||||||
struct Object {
|
template<class T> struct Object {
|
||||||
// the two programmer-set values
|
// the two programmer-set values
|
||||||
int position;
|
int position;
|
||||||
int motion;
|
int motion;
|
||||||
@ -146,10 +146,31 @@ class TIA {
|
|||||||
bool is_moving;
|
bool is_moving;
|
||||||
|
|
||||||
Object() : is_moving(false) {};
|
Object() : is_moving(false) {};
|
||||||
|
|
||||||
|
void dequeue_pixels(uint8_t *const target, const uint8_t collision_identity, const int time_now)
|
||||||
|
{
|
||||||
|
// if(enqueued_start_ != enqueued_end_)
|
||||||
|
// {
|
||||||
|
// static_cast<T *>(this)->output_pixels(&target[enqueued_start_], enqueued_end_ - enqueued_start_, collision_identity);
|
||||||
|
// enqueued_end_ = enqueued_start_ = 0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void enqueue_pixels(const int start, const int end)
|
||||||
|
{
|
||||||
|
// enqueued_start_ = start;
|
||||||
|
// enqueued_end_ = end;
|
||||||
|
static_cast<T *>(this)->skip_pixels(end - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// int enqueued_start_, enqueued_end_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// player state
|
// player state
|
||||||
struct Player: public Object {
|
struct Player: public Object<Player> {
|
||||||
|
Player() : copy_flags(0), graphic{0, 0}, reverse_mask(false), pixel_position(32), graphic_index(0), adder(4) {}
|
||||||
|
|
||||||
int adder;
|
int adder;
|
||||||
int copy_flags; // a bit field, corresponding to the first few values of NUSIZ
|
int copy_flags; // a bit field, corresponding to the first few values of NUSIZ
|
||||||
uint8_t graphic[2]; // the player graphic; 1 = new, 0 = current
|
uint8_t graphic[2]; // the player graphic; 1 = new, 0 = current
|
||||||
@ -168,11 +189,43 @@ class TIA {
|
|||||||
pixel_position = 0;
|
pixel_position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void enqueue_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
||||||
{
|
{
|
||||||
if(pixel_position == 32) return;
|
output_pixels(target, count, collision_identity, pixel_position, adder, reverse_mask);
|
||||||
if(graphic[graphic_index])
|
skip_pixels(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dequeue_pixels(uint8_t *const target, const uint8_t collision_identity, const int time_now)
|
||||||
|
{
|
||||||
|
if(queue_.start != queue_.end)
|
||||||
{
|
{
|
||||||
|
output_pixels(&target[queue_.start], queue_.end - queue_.start, collision_identity, queue_.pixel_position, queue_.adder, queue_.reverse_mask);
|
||||||
|
queue_.start = queue_.end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enqueue_pixels(const int start, const int end)
|
||||||
|
{
|
||||||
|
queue_.start = start;
|
||||||
|
queue_.end = end;
|
||||||
|
queue_.pixel_position = pixel_position;
|
||||||
|
queue_.adder = adder;
|
||||||
|
queue_.reverse_mask = reverse_mask;
|
||||||
|
skip_pixels(end - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct QueuedPixels
|
||||||
|
{
|
||||||
|
int start, end;
|
||||||
|
int pixel_position;
|
||||||
|
int adder;
|
||||||
|
int reverse_mask;
|
||||||
|
} queue_;
|
||||||
|
|
||||||
|
inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity, int pixel_position, int adder, int reverse_mask)
|
||||||
|
{
|
||||||
|
if(pixel_position == 32 || !graphic[graphic_index]) return;
|
||||||
int output_cursor = 0;
|
int output_cursor = 0;
|
||||||
while(pixel_position < 32 && output_cursor < count)
|
while(pixel_position < 32 && output_cursor < count)
|
||||||
{
|
{
|
||||||
@ -182,17 +235,11 @@ class TIA {
|
|||||||
pixel_position += adder;
|
pixel_position += adder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
skip_pixels(count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Player() : copy_flags(0), graphic{0, 0}, reverse_mask(false), pixel_position(32), graphic_index(0), adder(4) {}
|
|
||||||
} player_[2];
|
} player_[2];
|
||||||
|
|
||||||
// common actor for things that appear as a horizontal run of pixels
|
// common actor for things that appear as a horizontal run of pixels
|
||||||
struct HorizontalRun: public Object {
|
struct HorizontalRun: public Object<HorizontalRun> {
|
||||||
int pixel_position;
|
int pixel_position;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
@ -206,7 +253,7 @@ class TIA {
|
|||||||
pixel_position = size;
|
pixel_position = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void enqueue_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
||||||
{
|
{
|
||||||
int output_cursor = 0;
|
int output_cursor = 0;
|
||||||
while(pixel_position && output_cursor < count)
|
while(pixel_position && output_cursor < count)
|
||||||
@ -227,12 +274,12 @@ class TIA {
|
|||||||
bool locked_to_player;
|
bool locked_to_player;
|
||||||
int copy_flags;
|
int copy_flags;
|
||||||
|
|
||||||
inline void enqueue_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
||||||
{
|
{
|
||||||
if(!pixel_position) return;
|
if(!pixel_position) return;
|
||||||
if(enabled && !locked_to_player)
|
if(enabled && !locked_to_player)
|
||||||
{
|
{
|
||||||
HorizontalRun::enqueue_pixels(target, count, collision_identity);
|
HorizontalRun::output_pixels(target, count, collision_identity);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -249,12 +296,12 @@ class TIA {
|
|||||||
int enabled_index;
|
int enabled_index;
|
||||||
const int copy_flags = 0;
|
const int copy_flags = 0;
|
||||||
|
|
||||||
inline void enqueue_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
inline void output_pixels(uint8_t *const target, const int count, const uint8_t collision_identity)
|
||||||
{
|
{
|
||||||
if(!pixel_position) return;
|
if(!pixel_position) return;
|
||||||
if(enabled[enabled_index])
|
if(enabled[enabled_index])
|
||||||
{
|
{
|
||||||
HorizontalRun::enqueue_pixels(target, count, collision_identity);
|
HorizontalRun::output_pixels(target, count, collision_identity);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -272,7 +319,7 @@ class TIA {
|
|||||||
|
|
||||||
// drawing methods and state
|
// drawing methods and state
|
||||||
template<class T> void draw_object(T &, const uint8_t collision_identity, int start, int end);
|
template<class T> void draw_object(T &, const uint8_t collision_identity, int start, int end);
|
||||||
template<class T> void draw_object_visible(T &, const uint8_t collision_identity, int start, int end);
|
template<class T> void draw_object_visible(T &, const uint8_t collision_identity, int start, int end, int time_now);
|
||||||
inline void draw_playfield(int start, int end);
|
inline void draw_playfield(int start, int end);
|
||||||
|
|
||||||
inline void output_for_cycles(int number_of_cycles);
|
inline void output_for_cycles(int number_of_cycles);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user