Skip to content

Commit

Permalink
gba: add graphics viewer support (ares-emulator#1626)
Browse files Browse the repository at this point in the history
Adds GBA support to the ares graphics viewer. Supports viewing VRAM
contents as Mode 3/4/5 bitmaps, or as 4bpp/8bpp tiles.
  • Loading branch information
png183 authored Aug 25, 2024
1 parent 3cd82c8 commit efb7f61
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 1 deletion.
130 changes: 130 additions & 0 deletions ares/gba/ppu/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,134 @@ auto PPU::Debugger::load(Node::Object parent) -> void {
memory.pram->setWrite([&](u32 address, u8 data) -> void {
ppu.pram[address >> 1].byte(address & 1) = data;
});

graphics.tiles4bpp = parent->append<Node::Debugger::Graphics>("4 BPP Tiles");
graphics.tiles4bpp->setSize(512, 384);
graphics.tiles4bpp->setCapture([&]() -> vector<u32> {
vector<u32> output;
output.resize(512 * 384);
for(u32 tileY : range(48)) {
for(u32 tileX : range(64)) {
n32 address = tileY * 64 + tileX << 5;
for(u32 y : range(8)) {
for(u32 x : range(4)) {
n8 colors = ppu.vram[address + y * 4 + x];
n4 leftPixel = colors & 0xf;
n4 rightPixel = colors >> 4;
output[(tileY * 8 + y) * 512 + (tileX * 8 + (x << 1))] = leftPixel * 0x111111;
output[(tileY * 8 + y) * 512 + (tileX * 8 + (x << 1)) + 1] = rightPixel * 0x111111;
}
}
}
}
return output;
});

graphics.tiles8bpp = parent->append<Node::Debugger::Graphics>("8 BPP Tiles");
graphics.tiles8bpp->setSize(256, 384);
graphics.tiles8bpp->setCapture([&]() -> vector<u32> {
vector<u32> output;
output.resize(256 * 384);
for(u32 tileY : range(48)) {
for(u32 tileX : range(32)) {
n32 address = tileY * 32 + tileX << 6;
for(u32 y : range(8)) {
for(u32 x : range(8)) {
n9 color = ppu.vram[address + y * 8 + x];
if(tileY >= 32) color += 0x100; //bottom 1/3 of tile viewer uses OBJ palettes
n15 pixel = ppu.pram[color];
n8 r = pixel >> 0 & 31; r = r << 3 | r >> 2;
n8 g = pixel >> 5 & 31; g = g << 3 | g >> 2;
n8 b = pixel >> 10 & 31; b = b << 3 | b >> 2;
n8 a = 255;
output[(tileY * 8 + y) * 256 + (tileX * 8 + x)] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
}
}
return output;
});

graphics.mode3 = parent->append<Node::Debugger::Graphics>("Mode 3");
graphics.mode3->setSize(240, 160);
graphics.mode3->setCapture([&]() -> vector<u32> {
vector<u32> output;
output.resize(240 * 160);
for(u32 y : range(160)) {
for(u32 x : range(240)) {
n15 pixel = ppu.vram[y * 480 + x * 2 + 1] << 8 | ppu.vram[y * 480 + x * 2] << 0;
n8 r = pixel >> 0 & 31; r = r << 3 | r >> 2;
n8 g = pixel >> 5 & 31; g = g << 3 | g >> 2;
n8 b = pixel >> 10 & 31; b = b << 3 | b >> 2;
n8 a = 255;
output[y * 240 + x] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
return output;
});

graphics.mode4 = parent->append<Node::Debugger::Graphics>("Mode 4");
graphics.mode4->setSize(240, 320);
graphics.mode4->setCapture([&]() -> vector<u32> {
vector<u32> output;
output.resize(240 * 320);
for(u32 y : range(160)) {
for(u32 x : range(240)) {
n8 color = ppu.vram[y * 240 + x];
n15 pixel = ppu.pram[color];
n8 r = pixel >> 0 & 31; r = r << 3 | r >> 2;
n8 g = pixel >> 5 & 31; g = g << 3 | g >> 2;
n8 b = pixel >> 10 & 31; b = b << 3 | b >> 2;
n8 a = 255;
output[y * 240 + x] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
for(u32 y : range(160)) {
for(u32 x : range(240)) {
n8 color = ppu.vram[0xa000 + y * 240 + x];
n15 pixel = ppu.pram[color];
n8 r = pixel >> 0 & 31; r = r << 3 | r >> 2;
n8 g = pixel >> 5 & 31; g = g << 3 | g >> 2;
n8 b = pixel >> 10 & 31; b = b << 3 | b >> 2;
n8 a = 255;
output[(y + 160) * 240 + x] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
return output;
});

graphics.mode5 = parent->append<Node::Debugger::Graphics>("Mode 5");
graphics.mode5->setSize(160, 256);
graphics.mode5->setCapture([&]() -> vector<u32> {
vector<u32> output;
output.resize(160 * 256);
for(u32 y : range(256)) {
for(u32 x : range(160)) {
n15 pixel = ppu.vram[y * 320 + x * 2 + 1] << 8 | ppu.vram[y * 320 + x * 2] << 0;
n8 r = pixel >> 0 & 31; r = r << 3 | r >> 2;
n8 g = pixel >> 5 & 31; g = g << 3 | g >> 2;
n8 b = pixel >> 10 & 31; b = b << 3 | b >> 2;
n8 a = 255;
output[y * 160 + x] = a << 24 | r << 16 | g << 8 | b << 0;
}
}
return output;
});
}

auto PPU::Debugger::unload(Node::Object parent) -> void {
parent->remove(memory.vram);
parent->remove(memory.pram);
parent->remove(graphics.tiles4bpp);
parent->remove(graphics.tiles8bpp);
parent->remove(graphics.mode3);
parent->remove(graphics.mode4);
parent->remove(graphics.mode5);
memory.vram.reset();
memory.pram.reset();
graphics.tiles4bpp.reset();
graphics.tiles8bpp.reset();
graphics.mode3.reset();
graphics.mode4.reset();
graphics.mode5.reset();
}
2 changes: 1 addition & 1 deletion ares/gba/ppu/ppu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ auto PPU::load(Node::Object parent) -> void {
}

auto PPU::unload() -> void {
debugger = {};
debugger.unload(node);
colorEmulation.reset();
interframeBlending.reset();
rotation.reset();
Expand Down
9 changes: 9 additions & 0 deletions ares/gba/ppu/ppu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,20 @@ struct PPU : Thread, IO {
struct Debugger {
//debugger.cpp
auto load(Node::Object) -> void;
auto unload(Node::Object) -> void;

struct Memory {
Node::Debugger::Memory vram;
Node::Debugger::Memory pram;
} memory;

struct Graphics {
Node::Debugger::Graphics tiles4bpp;
Node::Debugger::Graphics tiles8bpp;
Node::Debugger::Graphics mode3;
Node::Debugger::Graphics mode4;
Node::Debugger::Graphics mode5;
} graphics;
} debugger;

//ppu.cpp
Expand Down

0 comments on commit efb7f61

Please sign in to comment.