diff options
author | Oxore <oxore@protonmail.com> | 2023-05-07 00:25:04 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-05-07 00:25:04 +0300 |
commit | 9214810f4305efef3667820b37ebd942782279da (patch) | |
tree | 9971c4c50f590d2ed8d571b95375b7de075b8f9a | |
parent | b56bb29d9ba8d0d4dfaf6371e81f7cf73f076a3b (diff) |
Impl scroll plane B
-rw-r--r-- | vdp.cpp | 62 | ||||
-rw-r--r-- | vdp.hpp | 1 |
2 files changed, 60 insertions, 3 deletions
@@ -53,6 +53,14 @@ ((reg) = ((reg) & ~SCROLLA_ADDR_MASK) \ | (((uint16_t)(v) >> SCROLLA_ADDR_SHIFT) & SCROLLA_ADDR_MASK)) +#define SCROLLB_ADDR_MASK (7) +#define SCROLLB_ADDR_SHIFT (13) +#define SCROLLB_ADDR_GET(reg) \ + ((((uint16_t)(reg)) & (SCROLLB_ADDR_MASK)) << SCROLLB_ADDR_SHIFT) +#define SCROLLB_ADDR_SET(reg, v) \ + ((reg) = ((reg) & ~SCROLLB_ADDR_MASK) \ + | (((uint16_t)(v) >> SCROLLB_ADDR_SHIFT) & SCROLLB_ADDR_MASK)) + // 0: V32 CELL, 1: V64 CELL, 2: Prohibited, 3: V128 CELL #define SCROLLSIZE_VCELL_MASK (3) #define SCROLLSIZE_VCELL_SHIFT (4) @@ -201,10 +209,47 @@ static inline uint16_t GetU16BE(const void *buf) (static_cast<uint16_t>(reinterpret_cast<const uint8_t*>(buf)[1]) << 0); } +void VDP::renderScrollBLine(const size_t line_index, const size_t hcell_count) +{ + const uint8_t scroll_reg = _reg[static_cast<size_t>(RegID::kScrollBAddress)]; + const uint16_t scroll_addr = SCROLLB_ADDR_GET(scroll_reg); + const size_t cy = line_index / kCellHeightPixels; + const size_t y = line_index % kCellHeightPixels; + for (size_t cx = 0; cx < hcell_count; cx++) { + if (cx * kCellWidthPixels >= kRenderWidth) { + break; + } + const uint16_t cell_id = GetU16BE( + _vram + scroll_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); + const uint32_t val = GetU32BE( + _vram + (cell_id * kCellHeightPixels + y) * (kCellWidthPixels / kPixelsPerByte)); + for (size_t x = 0; x < kCellWidthPixels; x++) { + if (cx * kCellWidthPixels + x >= kRenderWidth) { + continue; + } + const size_t color_index = (val >> ((kCellWidthPixels - 1 - x) * 4)) & 0xf; + const uint16_t bg_color = _reg[static_cast<size_t>(RegID::kBackgroundColor)] & 0xf; + const uint16_t bg_palette = + (_reg[static_cast<size_t>(RegID::kBackgroundColor)] & 0x30) >> 4; + // TODO compare current palette too + (void) bg_palette; + if (color_index == bg_color) { + // Do not render anything - background color means transparency + continue; + } + 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) + cx * kCellWidthPixels + x; + _rendered_buffer[render_offset] = color; + } + } +} + void VDP::renderScrollALine(const size_t line_index, const size_t hcell_count) { - const uint8_t scrolla_reg = _reg[static_cast<size_t>(RegID::kScrollAAddress)]; - const uint16_t scrolla_addr = SCROLLA_ADDR_GET(scrolla_reg); + const uint8_t scroll_reg = _reg[static_cast<size_t>(RegID::kScrollAAddress)]; + const uint16_t scroll_addr = SCROLLA_ADDR_GET(scroll_reg); const size_t cy = line_index / kCellHeightPixels; const size_t y = line_index % kCellHeightPixels; for (size_t cx = 0; cx < hcell_count; cx++) { @@ -212,7 +257,7 @@ void VDP::renderScrollALine(const size_t line_index, const size_t hcell_count) break; } const uint16_t cell_id = GetU16BE( - _vram + scrolla_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); + _vram + scroll_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); const uint32_t val = GetU32BE( _vram + (cell_id * kCellHeightPixels + y) * (kCellWidthPixels / kPixelsPerByte)); for (size_t x = 0; x < kCellWidthPixels; x++) { @@ -220,6 +265,15 @@ void VDP::renderScrollALine(const size_t line_index, const size_t hcell_count) continue; } const size_t color_index = (val >> ((kCellWidthPixels - 1 - x) * 4)) & 0xf; + const uint16_t bg_color = _reg[static_cast<size_t>(RegID::kBackgroundColor)] & 0xf; + const uint16_t bg_palette = + (_reg[static_cast<size_t>(RegID::kBackgroundColor)] & 0x30) >> 4; + // TODO compare current palette too + (void) bg_palette; + if (color_index == bg_color) { + // Do not render anything - background color means transparency + continue; + } const uint16_t cram_color = GetU16BE(_cram + color_index * sizeof(uint16_t)); const uint32_t color = RenderColorFromCRAM(cram_color); const size_t render_offset = @@ -236,6 +290,7 @@ bool VDP::Scanline() return true; } const uint16_t lines_per_screen = _status.pal_mode ? kLinesPerScreenPAL : kLinesPerScreenNTSC; + memset(_rendered_buffer + kRenderWidth * _lines_counter, 0, kRenderWidth); if (_lines_counter >= (int)kRenderHeight) { // just render palette for (size_t i = 0; i < kRenderWidth; i++) { @@ -252,6 +307,7 @@ 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); } } @@ -72,6 +72,7 @@ class VDP { }; void renderScrollALine(size_t line_index, size_t hcell_count); + void renderScrollBLine(size_t line_index, size_t hcell_count); void writeData(uint8_t address_mode, uint16_t address, uint16_t value); void writeControl(uint16_t value); uint16_t readData(uint8_t address_mode, uint16_t address); |