mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempt to copy and paste my way to working type-1 sprites.
This commit is contained in:
parent
023da1970a
commit
c140f370fe
@ -212,19 +212,23 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
|
|||||||
// ------------------------
|
// ------------------------
|
||||||
// Perform memory accesses.
|
// Perform memory accesses.
|
||||||
// ------------------------
|
// ------------------------
|
||||||
#define fetch(function, clock, offset) { \
|
#define fetch(function, clock, offset) { \
|
||||||
const int first_window = from_internal<personality, clock>(this->fetch_pointer_.column); \
|
const int first_window = from_internal<personality, clock>(this->fetch_pointer_.column); \
|
||||||
const int final_window = from_internal<personality, clock>(end_column); \
|
const int final_window = from_internal<personality, clock>(end_column); \
|
||||||
if(first_window == final_window) break; \
|
if(first_window == final_window) break; \
|
||||||
if(final_window != clock_rate<personality, clock>()) { \
|
if(final_window != clock_rate<personality, clock>()) { \
|
||||||
function<true>( \
|
function<true>( \
|
||||||
this->line_buffers_[this->fetch_pointer_.row], this->fetch_pointer_.row + offset, \
|
this->line_buffers_[this->fetch_pointer_.row], \
|
||||||
first_window, final_window); \
|
this->line_buffers_[(this->fetch_pointer_.row + 1) % this->mode_timing_.total_lines], \
|
||||||
} else { \
|
this->fetch_pointer_.row + offset, \
|
||||||
function<false>( \
|
first_window, final_window); \
|
||||||
this->line_buffers_[this->fetch_pointer_.row], this->fetch_pointer_.row + offset, \
|
} else { \
|
||||||
first_window, final_window); \
|
function<false>( \
|
||||||
} \
|
this->line_buffers_[this->fetch_pointer_.row], \
|
||||||
|
this->line_buffers_[(this->fetch_pointer_.row + 1) % this->mode_timing_.total_lines], \
|
||||||
|
this->fetch_pointer_.row + offset, \
|
||||||
|
first_window, final_window); \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(line_buffer.fetch_mode) {
|
switch(line_buffer.fetch_mode) {
|
||||||
|
@ -508,14 +508,14 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
template<bool use_end, typename Fetcher> void dispatch(Fetcher &fetcher, int start, int end);
|
template<bool use_end, typename Fetcher> void dispatch(Fetcher &fetcher, int start, int end);
|
||||||
|
|
||||||
// Various fetchers.
|
// Various fetchers.
|
||||||
template<bool use_end> void fetch_tms_refresh(LineBuffer &, int y, int start, int end);
|
template<bool use_end> void fetch_tms_refresh(LineBuffer &, LineBuffer &, int y, int start, int end);
|
||||||
template<bool use_end> void fetch_tms_text(LineBuffer &, int y, int start, int end);
|
template<bool use_end> void fetch_tms_text(LineBuffer &, LineBuffer &, int y, int start, int end);
|
||||||
template<bool use_end> void fetch_tms_character(LineBuffer &, int y, int start, int end);
|
template<bool use_end> void fetch_tms_character(LineBuffer &, LineBuffer &, int y, int start, int end);
|
||||||
|
|
||||||
template<bool use_end> void fetch_yamaha(LineBuffer &, int y, int start, int end);
|
template<bool use_end> void fetch_yamaha(LineBuffer &, LineBuffer &, int y, int start, int end);
|
||||||
template<ScreenMode> void fetch_yamaha(LineBuffer &, int y, int end);
|
template<ScreenMode> void fetch_yamaha(LineBuffer &, LineBuffer &, int y, int end);
|
||||||
|
|
||||||
template<bool use_end> void fetch_sms(LineBuffer &, int y, int start, int end);
|
template<bool use_end> void fetch_sms(LineBuffer &, LineBuffer &, int y, int start, int end);
|
||||||
|
|
||||||
// A helper function to output the current border colour for
|
// A helper function to output the current border colour for
|
||||||
// the number of cycles supplied.
|
// the number of cycles supplied.
|
||||||
|
@ -140,10 +140,10 @@ struct CharacterFetcher {
|
|||||||
|
|
||||||
if(buffer.screen_mode == ScreenMode::Graphics) {
|
if(buffer.screen_mode == ScreenMode::Graphics) {
|
||||||
// If this is high resolution mode, allow the row number to affect the pattern and colour addresses.
|
// If this is high resolution mode, allow the row number to affect the pattern and colour addresses.
|
||||||
pattern_base &= size_t(0x2000 | ((y & 0xc0) << 5));
|
pattern_base &= AddressT(0x2000 | ((y & 0xc0) << 5));
|
||||||
colour_base &= size_t(0x2000 | ((y & 0xc0) << 5));
|
colour_base &= AddressT(0x2000 | ((y & 0xc0) << 5));
|
||||||
|
|
||||||
colour_base += size_t(y & 7);
|
colour_base += AddressT(y & 7);
|
||||||
colour_name_shift = 0;
|
colour_name_shift = 0;
|
||||||
} else {
|
} else {
|
||||||
colour_base &= size_t(0xffc0);
|
colour_base &= size_t(0xffc0);
|
||||||
@ -257,20 +257,20 @@ struct CharacterFetcher {
|
|||||||
// MARK: - TMS fetch routines.
|
// MARK: - TMS fetch routines.
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<bool use_end> void Base<personality>::fetch_tms_refresh(LineBuffer &, int, int start, int end) {
|
template<bool use_end> void Base<personality>::fetch_tms_refresh(LineBuffer &, LineBuffer &, int, int start, int end) {
|
||||||
RefreshFetcher refresher(this);
|
RefreshFetcher refresher(this);
|
||||||
dispatch<use_end>(refresher, start, end);
|
dispatch<use_end>(refresher, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<bool use_end> void Base<personality>::fetch_tms_text(LineBuffer &line_buffer, int y, int start, int end) {
|
template<bool use_end> void Base<personality>::fetch_tms_text(LineBuffer &line_buffer, LineBuffer &, int y, int start, int end) {
|
||||||
TextFetcher fetcher(this, line_buffer, y);
|
TextFetcher fetcher(this, line_buffer, y);
|
||||||
dispatch<use_end>(fetcher, start, end);
|
dispatch<use_end>(fetcher, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<bool use_end> void Base<personality>::fetch_tms_character(LineBuffer &line_buffer, int y, int start, int end) {
|
template<bool use_end> void Base<personality>::fetch_tms_character(LineBuffer &line_buffer, LineBuffer &next_line_buffer, int y, int start, int end) {
|
||||||
CharacterFetcher fetcher(this, line_buffer, line_buffers_[(y + 1) % mode_timing_.total_lines], y);
|
CharacterFetcher fetcher(this, line_buffer, next_line_buffer, y);
|
||||||
dispatch<use_end>(fetcher, start, end);
|
dispatch<use_end>(fetcher, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,9 +414,9 @@ struct SMSFetcher {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer, int y, int start, int end) {
|
template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer, LineBuffer &next_line_buffer, int y, int start, int end) {
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
SMSFetcher fetcher(this, line_buffer, line_buffers_[(y + 1) % mode_timing_.total_lines], y);
|
SMSFetcher fetcher(this, line_buffer, next_line_buffer, y);
|
||||||
dispatch<use_end>(fetcher, start, end);
|
dispatch<use_end>(fetcher, start, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,7 +424,7 @@ template<bool use_end> void Base<personality>::fetch_sms(LineBuffer &line_buffer
|
|||||||
// MARK: - Yamaha
|
// MARK: - Yamaha
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_buffer, int y, int end) {
|
template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_buffer, LineBuffer &next_line_buffer, int y, int end) {
|
||||||
const AddressT rotated_name_ = pattern_name_address_ >> 1;
|
const AddressT rotated_name_ = pattern_name_address_ >> 1;
|
||||||
const uint8_t *const ram2 = &ram_[65536];
|
const uint8_t *const ram2 = &ram_[65536];
|
||||||
|
|
||||||
@ -455,6 +455,11 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
|
|||||||
name_[3] = ram_[start + column + 3];
|
name_[3] = ram_[start + column + 3];
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ScreenMode::Graphics: {
|
||||||
|
const auto row_base = pattern_name_address_ & (AddressT((y << 2)&~31) | 0x1fc00);
|
||||||
|
tile_offset_ = ram_[(row_base + Storage<personality>::next_event_->id) & 0x1ffff];
|
||||||
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -467,6 +472,12 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
|
|||||||
line_buffer.characters.flags[column] = ram_[address + column];
|
line_buffer.characters.flags[column] = ram_[address + column];
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ScreenMode::Graphics: {
|
||||||
|
const auto colour_base = (colour_table_address_ & (0x2000 | ((y & 0xc0) << 5))) + (y & 7);
|
||||||
|
line_buffer.tiles.patterns[Storage<personality>::next_event_->id][1] =
|
||||||
|
ram_[colour_base + AddressT((tile_offset_ << 3)) & 0x1ffff];
|
||||||
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -493,10 +504,56 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
|
|||||||
line_buffer.characters.shapes[column + 3] = ram_[start + AddressT(name_[3] << 3)];
|
line_buffer.characters.shapes[column + 3] = ram_[start + AddressT(name_[3] << 3)];
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ScreenMode::Graphics: {
|
||||||
|
const auto pattern_base = (pattern_generator_table_address_ & (0x2000 | ((y & 0xc0) << 5))) + (y & 7);
|
||||||
|
line_buffer.tiles.patterns[Storage<personality>::next_event_->id][0] =
|
||||||
|
ram_[(pattern_base + AddressT(tile_offset_ << 3)) & 0x1ffff];
|
||||||
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type::SpriteY:
|
||||||
|
switch(mode) {
|
||||||
|
default:
|
||||||
|
posit_sprite(next_line_buffer, Storage<personality>::next_event_->id, ram_[sprite_attribute_table_address_ & AddressT((Storage<personality>::next_event_->id << 2) | 0x1ff80)], y);
|
||||||
|
if(Storage<personality>::next_event_->id == 31) {
|
||||||
|
next_line_buffer.reset_sprite_collection();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::SpriteLocation:
|
||||||
|
switch(mode) {
|
||||||
|
default:
|
||||||
|
line_buffer.active_sprites[Storage<personality>::next_event_->id].x =
|
||||||
|
ram_[
|
||||||
|
sprite_attribute_table_address_ & AddressT(0x1ff81 | (line_buffer.active_sprites[Storage<personality>::next_event_->id].index << 2))
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type::SpritePattern:
|
||||||
|
switch(mode) {
|
||||||
|
default: {
|
||||||
|
const uint8_t name = ram_[
|
||||||
|
sprite_attribute_table_address_ & AddressT(0x1ff82 | (line_buffer.active_sprites[Storage<personality>::next_event_->id].index << 2))
|
||||||
|
] & (sprites_16x16_ ? ~3 : ~0);
|
||||||
|
line_buffer.active_sprites[Storage<personality>::next_event_->id].image[2] = ram_[
|
||||||
|
sprite_attribute_table_address_ & AddressT(0x1ff83 | (line_buffer.active_sprites[Storage<personality>::next_event_->id].index << 2))
|
||||||
|
];
|
||||||
|
line_buffer.active_sprites[Storage<personality>::next_event_->id].x -= (line_buffer.active_sprites[Storage<personality>::next_event_->id].image[2] & 0x80) >> 2;
|
||||||
|
|
||||||
|
const size_t graphic_location = sprite_generator_table_address_ & AddressT(0x1f800 | (name << 3) | line_buffer.active_sprites[Storage<personality>::next_event_->id].row);
|
||||||
|
line_buffer.active_sprites[Storage<personality>::next_event_->id].image[0] = ram_[graphic_location];
|
||||||
|
line_buffer.active_sprites[Storage<personality>::next_event_->id].image[1] = ram_[graphic_location+16];
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Type::DataBlock:
|
case Type::DataBlock:
|
||||||
// Exactly how to fetch depends upon mode...
|
// Exactly how to fetch depends upon mode...
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
@ -544,10 +601,10 @@ template<ScreenMode mode> void Base<personality>::fetch_yamaha(LineBuffer &line_
|
|||||||
|
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<bool use_end> void Base<personality>::fetch_yamaha(LineBuffer &line_buffer, int y, int, int end) {
|
template<bool use_end> void Base<personality>::fetch_yamaha(LineBuffer &line_buffer, LineBuffer &next_line_buffer, int y, int, int end) {
|
||||||
if constexpr (is_yamaha_vdp(personality)) {
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
// Dispatch according to [supported] screen mode.
|
// Dispatch according to [supported] screen mode.
|
||||||
#define Dispatch(mode) case mode: fetch_yamaha<mode>(line_buffer, y, end); break;
|
#define Dispatch(mode) case mode: fetch_yamaha<mode>(line_buffer, next_line_buffer, y, end); break;
|
||||||
switch(line_buffer.screen_mode) {
|
switch(line_buffer.screen_mode) {
|
||||||
default: break;
|
default: break;
|
||||||
Dispatch(ScreenMode::Blank);
|
Dispatch(ScreenMode::Blank);
|
||||||
|
Loading…
Reference in New Issue
Block a user