summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vdp.cpp69
-rw-r--r--vdp.hpp7
2 files changed, 50 insertions, 26 deletions
diff --git a/vdp.cpp b/vdp.cpp
index d8ca026..f02c398 100644
--- a/vdp.cpp
+++ b/vdp.cpp
@@ -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++;
diff --git a/vdp.hpp b/vdp.hpp
index 2a99ebc..e811422 100644
--- a/vdp.hpp
+++ b/vdp.hpp
@@ -76,9 +76,10 @@ class VDP {
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);
+ size_t hcell_count,
+ size_t vcell_count);
+ void renderScrollALine(size_t line_index, size_t hcell_count, size_t vcell_count);
+ void renderScrollBLine(size_t line_index, size_t hcell_count, size_t vcell_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);