mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Move Master System state, and start simplifying.
This commit is contained in:
parent
1fb94d15ab
commit
4b7606894e
@ -481,12 +481,11 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
|
|||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
void Base<personality>::output_border(int cycles, [[maybe_unused]] uint32_t cram_dot) {
|
void Base<personality>::output_border(int cycles, [[maybe_unused]] uint32_t cram_dot) {
|
||||||
cycles = from_internal<personality, Clock::CRT>(cycles);
|
cycles = from_internal<personality, Clock::CRT>(cycles);
|
||||||
const uint32_t border_colour =
|
|
||||||
is_sega_vdp(personality) ?
|
|
||||||
master_system_.colour_ram[16 + background_colour_] :
|
|
||||||
palette[background_colour_];
|
|
||||||
|
|
||||||
|
uint32_t border_colour;
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
border_colour = Storage<personality>::colour_ram_[16 + background_colour_];
|
||||||
|
|
||||||
if(cram_dot) {
|
if(cram_dot) {
|
||||||
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_.begin_data(1));
|
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_.begin_data(1));
|
||||||
if(pixel_target) {
|
if(pixel_target) {
|
||||||
@ -498,6 +497,8 @@ void Base<personality>::output_border(int cycles, [[maybe_unused]] uint32_t cram
|
|||||||
crt_.output_level(4);
|
crt_.output_level(4);
|
||||||
cycles -= 4;
|
cycles -= 4;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
border_colour = palette[background_colour_];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!cycles) {
|
if(!cycles) {
|
||||||
@ -562,7 +563,7 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
value &= 0x7f;
|
value &= 0x7f;
|
||||||
} else if constexpr (is_sega_vdp(personality)) {
|
} else if constexpr (is_sega_vdp(personality)) {
|
||||||
if(value & 0x40) {
|
if(value & 0x40) {
|
||||||
master_system_.cram_is_selected = true;
|
Storage<personality>::cram_is_selected_ = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
value &= 0xf;
|
value &= 0xf;
|
||||||
@ -574,12 +575,12 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
switch(value) {
|
switch(value) {
|
||||||
case 0:
|
case 0:
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
master_system_.vertical_scroll_lock = low_write_ & 0x80;
|
Storage<personality>::master_system_.vertical_scroll_lock = low_write_ & 0x80;
|
||||||
master_system_.horizontal_scroll_lock = low_write_ & 0x40;
|
Storage<personality>::master_system_.horizontal_scroll_lock = low_write_ & 0x40;
|
||||||
master_system_.hide_left_column = low_write_ & 0x20;
|
Storage<personality>::master_system_.hide_left_column = low_write_ & 0x20;
|
||||||
enable_line_interrupts_ = low_write_ & 0x10;
|
enable_line_interrupts_ = low_write_ & 0x10;
|
||||||
master_system_.shift_sprites_8px_left = low_write_ & 0x08;
|
Storage<personality>::master_system_.shift_sprites_8px_left = low_write_ & 0x08;
|
||||||
master_system_.mode4_enable = low_write_ & 0x04;
|
Storage<personality>::master_system_.mode4_enable = low_write_ & 0x04;
|
||||||
}
|
}
|
||||||
mode2_enable_ = low_write_ & 0x02;
|
mode2_enable_ = low_write_ & 0x02;
|
||||||
break;
|
break;
|
||||||
@ -599,7 +600,10 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
pattern_name_address_ = size_t((low_write_ & 0xf) << 10) | 0x3ff;
|
pattern_name_address_ = size_t((low_write_ & 0xf) << 10) | 0x3ff;
|
||||||
master_system_.pattern_name_address = pattern_name_address_ | ((personality == TMS::SMSVDP) ? 0x000 : 0x400);
|
|
||||||
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
Storage<personality>::master_system_.pattern_name_address = pattern_name_address_ | ((personality == TMS::SMSVDP) ? 0x000 : 0x400);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
@ -612,12 +616,16 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
sprite_attribute_table_address_ = size_t((low_write_ & 0x7f) << 7) | 0x7f;
|
sprite_attribute_table_address_ = size_t((low_write_ & 0x7f) << 7) | 0x7f;
|
||||||
master_system_.sprite_attribute_table_address = sprite_attribute_table_address_ | ((personality == TMS::SMSVDP) ? 0x00 : 0x80);
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
Storage<personality>::master_system_.sprite_attribute_table_address = sprite_attribute_table_address_ | ((personality == TMS::SMSVDP) ? 0x00 : 0x80);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
sprite_generator_table_address_ = size_t((low_write_ & 0x07) << 11) | 0x7ff;
|
sprite_generator_table_address_ = size_t((low_write_ & 0x07) << 11) | 0x7ff;
|
||||||
master_system_.sprite_generator_table_address = sprite_generator_table_address_ | ((personality == TMS::SMSVDP) ? 0x0000 : 0x1800);
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
Storage<personality>::master_system_.sprite_generator_table_address = sprite_generator_table_address_ | ((personality == TMS::SMSVDP) ? 0x0000 : 0x1800);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
@ -627,7 +635,7 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
master_system_.horizontal_scroll = low_write_;
|
Storage<personality>::master_system_.horizontal_scroll = low_write_;
|
||||||
} else {
|
} else {
|
||||||
LOG("Unknown TMS write: " << int(low_write_) << " to " << int(value));
|
LOG("Unknown TMS write: " << int(low_write_) << " to " << int(value));
|
||||||
}
|
}
|
||||||
@ -635,7 +643,7 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
|
|
||||||
case 9:
|
case 9:
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
master_system_.vertical_scroll = low_write_;
|
Storage<personality>::master_system_.vertical_scroll = low_write_;
|
||||||
} else {
|
} else {
|
||||||
LOG("Unknown TMS write: " << int(low_write_) << " to " << int(value));
|
LOG("Unknown TMS write: " << int(low_write_) << " to " << int(value));
|
||||||
}
|
}
|
||||||
@ -667,7 +675,10 @@ void Base<personality>::write_register(uint8_t value) {
|
|||||||
queued_access_ = MemoryAccess::Read;
|
queued_access_ = MemoryAccess::Read;
|
||||||
cycles_until_access_ = Timing<personality>::VRAMAccessDelay;
|
cycles_until_access_ = Timing<personality>::VRAMAccessDelay;
|
||||||
}
|
}
|
||||||
master_system_.cram_is_selected = false;
|
|
||||||
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
Storage<personality>::cram_is_selected_ = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,5 +908,5 @@ template class TI::TMS::TMS9918<Personality::V9938>;
|
|||||||
//template class TI::TMS::TMS9918<Personality::V9958>;
|
//template class TI::TMS::TMS9918<Personality::V9958>;
|
||||||
template class TI::TMS::TMS9918<Personality::SMSVDP>;
|
template class TI::TMS::TMS9918<Personality::SMSVDP>;
|
||||||
template class TI::TMS::TMS9918<Personality::SMS2VDP>;
|
template class TI::TMS::TMS9918<Personality::SMS2VDP>;
|
||||||
template class TI::TMS::TMS9918<Personality::GGVDP>;
|
//template class TI::TMS::TMS9918<Personality::GGVDP>;
|
||||||
//template class TI::TMS::TMS9918<Personality::MDVDP>;
|
//template class TI::TMS::TMS9918<Personality::MDVDP>;
|
||||||
|
@ -132,7 +132,39 @@ template <Personality personality> struct Storage<personality, std::enable_if_t<
|
|||||||
|
|
||||||
// Master System-specific storage.
|
// Master System-specific storage.
|
||||||
template <Personality personality> struct Storage<personality, std::enable_if_t<is_sega_vdp(personality)>> {
|
template <Personality personality> struct Storage<personality, std::enable_if_t<is_sega_vdp(personality)>> {
|
||||||
// TODO: relocate contents of master_system_ struct;
|
// The SMS VDP has a programmer-set colour palette, with a dedicated patch of RAM. But the RAM is only exactly
|
||||||
|
// fast enough for the pixel clock. So when the programmer writes to it, that causes a one-pixel glitch; there
|
||||||
|
// isn't the bandwidth for the read both write to occur simultaneously. The following buffer therefore keeps
|
||||||
|
// track of pending collisions, for visual reproduction.
|
||||||
|
struct CRAMDot {
|
||||||
|
LineBufferPointer location;
|
||||||
|
uint32_t value;
|
||||||
|
};
|
||||||
|
std::vector<CRAMDot> upcoming_cram_dots_;
|
||||||
|
|
||||||
|
// The Master System's additional colour RAM.
|
||||||
|
uint32_t colour_ram_[32];
|
||||||
|
bool cram_is_selected_ = false;
|
||||||
|
|
||||||
|
// Fields below affect only the Master System output mode.
|
||||||
|
struct {
|
||||||
|
// Programmer-set flags.
|
||||||
|
bool vertical_scroll_lock = false;
|
||||||
|
bool horizontal_scroll_lock = false;
|
||||||
|
bool hide_left_column = false;
|
||||||
|
bool shift_sprites_8px_left = false;
|
||||||
|
bool mode4_enable = false;
|
||||||
|
uint8_t horizontal_scroll = 0;
|
||||||
|
uint8_t vertical_scroll = 0;
|
||||||
|
|
||||||
|
// Holds the vertical scroll position for this frame; this is latched
|
||||||
|
// once and cannot dynamically be changed until the next frame.
|
||||||
|
uint8_t latched_vertical_scroll = 0;
|
||||||
|
|
||||||
|
size_t pattern_name_address;
|
||||||
|
size_t sprite_attribute_table_address;
|
||||||
|
size_t sprite_generator_table_address;
|
||||||
|
} master_system_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <Personality personality> struct Base: public Storage<personality> {
|
template <Personality personality> struct Base: public Storage<personality> {
|
||||||
@ -269,40 +301,6 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
// with the beginning of writing the next, hence the two separate line buffers.
|
// with the beginning of writing the next, hence the two separate line buffers.
|
||||||
LineBufferPointer read_pointer_, write_pointer_;
|
LineBufferPointer read_pointer_, write_pointer_;
|
||||||
|
|
||||||
// The SMS VDP has a programmer-set colour palette, with a dedicated patch of RAM. But the RAM is only exactly
|
|
||||||
// fast enough for the pixel clock. So when the programmer writes to it, that causes a one-pixel glitch; there
|
|
||||||
// isn't the bandwidth for the read both write to occur simultaneously. The following buffer therefore keeps
|
|
||||||
// track of pending collisions, for visual reproduction.
|
|
||||||
struct CRAMDot {
|
|
||||||
LineBufferPointer location;
|
|
||||||
uint32_t value;
|
|
||||||
};
|
|
||||||
std::vector<CRAMDot> upcoming_cram_dots_;
|
|
||||||
|
|
||||||
// Extra information that affects the Master System output mode.
|
|
||||||
struct {
|
|
||||||
// Programmer-set flags.
|
|
||||||
bool vertical_scroll_lock = false;
|
|
||||||
bool horizontal_scroll_lock = false;
|
|
||||||
bool hide_left_column = false;
|
|
||||||
bool shift_sprites_8px_left = false;
|
|
||||||
bool mode4_enable = false;
|
|
||||||
uint8_t horizontal_scroll = 0;
|
|
||||||
uint8_t vertical_scroll = 0;
|
|
||||||
|
|
||||||
// The Master System's additional colour RAM.
|
|
||||||
uint32_t colour_ram[32];
|
|
||||||
bool cram_is_selected = false;
|
|
||||||
|
|
||||||
// Holds the vertical scroll position for this frame; this is latched
|
|
||||||
// once and cannot dynamically be changed until the next frame.
|
|
||||||
uint8_t latched_vertical_scroll = 0;
|
|
||||||
|
|
||||||
size_t pattern_name_address;
|
|
||||||
size_t sprite_attribute_table_address;
|
|
||||||
size_t sprite_generator_table_address;
|
|
||||||
} master_system_;
|
|
||||||
|
|
||||||
int masked_address(int address);
|
int masked_address(int address);
|
||||||
void write_vram(uint8_t);
|
void write_vram(uint8_t);
|
||||||
void write_register(uint8_t);
|
void write_register(uint8_t);
|
||||||
@ -319,7 +317,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
if(master_system_.mode4_enable) {
|
if(Storage<personality>::master_system_.mode4_enable) {
|
||||||
return ScreenMode::SMSMode4;
|
return ScreenMode::SMSMode4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,12 +354,12 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
|
|
||||||
case MemoryAccess::Write:
|
case MemoryAccess::Write:
|
||||||
if constexpr (is_sega_vdp(personality)) {
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
if(master_system_.cram_is_selected) {
|
if(Storage<personality>::cram_is_selected_) {
|
||||||
// Adjust the palette. In a Master System blue has a slightly different
|
// Adjust the palette. In a Master System blue has a slightly different
|
||||||
// scale; cf. https://www.retrorgb.com/sega-master-system-non-linear-blue-channel-findings.html
|
// scale; cf. https://www.retrorgb.com/sega-master-system-non-linear-blue-channel-findings.html
|
||||||
constexpr uint8_t rg_scale[] = {0, 85, 170, 255};
|
constexpr uint8_t rg_scale[] = {0, 85, 170, 255};
|
||||||
constexpr uint8_t b_scale[] = {0, 104, 170, 255};
|
constexpr uint8_t b_scale[] = {0, 104, 170, 255};
|
||||||
master_system_.colour_ram[ram_pointer_ & 0x1f] = palette_pack(
|
Storage<personality>::colour_ram_[ram_pointer_ & 0x1f] = palette_pack(
|
||||||
rg_scale[(read_ahead_buffer_ >> 0) & 3],
|
rg_scale[(read_ahead_buffer_ >> 0) & 3],
|
||||||
rg_scale[(read_ahead_buffer_ >> 2) & 3],
|
rg_scale[(read_ahead_buffer_ >> 2) & 3],
|
||||||
b_scale[(read_ahead_buffer_ >> 4) & 3]
|
b_scale[(read_ahead_buffer_ >> 4) & 3]
|
||||||
@ -370,7 +368,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
// Schedule a CRAM dot; this is scheduled for wherever it should appear
|
// Schedule a CRAM dot; this is scheduled for wherever it should appear
|
||||||
// on screen. So it's wherever the output stream would be now. Which
|
// on screen. So it's wherever the output stream would be now. Which
|
||||||
// is output_lag cycles ago from the point of view of the input stream.
|
// is output_lag cycles ago from the point of view of the input stream.
|
||||||
CRAMDot &dot = upcoming_cram_dots_.emplace_back();
|
auto &dot = Storage<personality>::upcoming_cram_dots_.emplace_back();
|
||||||
dot.location.column = write_pointer_.column - output_lag;
|
dot.location.column = write_pointer_.column - output_lag;
|
||||||
dot.location.row = write_pointer_.row;
|
dot.location.row = write_pointer_.row;
|
||||||
|
|
||||||
@ -383,7 +381,7 @@ template <Personality personality> struct Base: public Storage<personality> {
|
|||||||
dot.location.row += dot.location.column / 342;
|
dot.location.row += dot.location.column / 342;
|
||||||
dot.location.column %= 342;
|
dot.location.column %= 342;
|
||||||
|
|
||||||
dot.value = master_system_.colour_ram[ram_pointer_ & 0x1f];
|
dot.value = Storage<personality>::colour_ram_[ram_pointer_ & 0x1f];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,8 @@ void Base<personality>::draw_tms_text(int start, int end) {
|
|||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
void Base<personality>::draw_sms(int start, int end, uint32_t cram_dot) {
|
void Base<personality>::draw_sms(int start, int end, uint32_t cram_dot) {
|
||||||
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
|
||||||
LineBuffer &line_buffer = line_buffers_[read_pointer_.row];
|
LineBuffer &line_buffer = line_buffers_[read_pointer_.row];
|
||||||
int colour_buffer[256];
|
int colour_buffer[256];
|
||||||
|
|
||||||
@ -141,7 +143,7 @@ void Base<personality>::draw_sms(int start, int end, uint32_t cram_dot) {
|
|||||||
*/
|
*/
|
||||||
int tile_start = start, tile_end = end;
|
int tile_start = start, tile_end = end;
|
||||||
int tile_offset = start;
|
int tile_offset = start;
|
||||||
if(read_pointer_.row >= 16 || !master_system_.horizontal_scroll_lock) {
|
if(read_pointer_.row >= 16 || !Storage<personality>::master_system_.horizontal_scroll_lock) {
|
||||||
for(int c = start; c < (line_buffer.latched_horizontal_scroll & 7); ++c) {
|
for(int c = start; c < (line_buffer.latched_horizontal_scroll & 7); ++c) {
|
||||||
colour_buffer[c] = 16 + background_colour_;
|
colour_buffer[c] = 16 + background_colour_;
|
||||||
++tile_offset;
|
++tile_offset;
|
||||||
@ -266,20 +268,22 @@ void Base<personality>::draw_sms(int start, int end, uint32_t cram_dot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map from the 32-colour buffer to real output pixels, applying the specific CRAM dot if any.
|
// Map from the 32-colour buffer to real output pixels, applying the specific CRAM dot if any.
|
||||||
pixel_target_[start] = master_system_.colour_ram[colour_buffer[start] & 0x1f] | cram_dot;
|
pixel_target_[start] = Storage<personality>::colour_ram_[colour_buffer[start] & 0x1f] | cram_dot;
|
||||||
for(int c = start+1; c < end; ++c) {
|
for(int c = start+1; c < end; ++c) {
|
||||||
pixel_target_[c] = master_system_.colour_ram[colour_buffer[c] & 0x1f];
|
pixel_target_[c] = Storage<personality>::colour_ram_[colour_buffer[c] & 0x1f];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the VDP is set to hide the left column and this is the final call that'll come
|
// If the VDP is set to hide the left column and this is the final call that'll come
|
||||||
// this line, hide it.
|
// this line, hide it.
|
||||||
if(end == 256) {
|
if(end == 256) {
|
||||||
if(master_system_.hide_left_column) {
|
if(Storage<personality>::master_system_.hide_left_column) {
|
||||||
pixel_origin_[0] = pixel_origin_[1] = pixel_origin_[2] = pixel_origin_[3] =
|
pixel_origin_[0] = pixel_origin_[1] = pixel_origin_[2] = pixel_origin_[3] =
|
||||||
pixel_origin_[4] = pixel_origin_[5] = pixel_origin_[6] = pixel_origin_[7] =
|
pixel_origin_[4] = pixel_origin_[5] = pixel_origin_[6] = pixel_origin_[7] =
|
||||||
master_system_.colour_ram[16 + background_colour_];
|
Storage<personality>::colour_ram_[16 + background_colour_];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Yamaha
|
// MARK: - Yamaha
|
||||||
|
@ -319,15 +319,17 @@ template<bool use_end> void Base<personality>::fetch_tms_character(int start, in
|
|||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
|
template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
|
||||||
|
if constexpr (is_sega_vdp(personality)) {
|
||||||
|
|
||||||
#define sprite_fetch(sprite) {\
|
#define sprite_fetch(sprite) {\
|
||||||
line_buffer.active_sprites[sprite].x = \
|
line_buffer.active_sprites[sprite].x = \
|
||||||
ram_[\
|
ram_[\
|
||||||
master_system_.sprite_attribute_table_address & size_t(0x3f80 | (line_buffer.active_sprites[sprite].index << 1))\
|
Storage<personality>::master_system_.sprite_attribute_table_address & size_t(0x3f80 | (line_buffer.active_sprites[sprite].index << 1))\
|
||||||
] - (master_system_.shift_sprites_8px_left ? 8 : 0); \
|
] - (Storage<personality>::master_system_.shift_sprites_8px_left ? 8 : 0); \
|
||||||
const uint8_t name = ram_[\
|
const uint8_t name = ram_[\
|
||||||
master_system_.sprite_attribute_table_address & size_t(0x3f81 | (line_buffer.active_sprites[sprite].index << 1))\
|
Storage<personality>::master_system_.sprite_attribute_table_address & size_t(0x3f81 | (line_buffer.active_sprites[sprite].index << 1))\
|
||||||
] & (sprites_16x16_ ? ~1 : ~0);\
|
] & (sprites_16x16_ ? ~1 : ~0);\
|
||||||
const size_t graphic_location = master_system_.sprite_generator_table_address & size_t(0x2000 | (name << 5) | (line_buffer.active_sprites[sprite].row << 2)); \
|
const size_t graphic_location = Storage<personality>::master_system_.sprite_generator_table_address & size_t(0x2000 | (name << 5) | (line_buffer.active_sprites[sprite].row << 2)); \
|
||||||
line_buffer.active_sprites[sprite].image[0] = ram_[graphic_location]; \
|
line_buffer.active_sprites[sprite].image[0] = ram_[graphic_location]; \
|
||||||
line_buffer.active_sprites[sprite].image[1] = ram_[graphic_location+1]; \
|
line_buffer.active_sprites[sprite].image[1] = ram_[graphic_location+1]; \
|
||||||
line_buffer.active_sprites[sprite].image[2] = ram_[graphic_location+2]; \
|
line_buffer.active_sprites[sprite].image[2] = ram_[graphic_location+2]; \
|
||||||
@ -346,8 +348,8 @@ template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
|
|||||||
|
|
||||||
#define sprite_y_read(location, sprite) \
|
#define sprite_y_read(location, sprite) \
|
||||||
slot(location): \
|
slot(location): \
|
||||||
posit_sprite(sprite_selection_buffer, sprite, ram_[master_system_.sprite_attribute_table_address & ((sprite) | 0x3f00)], write_pointer_.row); \
|
posit_sprite(sprite_selection_buffer, sprite, ram_[Storage<personality>::master_system_.sprite_attribute_table_address & ((sprite) | 0x3f00)], write_pointer_.row); \
|
||||||
posit_sprite(sprite_selection_buffer, sprite+1, ram_[master_system_.sprite_attribute_table_address & ((sprite + 1) | 0x3f00)], write_pointer_.row); \
|
posit_sprite(sprite_selection_buffer, sprite+1, ram_[Storage<personality>::master_system_.sprite_attribute_table_address & ((sprite + 1) | 0x3f00)], write_pointer_.row); \
|
||||||
|
|
||||||
#define fetch_tile_name(column, row_info) {\
|
#define fetch_tile_name(column, row_info) {\
|
||||||
const size_t scrolled_column = (column - horizontal_offset) & 0x1f;\
|
const size_t scrolled_column = (column - horizontal_offset) & 0x1f;\
|
||||||
@ -391,16 +393,16 @@ template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
|
|||||||
// Determine the coarse horizontal scrolling offset; this isn't applied on the first two lines if the programmer has requested it.
|
// Determine the coarse horizontal scrolling offset; this isn't applied on the first two lines if the programmer has requested it.
|
||||||
LineBuffer &line_buffer = line_buffers_[write_pointer_.row];
|
LineBuffer &line_buffer = line_buffers_[write_pointer_.row];
|
||||||
LineBuffer &sprite_selection_buffer = line_buffers_[(write_pointer_.row + 1) % mode_timing_.total_lines];
|
LineBuffer &sprite_selection_buffer = line_buffers_[(write_pointer_.row + 1) % mode_timing_.total_lines];
|
||||||
const int horizontal_offset = (write_pointer_.row >= 16 || !master_system_.horizontal_scroll_lock) ? (line_buffer.latched_horizontal_scroll >> 3) : 0;
|
const int horizontal_offset = (write_pointer_.row >= 16 || !Storage<personality>::master_system_.horizontal_scroll_lock) ? (line_buffer.latched_horizontal_scroll >> 3) : 0;
|
||||||
|
|
||||||
// Limit address bits in use if this is a SMS2 mode.
|
// Limit address bits in use if this is a SMS2 mode.
|
||||||
const bool is_tall_mode = mode_timing_.pixel_lines != 192;
|
const bool is_tall_mode = mode_timing_.pixel_lines != 192;
|
||||||
const size_t pattern_name_address = master_system_.pattern_name_address | (is_tall_mode ? 0x800 : 0);
|
const size_t pattern_name_address = Storage<personality>::master_system_.pattern_name_address | (is_tall_mode ? 0x800 : 0);
|
||||||
const size_t pattern_name_offset = is_tall_mode ? 0x100 : 0;
|
const size_t pattern_name_offset = is_tall_mode ? 0x100 : 0;
|
||||||
|
|
||||||
// Determine row info for the screen both (i) if vertical scrolling is applied; and (ii) if it isn't.
|
// Determine row info for the screen both (i) if vertical scrolling is applied; and (ii) if it isn't.
|
||||||
// The programmer can opt out of applying vertical scrolling to the right-hand portion of the display.
|
// The programmer can opt out of applying vertical scrolling to the right-hand portion of the display.
|
||||||
const int scrolled_row = (write_pointer_.row + master_system_.latched_vertical_scroll) % (is_tall_mode ? 256 : 224);
|
const int scrolled_row = (write_pointer_.row + Storage<personality>::master_system_.latched_vertical_scroll) % (is_tall_mode ? 256 : 224);
|
||||||
struct RowInfo {
|
struct RowInfo {
|
||||||
size_t pattern_address_base;
|
size_t pattern_address_base;
|
||||||
size_t sub_row[2];
|
size_t sub_row[2];
|
||||||
@ -410,7 +412,7 @@ template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
|
|||||||
{size_t((scrolled_row & 7) << 2), 28 ^ size_t((scrolled_row & 7) << 2)}
|
{size_t((scrolled_row & 7) << 2), 28 ^ size_t((scrolled_row & 7) << 2)}
|
||||||
};
|
};
|
||||||
RowInfo row_info;
|
RowInfo row_info;
|
||||||
if(master_system_.vertical_scroll_lock) {
|
if(Storage<personality>::master_system_.vertical_scroll_lock) {
|
||||||
row_info.pattern_address_base = (pattern_name_address & size_t(((write_pointer_.row & ~7) << 3) | 0x3800)) - pattern_name_offset;
|
row_info.pattern_address_base = (pattern_name_address & size_t(((write_pointer_.row & ~7) << 3) | 0x3800)) - pattern_name_offset;
|
||||||
row_info.sub_row[0] = size_t((write_pointer_.row & 7) << 2);
|
row_info.sub_row[0] = size_t((write_pointer_.row & 7) << 2);
|
||||||
row_info.sub_row[1] = 28 ^ size_t((write_pointer_.row & 7) << 2);
|
row_info.sub_row[1] = 28 ^ size_t((write_pointer_.row & 7) << 2);
|
||||||
@ -463,6 +465,7 @@ template<bool use_end> void Base<personality>::fetch_sms(int start, int end) {
|
|||||||
#undef sprite_y_read
|
#undef sprite_y_read
|
||||||
#undef sprite_fetch_block
|
#undef sprite_fetch_block
|
||||||
#undef sprite_fetch
|
#undef sprite_fetch
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Yamaha
|
// MARK: - Yamaha
|
||||||
|
Loading…
Reference in New Issue
Block a user