diff options
author | Oxore <oxore@protonmail.com> | 2023-05-07 13:22:46 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-05-07 13:22:46 +0300 |
commit | f475974aeee25082d6384f69212a9d237d394477 (patch) | |
tree | aa8e350f6c69fc8661ac2210fb1b4e2ef5a22342 /vdp.cpp | |
parent | bce8c2f19a564f17d41fa0a3fb935b0181cad147 (diff) |
Impl vertical overall scrolling
Diffstat (limited to 'vdp.cpp')
-rw-r--r-- | vdp.cpp | 69 |
1 files changed, 46 insertions, 23 deletions
@@ -98,7 +98,7 @@ static constexpr size_t kCellHeightPixels = 8; static constexpr size_t kPixelsPerByte = 2; static constexpr size_t kBitsPerPixel = 4; // Only 10 bits are effective in scroll speed value -static constexpr uint16_t kHscrollSpeedMask = BitsCountToMask(10); +static constexpr uint16_t kScrollSpeedMask = BitsCountToMask(10); // Each pixel has 4 bit depth color static constexpr uint16_t kPixelColorMask = BitsCountToMask(kBitsPerPixel); @@ -196,7 +196,7 @@ static inline size_t scrollsize_cells_count(uint8_t xcell_value) return (xcell_value + 1) * 32; } -static inline uint32_t RenderColorFromCRAM(uint16_t color) +static constexpr inline uint32_t RenderColorFromCRAM(uint16_t color) { const uint32_t blue = ((color >> 9) & 7) << 5; const uint32_t green = ((color >> 5) & 7) << 5; @@ -204,20 +204,34 @@ static inline uint32_t RenderColorFromCRAM(uint16_t color) return 0xff000000 | (red << 16) | (green << 8) | blue; } -static inline uint32_t GetU32BE(const void *buf) +static constexpr inline uint32_t GetU32BE(const void *buf) { return - (static_cast<uint32_t>(reinterpret_cast<const uint8_t*>(buf)[0]) << 24) | - (static_cast<uint32_t>(reinterpret_cast<const uint8_t*>(buf)[1]) << 16) | - (static_cast<uint32_t>(reinterpret_cast<const uint8_t*>(buf)[2]) << 8) | - (static_cast<uint32_t>(reinterpret_cast<const uint8_t*>(buf)[3]) << 0); + (static_cast<uint32_t>(static_cast<const uint8_t*>(buf)[0]) << 24) | + (static_cast<uint32_t>(static_cast<const uint8_t*>(buf)[1]) << 16) | + (static_cast<uint32_t>(static_cast<const uint8_t*>(buf)[2]) << 8) | + (static_cast<uint32_t>(static_cast<const uint8_t*>(buf)[3]) << 0); } -static inline uint16_t GetU16BE(const void *buf) +static constexpr inline uint16_t GetU16BE(const void *buf) { return - (static_cast<uint16_t>(reinterpret_cast<const uint8_t*>(buf)[0]) << 8) | - (static_cast<uint16_t>(reinterpret_cast<const uint8_t*>(buf)[1]) << 0); + (static_cast<uint16_t>(static_cast<const uint8_t*>(buf)[0]) << 8) | + (static_cast<uint16_t>(static_cast<const uint8_t*>(buf)[1]) << 0); +} + +static constexpr size_t AddWrapping(size_t a, size_t b, const size_t range) +{ + a = a % range; + b = b % range; + if (a >= b) { + if (range - a < b) { + return b - (range - a); + } + } else if (range - b < a) { + return a - (range - b); + } + return a + b; } void VDP::renderScrollLine( @@ -225,12 +239,16 @@ void VDP::renderScrollLine( const uint16_t plane_addr, const uint16_t hscroll_table_addr, const size_t plane_index, - const size_t hcell_count) + const size_t hcell_count, + const size_t vcell_count) { + // TODO impl cell scroll and line scroll depending on kModeSet3 regester value + const size_t vscroll = + GetU16BE(_vsram + sizeof(uint16_t) * plane_index) & kScrollSpeedMask; const size_t hscroll = - GetU16BE(_vram + hscroll_table_addr + sizeof(uint16_t) * plane_index) & kHscrollSpeedMask; - const size_t cy = line_index / kCellHeightPixels; - const size_t y = line_index % kCellHeightPixels; + GetU16BE(_vram + hscroll_table_addr + sizeof(uint16_t) * plane_index) & kScrollSpeedMask; + const size_t cy = AddWrapping(line_index, vscroll, vcell_count * kCellHeightPixels) / kCellHeightPixels; + const size_t y = AddWrapping(line_index, vscroll, vcell_count * kCellHeightPixels) % kCellHeightPixels; for (size_t cx = 0; cx < hcell_count; cx++) { const uint16_t sprite_id = GetU16BE( _vram + plane_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); @@ -243,6 +261,10 @@ void VDP::renderScrollLine( if (render_offset_x >= kRenderWidth) { continue; } + const size_t render_offset_y = line_index * kRenderWidth; + if (render_offset_y >= kRenderWidth * kRenderHeight) { + continue; + } const size_t color_index = (val >> ((kCellWidthPixels - 1 - x) * kBitsPerPixel)) & kPixelColorMask; const uint16_t bgcolor_reg = _reg[static_cast<size_t>(RegID::kBackgroundColor)]; @@ -256,27 +278,27 @@ void VDP::renderScrollLine( } const uint16_t cram_color = GetU16BE(_cram + color_index * sizeof(uint16_t)); const uint32_t color = RenderColorFromCRAM(cram_color); - const size_t render_offset = - ((cy * kCellHeightPixels + y) * kRenderWidth) + render_offset_x; - _rendered_buffer[render_offset] = color; + _rendered_buffer[render_offset_y + render_offset_x] = color; } } } -void VDP::renderScrollBLine(const size_t line_index, const size_t hcell_count) +void VDP::renderScrollBLine( + const size_t line_index, const size_t hcell_count, const size_t vcell_count) { const uint16_t plane_addr = SCROLLB_ADDR_GET(_reg[static_cast<size_t>(RegID::kScrollBAddress)]); const size_t hscroll_table_addr = HSCROLL_TABLE_ADDR_GET(_reg[static_cast<size_t>(RegID::kHScrollTableAddress)]); - renderScrollLine(line_index, plane_addr, hscroll_table_addr, 1, hcell_count); + renderScrollLine(line_index, plane_addr, hscroll_table_addr, 1, hcell_count, vcell_count); } -void VDP::renderScrollALine(const size_t line_index, const size_t hcell_count) +void VDP::renderScrollALine( + const size_t line_index, const size_t hcell_count, const size_t vcell_count) { const uint16_t plane_addr = SCROLLA_ADDR_GET(_reg[static_cast<size_t>(RegID::kScrollAAddress)]); const size_t hscroll_table_addr = HSCROLL_TABLE_ADDR_GET(_reg[static_cast<size_t>(RegID::kHScrollTableAddress)]); - renderScrollLine(line_index, plane_addr, hscroll_table_addr, 0, hcell_count); + renderScrollLine(line_index, plane_addr, hscroll_table_addr, 0, hcell_count, vcell_count); } bool VDP::Scanline() @@ -306,8 +328,9 @@ bool VDP::Scanline() // 2 is prohibited value, so we just won't render if it is set if (vcell != 2 && hcell != 2) { const size_t hcell_count = scrollsize_cells_count(hcell); - renderScrollBLine(_lines_counter, hcell_count); - renderScrollALine(_lines_counter, hcell_count); + const size_t vcell_count = scrollsize_cells_count(vcell); + renderScrollBLine(_lines_counter, hcell_count, vcell_count); + renderScrollALine(_lines_counter, hcell_count, vcell_count); } } _lines_counter++; |