summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-05-07 12:14:47 +0300
committerOxore <oxore@protonmail.com>2023-05-07 12:14:47 +0300
commitbce8c2f19a564f17d41fa0a3fb935b0181cad147 (patch)
tree8806bd5e0f6d1f6c3b5298c9e58d745471df12a4
parentfcdecd37a2fb59ab534bc02f2b3744e83aff22ec (diff)
Refactor overall scroll rendering
-rw-r--r--vdp.cpp158
-rw-r--r--vdp.hpp6
2 files changed, 73 insertions, 91 deletions
diff --git a/vdp.cpp b/vdp.cpp
index 395237f..d8ca026 100644
--- a/vdp.cpp
+++ b/vdp.cpp
@@ -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()
diff --git a/vdp.hpp b/vdp.hpp
index e5b81d1..2a99ebc 100644
--- a/vdp.hpp
+++ b/vdp.hpp
@@ -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);