added pattern table viewer

This commit is contained in:
Lauchmelder 2022-03-04 14:16:41 +01:00
parent aef80e42fb
commit 9856e730fd
No known key found for this signature in database
GPG key ID: C2403C69D78F011D
11 changed files with 157 additions and 37 deletions

View file

@ -164,6 +164,8 @@ void Bus::WriteCPU(Word addr, Byte val)
{ {
if (0x0000 <= addr && addr < 0x2000) if (0x0000 <= addr && addr < 0x2000)
{ {
if (addr == 0x0348)
volatile int jdfkdf = 3;
RAM[addr & 0x7FF] = val; RAM[addr & 0x7FF] = val;
} }
else if (0x2000 <= addr && addr < 0x4000) else if (0x2000 <= addr && addr < 0x4000)

View file

@ -13,7 +13,7 @@ add_executable(nesemu
"debugger/PPUWatcher.cpp" "debugger/PPUWatcher.cpp"
"debugger/Disassembler.cpp" "debugger/Disassembler.cpp"
"debugger/MemoryViewer.cpp" "debugger/MemoryViewer.cpp"
"debugger/NametableViewer.cpp" "ControllerPort.cpp" "controllers/StandardController.cpp" "gfx/Input.cpp" "debugger/ControllerPortViewer.cpp" "gfx/Screen.cpp" "debugger/Palettes.cpp" "APU.cpp") "debugger/NametableViewer.cpp" "ControllerPort.cpp" "controllers/StandardController.cpp" "gfx/Input.cpp" "debugger/ControllerPortViewer.cpp" "gfx/Screen.cpp" "debugger/Palettes.cpp" "APU.cpp" "debugger/PatternTableViewer.cpp")
target_include_directories(nesemu PRIVATE target_include_directories(nesemu PRIVATE
mappers mappers

View file

@ -6,6 +6,7 @@
class Mapper class Mapper
{ {
friend class Disassembler; friend class Disassembler;
friend class PatternTableViewer;
public: public:
virtual Byte ReadCPU(Word addr) = 0; virtual Byte ReadCPU(Word addr) = 0;

View file

@ -184,7 +184,10 @@ void PPU::Tick()
volatile int dfjk = 3; volatile int dfjk = 3;
screen->SetPixel(x, y, colorTable[colorVal]); screen->SetPixel(x, y, colorTable[colorVal]);
}
if (cycleType == CycleType::Fetching || cycleType == CycleType::PreFetching)
{
loTile.Raw <<= 1; loTile.Raw <<= 1;
hiTile.Raw <<= 1; hiTile.Raw <<= 1;
loAttribute.Raw <<= 1; loAttribute.Raw <<= 1;

View file

@ -10,6 +10,7 @@
#include "Disassembler.hpp" #include "Disassembler.hpp"
#include "MemoryViewer.hpp" #include "MemoryViewer.hpp"
#include "NametableViewer.hpp" #include "NametableViewer.hpp"
#include "PatternTableViewer.hpp"
#include "ControllerPortViewer.hpp" #include "ControllerPortViewer.hpp"
#include "Palettes.hpp" #include "Palettes.hpp"
@ -26,6 +27,7 @@ Debugger::Debugger(Bus* bus) :
windows.push_back(new MemoryViewer(this, bus)); windows.push_back(new MemoryViewer(this, bus));
windows.push_back(new NametableViewer(this, bus)); windows.push_back(new NametableViewer(this, bus));
windows.push_back(new PatternTableViewer(this, bus->cartridge.GetMapper()));
windows.push_back(new ControllerPortViewer(this, &bus->controllerPort)); windows.push_back(new ControllerPortViewer(this, &bus->controllerPort));
windows.push_back(new Palettes(this, bus)); windows.push_back(new Palettes(this, bus));
} }

View file

@ -68,8 +68,6 @@ void NametableViewer::OnRender()
return; return;
} }
float smallerSize = std::min(ImGui::GetWindowWidth(), ImGui::GetWindowHeight()) - 20.0f; float smallerSize = std::min(ImGui::GetWindowWidth(), ImGui::GetWindowHeight()) - 20.0f;
if (smallerSize < 40.0f) if (smallerSize < 40.0f)
smallerSize = 40.0f; smallerSize = 40.0f;

View file

@ -10,28 +10,22 @@
Palettes::Palettes(Debugger* debugger, Bus* bus) : Palettes::Palettes(Debugger* debugger, Bus* bus) :
DebugWindow("Palettes", debugger), bus(bus) DebugWindow("Palettes", debugger), bus(bus)
{ {
glCreateTextures(GL_TEXTURE_2D, 4, backgroundPalettes.data()); glCreateTextures(GL_TEXTURE_2D, 1, &backgroundPalettes);
glCreateTextures(GL_TEXTURE_2D, 4, spritePalettes.data()); glCreateTextures(GL_TEXTURE_2D, 1, &spritePalettes);
for (GLuint texture : backgroundPalettes) glTextureStorage2D(backgroundPalettes, 1, GL_RGB8, 4, 4);
{ glTextureParameteri(backgroundPalettes, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureStorage2D(texture, 1, GL_RGB8, 4, 1); glTextureParameteri(backgroundPalettes, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
for (GLuint texture : spritePalettes) glTextureStorage2D(spritePalettes, 1, GL_RGB8, 4, 4);
{ glTextureParameteri(spritePalettes, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureStorage2D(texture, 1, GL_RGB8, 4, 1); glTextureParameteri(spritePalettes, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
} }
Palettes::~Palettes() Palettes::~Palettes()
{ {
glDeleteTextures(4, spritePalettes.data()); glDeleteTextures(1, &spritePalettes);
glDeleteTextures(4, backgroundPalettes.data()); glDeleteTextures(1, &backgroundPalettes);
} }
void Palettes::OnRender() void Palettes::OnRender()
@ -43,8 +37,9 @@ void Palettes::OnRender()
return; return;
} }
Color palette[4]; Color palette[4 * 4];
palette[0] = PPU::colorTable[bus->palettes[0]];
ImVec2 size = ImGui::GetWindowSize(); ImVec2 size = ImGui::GetWindowSize();
size.x /= 2; size.x /= 2;
size.y = size.x / 4; size.y = size.x / 4;
@ -52,26 +47,32 @@ void Palettes::OnRender()
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
palette[1] = PPU::colorTable[bus->palettes[i * 4 + 1]]; palette[4 * i + 0] = PPU::colorTable[bus->palettes[0]];
palette[2] = PPU::colorTable[bus->palettes[i * 4 + 2]]; palette[4 * i + 1] = PPU::colorTable[bus->palettes[i * 4 + 1]];
palette[3] = PPU::colorTable[bus->palettes[i * 4 + 3]]; palette[4 * i + 2] = PPU::colorTable[bus->palettes[i * 4 + 2]];
palette[4 * i + 3] = PPU::colorTable[bus->palettes[i * 4 + 3]];
glTextureSubImage2D(backgroundPalettes[i], 0, 0, 0, 4, 1, GL_RGB, GL_UNSIGNED_BYTE, (const void*)palette);
ImGui::Image((ImTextureID)backgroundPalettes[i], size);
} }
glTextureSubImage2D(backgroundPalettes, 0, 0, 0, 4, 4, GL_RGB, GL_UNSIGNED_BYTE, (const void*)palette);
for(float i = 0; i < 1.0f; i += 0.25f)
ImGui::Image((ImTextureID)backgroundPalettes, size, ImVec2(0, i), ImVec2(1, i + 0.25f));
} }
if (ImGui::CollapsingHeader("Sprites")) if (ImGui::CollapsingHeader("Sprites"))
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
palette[1] = PPU::colorTable[bus->palettes[0x10 + i * 4 + 1]]; palette[4 * i + 0] = PPU::colorTable[bus->palettes[0]];
palette[2] = PPU::colorTable[bus->palettes[0x10 + i * 4 + 2]]; palette[4 * i + 1] = PPU::colorTable[bus->palettes[0x10 + i * 4 + 1]];
palette[3] = PPU::colorTable[bus->palettes[0x10 + i * 4 + 3]]; palette[4 * i + 2] = PPU::colorTable[bus->palettes[0x10 + i * 4 + 2]];
palette[4 * i + 3] = PPU::colorTable[bus->palettes[0x10 + i * 4 + 3]];
glTextureSubImage2D(spritePalettes[i], 0, 0, 0, 4, 1, GL_RGB, GL_UNSIGNED_BYTE, (const void*)palette);
ImGui::Image((ImTextureID)spritePalettes[i], size);
} }
glTextureSubImage2D(spritePalettes, 0, 0, 0, 4, 4, GL_RGB, GL_UNSIGNED_BYTE, (const void*)palette);
for (float i = 0; i < 1.0f; i += 0.25f)
ImGui::Image((ImTextureID)spritePalettes, size, ImVec2(0, i), ImVec2(1, i + 0.25f));
} }
ImGui::End(); ImGui::End();

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <array>
#include "DebugWindow.hpp" #include "DebugWindow.hpp"
class Bus; class Bus;
@ -17,6 +16,6 @@ public:
private: private:
Bus* bus; Bus* bus;
std::array<uint32_t, 4> backgroundPalettes; uint32_t backgroundPalettes;
std::array<uint32_t, 4> spritePalettes; uint32_t spritePalettes;
}; };

View file

@ -0,0 +1,90 @@
#include "PatternTableViewer.hpp"
#include <glad/glad.h>
#include <imgui/imgui.h>
#include "Mapper000.hpp"
PatternTableViewer::PatternTableViewer(Debugger* debugger, Mapper* mapper) :
DebugWindow("Pattern Table Viewer", debugger), mapper(mapper)
{
glCreateTextures(GL_TEXTURE_2D, 1, &texture);
glTextureStorage2D(texture, 1, GL_RGB8, 128 * 2, 128);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
std::vector<Color> pixels(128 * 128);
for (int i = 0; i < 2; i++)
{
DecodePatternTable(i, pixels);
glTextureSubImage2D(texture, 0, 128 * i, 0, 128, 128, GL_RGB, GL_UNSIGNED_BYTE, (const void*)pixels.data());
}
}
PatternTableViewer::~PatternTableViewer()
{
glDeleteTextures(1, &texture);
}
void PatternTableViewer::OnRender()
{
if (!ImGui::Begin("Pattern Table Viewer", &isOpen))
{
ImGui::End();
return;
}
float smallerSize = std::min(ImGui::GetWindowWidth(), ImGui::GetWindowHeight()) - 20.0f;
if (smallerSize < 40.0f)
smallerSize = 40.0f;
if (ImGui::BeginTabBar("pattern_tables"))
{
if (ImGui::BeginTabItem("Table 1"))
{
ImGui::Image((ImTextureID)texture, ImVec2(smallerSize, smallerSize - 40.0f), ImVec2(0.0f, 0.0f), ImVec2(0.5f, 1.0f));
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Table 2"))
{
ImGui::Image((ImTextureID)texture, ImVec2(smallerSize, smallerSize - 40.0f), ImVec2(0.5f, 0.0f), ImVec2(1.0f, 1.0f));
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::End();
}
void PatternTableViewer::DecodePatternTable(int index, std::vector<Color>& buffer)
{
// uint8_t stride = 128;
Word baseAddr = 0x1000 * index;
for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
Word tileAddress = baseAddr + (16 * 16 * y) + (16 * x);
for(int l = 0; l < 8; l++)
{
uint8_t loColor = mapper->CHR_ROM[tileAddress + l];
uint8_t hiColor = mapper->CHR_ROM[tileAddress + 8 + l];
for (int k = 0; k < 8; k++)
{
uint8_t color = ((loColor & 0x80) >> 7) | ((hiColor & 0x80) >> 6);
color *= 80;
buffer[(y * 8 + l) * 128 + (x * 8 + k)] = Color{ color, color, color };
loColor <<= 1;
hiColor <<= 1;
}
}
}
}
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <vector>
#include "DebugWindow.hpp"
#include "../Types.hpp"
class Mapper;
class PatternTableViewer :
public DebugWindow
{
public:
PatternTableViewer(Debugger* debugger, Mapper* mapper);
~PatternTableViewer();
virtual void OnRender() override;
private:
void DecodePatternTable(int index, std::vector<Color>& buffer);
private:
Mapper* mapper;
uint32_t texture;
};

View file

@ -21,7 +21,7 @@ Byte Mapper000::ReadCPU(Word addr)
{ {
if (0x8000 <= addr && addr <= 0xFFFF) if (0x8000 <= addr && addr <= 0xFFFF)
{ {
return PRG_ROM[addr & (prgBanks * 0x4000 - 1)]; return PRG_ROM[addr & (0x4000 * prgBanks - 1)];
} }
return 0x00; return 0x00;