diff options
author | Oxore <oxore@protonmail.com> | 2023-05-07 12:14:47 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-05-07 12:14:47 +0300 |
commit | bce8c2f19a564f17d41fa0a3fb935b0181cad147 (patch) | |
tree | 8806bd5e0f6d1f6c3b5298c9e58d745471df12a4 | |
parent | fcdecd37a2fb59ab534bc02f2b3744e83aff22ec (diff) |
Refactor overall scroll rendering
-rw-r--r-- | vdp.cpp | 158 | ||||
-rw-r--r-- | vdp.hpp | 6 |
2 files changed, 73 insertions, 91 deletions
@@ -9,41 +9,33 @@ #include <cstring> #include <cstdio> +#define REG_VAL_GET(reg, mask, shift) (((reg) & ((mask) << (shift))) >> (shift)) +#define REG_VAL_SET(reg, mask, shift, v) \ + ((reg) = ((reg) & ~((mask) << (shift))) | ((v & (mask)) << (shift))) + /// DISP: Enable (1) / Disable (0) Display #define MODESET2_DISP_MASK (1) #define MODESET2_DISP_SHIFT (6) -#define MODESET2_DISP_GET(reg) \ - (((reg) & (MODESET2_DISP_MASK << MODESET2_DISP_SHIFT)) >> MODESET2_DISP_SHIFT) -#define MODESET2_DISP_SET(reg, v) \ - ((reg) = ((reg) & ~(MODESET2_DISP_MASK << MODESET2_DISP_SHIFT)) \ - | ((v & MODESET2_DISP_MASK) << MODESET2_DISP_SHIFT)) +#define MODESET2_DISP_GET(reg) REG_VAL_GET(reg, MODESET2_DISP_MASK, MODESET2_DISP_SHIFT) +#define MODESET2_DISP_SET(reg, v) REG_VAL_SET(reg, MODESET2_DISP_MASK, MODESET2_DISP_SHIFT, v) /// IE0: Enable (1) / Disable (0) V interrupt (IRQ 6) #define MODESET2_IE0_MASK (1) #define MODESET2_IE0_SHIFT (5) -#define MODESET2_IE0_GET(reg) \ - (((reg) & (MODESET2_IE0_MASK << MODESET2_IE0_SHIFT)) >> MODESET2_IE0_SHIFT) -#define MODESET2_IE0_SET(reg, v) \ - ((reg) = ((reg) & ~(MODESET2_IE0_MASK << MODESET2_IE0_SHIFT)) \ - | ((v & MODESET2_IE0_MASK) << MODESET2_IE0_SHIFT)) +#define MODESET2_IE0_GET(reg) REG_VAL_GET(reg, MODESET2_IE0_MASK, MODESET2_IE0_SHIFT) +#define MODESET2_IE0_SET(reg, v) REG_VAL_SET(reg, MODESET2_IE0_MASK, MODESET2_IE0_SHIFT, v) /// M1: Enable (1) / Disable (0) DMA #define MODESET2_M1_MASK (1) #define MODESET2_M1_SHIFT (4) -#define MODESET2_M1_GET(reg) \ - (((reg) & (MODESET2_M1_MASK << MODESET2_M1_SHIFT)) >> MODESET2_M1_SHIFT) -#define MODESET2_M1_SET(reg, v) \ - ((reg) = ((reg) & ~(MODESET2_M1_MASK << MODESET2_M1_SHIFT)) \ - | ((v & MODESET2_M1_MASK) << MODESET2_M1_SHIFT)) +#define MODESET2_M1_GET(reg) REG_VAL_GET(reg, MODESET2_M1_MASK, MODESET2_M1_SHIFT) +#define MODESET2_M1_SET(reg, v) REG_VAL_SET(reg, MODESET2_M1_MASK, MODESET2_M1_SHIFT, v) /// M2: V 30 (1) / V 28 (0) cell mode (PAL mode, always 0 in NTSC mdoe) #define MODESET2_M2_MASK (1) #define MODESET2_M2_SHIFT (3) -#define MODESET2_M2_GET(reg) \ - (((reg) & (MODESET2_M2_MASK << MODESET2_M2_SHIFT)) >> MODESET2_M2_SHIFT) -#define MODESET2_M2_SET(reg, v) \ - ((reg) = ((reg) & ~(MODESET2_M2_MASK << MODESET2_M2_SHIFT)) \ - | ((v & MODESET2_M2_MASK) << MODESET2_M2_SHIFT)) +#define MODESET2_M2_GET(reg) REG_VAL_GET(reg, MODESET2_M2_MASK, MODESET2_M2_SHIFT) +#define MODESET2_M2_SET(reg, v) REG_VAL_SET(reg, MODESET2_M2_MASK, MODESET2_M2_SHIFT, v) #define SCROLLA_ADDR_MASK (0x38) #define SCROLLA_ADDR_SHIFT (10) @@ -72,32 +64,43 @@ // 0: V32 CELL, 1: V64 CELL, 2: Prohibited, 3: V128 CELL #define SCROLLSIZE_VCELL_MASK (3) #define SCROLLSIZE_VCELL_SHIFT (4) -#define SCROLLSIZE_VCELL_GET(reg) \ - (((reg) & (SCROLLSIZE_VCELL_MASK << SCROLLSIZE_VCELL_SHIFT)) >> SCROLLSIZE_VCELL_SHIFT) -#define SCROLLSIZE_VCELL_SET(reg, v) \ - ((reg) = ((reg) & ~(SCROLLSIZE_VCELL_MASK << SCROLLSIZE_VCELL_SHIFT)) \ - | ((v & SCROLLSIZE_VCELL_MASK) << SCROLLSIZE_VCELL_SHIFT)) +#define SCROLLSIZE_VCELL_GET(reg) REG_VAL_GET(reg, SCROLLSIZE_VCELL_MASK, SCROLLSIZE_VCELL_SHIFT) +#define SCROLLSIZE_VCELL_SET(reg, v) REG_VAL_SET(reg, SCROLLSIZE_VCELL_MASK, SCROLLSIZE_VCELL_SHIFT, v) // 0: H32 CELL, 1: H64 CELL, 2: Prohibited, 3: H128 CELL #define SCROLLSIZE_HCELL_MASK (3) #define SCROLLSIZE_HCELL_SHIFT (0) -#define SCROLLSIZE_HCELL_GET(reg) \ - (((reg) & (SCROLLSIZE_HCELL_MASK << SCROLLSIZE_HCELL_SHIFT)) >> SCROLLSIZE_HCELL_SHIFT) -#define SCROLLSIZE_HCELL_SET(reg, v) \ - ((reg) = ((reg) & ~(SCROLLSIZE_HCELL_MASK << SCROLLSIZE_HCELL_SHIFT)) \ - | ((v & SCROLLSIZE_HCELL_MASK) << SCROLLSIZE_HCELL_SHIFT)) +#define SCROLLSIZE_HCELL_GET(reg) REG_VAL_GET(reg, SCROLLSIZE_HCELL_MASK, SCROLLSIZE_HCELL_SHIFT) +#define SCROLLSIZE_HCELL_SET(reg, v) REG_VAL_SET(reg, SCROLLSIZE_HCELL_MASK, SCROLLSIZE_HCELL_SHIFT, v) + +#define BGCOLOR_COLOR_MASK (3) +#define BGCOLOR_COLOR_SHIFT (0) +#define BGCOLOR_COLOR_GET(reg) REG_VAL_GET(reg, BGCOLOR_COLOR_MASK, BGCOLOR_COLOR_SHIFT) +#define BGCOLOR_COLOR_SET(reg, v) REG_VAL_SET(reg, BGCOLOR_COLOR_MASK, BGCOLOR_COLOR_SHIFT, v) + +#define BGCOLOR_PALETTE_MASK (3) +#define BGCOLOR_PALETTE_SHIFT (4) +#define BGCOLOR_PALETTE_GET(reg) REG_VAL_GET(reg, BGCOLOR_PALETTE_MASK, BGCOLOR_PALETTE_SHIFT) +#define BGCOLOR_PALETTE_SET(reg, v) REG_VAL_SET(reg, BGCOLOR_PALETTE_MASK, BGCOLOR_PALETTE_SHIFT, v) #define DMASRCADRHIGH_DMD_MASK (3) #define DMASRCADRHIGH_DMD_SHIFT (6) -#define DMASRCADRHIGH_DMD_GET(reg) \ - (((reg) & (DMASRCADRHIGH_DMD_MASK << DMASRCADRHIGH_DMD_SHIFT)) >> DMASRCADRHIGH_DMD_SHIFT) -#define DMASRCADRHIGH_DMD_SET(reg, v) \ - ((reg) = ((reg) & ~(DMASRCADRHIGH_DMD_MASK << DMASRCADRHIGH_DMD_SHIFT)) \ - | ((v & DMASRCADRHIGH_DMD_MASK) << DMASRCADRHIGH_DMD_SHIFT)) +#define DMASRCADRHIGH_DMD_GET(reg) REG_VAL_GET(reg, DMASRCADRHIGH_DMD_MASK, DMASRCADRHIGH_DMD_SHIFT) +#define DMASRCADRHIGH_DMD_SET(reg, v) REG_VAL_SET(reg, DMASRCADRHIGH_DMD_MASK, DMASRCADRHIGH_DMD_SHIFT, v) + +static constexpr size_t BitsCountToMask(const size_t bits) +{ + return bits ? ((1 << bits) | BitsCountToMask(bits - 1)) : 0; +} static constexpr size_t kCellWidthPixels = 8; 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); +// Each pixel has 4 bit depth color +static constexpr uint16_t kPixelColorMask = BitsCountToMask(kBitsPerPixel); uint32_t VDP::Read(const uint32_t offset, const enum bitness bitness) { @@ -217,37 +220,37 @@ 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) +void VDP::renderScrollLine( + const size_t line_index, + const uint16_t plane_addr, + const uint16_t hscroll_table_addr, + const size_t plane_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 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; for (size_t cx = 0; cx < hcell_count; cx++) { - if (cx * kCellWidthPixels >= kRenderWidth) { - break; - } const uint16_t sprite_id = GetU16BE( - _vram + scroll_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); + _vram + plane_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); + // Fetch whole 8 pixel (32 bit) line of sprite const uint32_t val = GetU32BE( _vram + (sprite_id * kCellHeightPixels + y) * (kCellWidthPixels / kPixelsPerByte)); - const size_t hscroll_table_addr_reg = - _reg[static_cast<size_t>(RegID::kHScrollTableAddress)]; - const size_t hscroll_table_addr = HSCROLL_TABLE_ADDR_GET(hscroll_table_addr_reg); - const size_t hscroll = GetU16BE(_vram + hscroll_table_addr + sizeof(uint16_t) * 1) & 0x3ff; for (size_t x = 0; x < kCellWidthPixels; x++) { const size_t render_offset_x = (cx * kCellWidthPixels + x + hscroll) % (hcell_count * kCellWidthPixels); if (render_offset_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; + const size_t color_index = + (val >> ((kCellWidthPixels - 1 - x) * kBitsPerPixel)) & kPixelColorMask; + const uint16_t bgcolor_reg = _reg[static_cast<size_t>(RegID::kBackgroundColor)]; + const uint16_t bgcolor_color = BGCOLOR_COLOR_GET(bgcolor_reg); + const uint16_t bgcolor_palette = BGCOLOR_PALETTE_GET(bgcolor_reg); // TODO compare current palette too - (void) bg_palette; - if (color_index == bg_color) { + (void) bgcolor_palette; + if (color_index == bgcolor_color) { // Do not render anything - background color means transparency continue; } @@ -260,47 +263,20 @@ 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 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); +} + void VDP::renderScrollALine(const size_t line_index, const size_t hcell_count) { - 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++) { - if (cx * kCellWidthPixels >= kRenderWidth) { - break; - } - const uint16_t sprite_id = GetU16BE( - _vram + scroll_addr + (cy * hcell_count + cx) * sizeof(uint16_t)); - const uint32_t val = GetU32BE( - _vram + (sprite_id * kCellHeightPixels + y) * (kCellWidthPixels / kPixelsPerByte)); - const size_t hscroll_table_addr_reg = - _reg[static_cast<size_t>(RegID::kHScrollTableAddress)]; - const size_t hscroll_table_addr = HSCROLL_TABLE_ADDR_GET(hscroll_table_addr_reg); - const size_t hscroll = GetU16BE(_vram + hscroll_table_addr + sizeof(uint16_t) * 0) & 0x3ff; - for (size_t x = 0; x < kCellWidthPixels; x++) { - const size_t render_offset_x = (cx * kCellWidthPixels + x + hscroll) % - (hcell_count * kCellWidthPixels); - if (render_offset_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) + render_offset_x; - _rendered_buffer[render_offset] = color; - } - } + 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); } bool VDP::Scanline() @@ -71,6 +71,12 @@ class VDP { kRegistersCount, ///< Keep it last }; + void renderScrollLine( + size_t line_index, + uint16_t plane_addr, + uint16_t hscroll_table_addr, + size_t plane_index, + size_t hcell_count); 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); |