22 std::span<const uint8_t> bytes,
int destination_word,
int bg_base_word) {
23 if (bg_base_word < 0 || bg_base_word > 0x4000 || destination_word < 0 ||
24 destination_word > 0x7FFF) {
25 return absl::InvalidArgumentError(
"Preview VRAM word address out of range");
27 const int offset = (destination_word - bg_base_word) * 2;
28 if (offset < 0 || offset % 32 != 0 || bytes.empty() ||
29 bytes.size() % 32 != 0 || bytes.size() > 0x8000 ||
30 static_cast<size_t>(offset) + bytes.size() > 0x8000 ||
31 destination_word * 2 + bytes.size() > 0x10000) {
32 return absl::InvalidArgumentError(
33 "Preview DMA must contain aligned 4bpp BG characters within VRAM");
36 for (
size_t tile = 0; tile < bytes.size() / 32; ++tile) {
38 for (
int y = 0; y < 8; ++y) {
39 for (
int x = 0; x < 8; ++x) {
40 for (
int plane = 0; plane < 4; ++plane) {
42 tile * 32 + (plane / 2) * 16 + y * 2 + plane % 2;
43 pixels[y * 8 + x] |= ((bytes[source] >> (7 - x)) & 1) << plane;
47 result.emplace(
static_cast<uint16_t
>(offset / 32 + tile), pixels);