summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vdp.cpp62
-rw-r--r--vdp.hpp1
2 files changed, 60 insertions, 3 deletions
diff --git a/vdp.cpp b/vdp.cpp
index 7b27a79..735ec13 100644
--- a/vdp.cpp
+++ b/vdp.cpp
@@ -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);
}
}
diff --git a/vdp.hpp b/vdp.hpp
index c239273..e5b81d1 100644
--- a/vdp.hpp
+++ b/vdp.hpp
@@ -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);