GUI Updates
Add DisplaySettings, replace ImGui style editor Update Debugger interface with memory viewer Decompose SNES initialization routines Update DungeonObjectRenderer plan Add DrawObjectRenderer UI mockup fofr DungeonEditor
This commit is contained in:
@@ -117,6 +117,8 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
constexpr float kYazeVersion = 0.05;
|
||||
|
||||
// ============================================================================
|
||||
// Window Variables
|
||||
// ============================================================================
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/dungeon/object_names.h"
|
||||
#include "app/zelda3/dungeon/room_names.h"
|
||||
#include "zelda3/dungeon/room.h"
|
||||
|
||||
@@ -32,6 +33,7 @@ absl::Status DungeonEditor::Update() {
|
||||
}
|
||||
|
||||
DrawToolset();
|
||||
DrawObjectRenderer();
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginTable("#DungeonEditTable", 3, toolset_table_flags_,
|
||||
@@ -197,9 +199,8 @@ void DungeonEditor::DrawToolset() {
|
||||
ImGui::Button(ICON_MD_PEST_CONTROL_RODENT);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Button("Load Dungeon Objects")) {
|
||||
// object_renderer_.CreateVramFromRoomBlockset();
|
||||
object_renderer_.RenderObjectsAsBitmaps();
|
||||
if (ImGui::Button("Dungeon Object Renderer")) {
|
||||
show_object_render_ = !show_object_render_;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
@@ -229,6 +230,47 @@ void DungeonEditor::DrawTileSelector() {
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonEditor::DrawObjectRenderer() {
|
||||
if (show_object_render_) {
|
||||
ImGui::Begin("Dungeon Object Renderer", &show_object_render_);
|
||||
|
||||
// Create an ImGui table where the left side of the table is a matrix of
|
||||
// buttons which represent each dungeon object. The right side of the table
|
||||
// is a canvas which will display the selected dungeon object. The canvas
|
||||
// will also have a tile selector and a grid overlay.
|
||||
if (ImGui::BeginTable("DungeonObjectEditorTable", 2,
|
||||
ImGuiTableFlags_SizingFixedFit, ImVec2(0, 0))) {
|
||||
ImGui::TableSetupColumn("Dungeon Objects",
|
||||
ImGuiTableColumnFlags_WidthFixed, 150.0f);
|
||||
ImGui::TableSetupColumn("Canvas");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::BeginChild("DungeonObjectButtons", ImVec2(150.0f, 0), true);
|
||||
|
||||
for (const auto each : zelda3::dungeon::Type1RoomObjectNames) {
|
||||
ImGui::Button(each.data());
|
||||
if (ImGui::IsItemClicked()) {
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
// Right side of the table - Canvas
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::BeginChild("DungeonObjectCanvas", ImVec2(0, 0), true);
|
||||
|
||||
// TODO: Insert code to display canvas, tile selector, and grid overlay
|
||||
// here
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -34,8 +34,11 @@ class DungeonEditor : public Editor,
|
||||
void DrawRoomGraphics();
|
||||
void DrawTileSelector();
|
||||
|
||||
void DrawObjectRenderer();
|
||||
|
||||
uint16_t current_room_id_ = 0;
|
||||
bool is_loaded_ = false;
|
||||
bool show_object_render_ = false;
|
||||
|
||||
gfx::Bitmap room_gfx_bmp_;
|
||||
|
||||
@@ -46,9 +49,9 @@ class DungeonEditor : public Editor,
|
||||
|
||||
gui::Canvas canvas_;
|
||||
gui::Canvas room_gfx_canvas_;
|
||||
ImGuiTableFlags toolset_table_flags_ = ImGuiTableFlags_SizingFixedFit |
|
||||
ImGuiTableFlags_Reorderable |
|
||||
ImGuiTableFlags_Resizable;
|
||||
ImGuiTableFlags toolset_table_flags_ =
|
||||
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable |
|
||||
ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "app/gui/widgets.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
@@ -176,12 +177,45 @@ void MasterEditor::DrawInfoPopup() {
|
||||
}
|
||||
|
||||
void MasterEditor::DrawYazeMenu() {
|
||||
static bool show_display_settings = false;
|
||||
static bool show_command_line_interface = false;
|
||||
|
||||
MENU_BAR()
|
||||
DrawFileMenu();
|
||||
DrawEditMenu();
|
||||
DrawViewMenu();
|
||||
DrawHelpMenu();
|
||||
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetStyle().ItemSpacing.x -
|
||||
ImGui::CalcTextSize(ICON_MD_DISPLAY_SETTINGS).x - 150);
|
||||
// Modify the style of the button to have no background color
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(ICON_MD_DISPLAY_SETTINGS)) {
|
||||
show_display_settings = !show_display_settings;
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_MD_TERMINAL)) {
|
||||
show_command_line_interface = !show_command_line_interface;
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::Text(absl::StrCat("yaze v", core::kYazeVersion).c_str());
|
||||
|
||||
END_MENU_BAR()
|
||||
|
||||
if (show_display_settings) {
|
||||
ImGui::Begin("Display Settings", &show_display_settings,
|
||||
ImGuiWindowFlags_None);
|
||||
gui::DrawDisplaySettings();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (show_command_line_interface) {
|
||||
ImGui::Begin("Command Line Interface", &show_command_line_interface,
|
||||
ImGuiWindowFlags_None);
|
||||
ImGui::Text("Enter a command:");
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void MasterEditor::DrawFileMenu() {
|
||||
@@ -266,7 +300,6 @@ void MasterEditor::DrawEditMenu() {
|
||||
|
||||
void MasterEditor::DrawViewMenu() {
|
||||
static bool show_imgui_metrics = false;
|
||||
static bool show_imgui_style_editor = false;
|
||||
static bool show_memory_editor = false;
|
||||
static bool show_asm_editor = false;
|
||||
static bool show_imgui_demo = false;
|
||||
@@ -303,12 +336,6 @@ void MasterEditor::DrawViewMenu() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (show_imgui_style_editor) {
|
||||
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
|
||||
ImGui::ShowStyleEditor();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (show_memory_viewer) {
|
||||
ImGui::Begin("Memory Viewer (ImGui)", &show_memory_viewer);
|
||||
|
||||
@@ -339,13 +366,7 @@ void MasterEditor::DrawViewMenu() {
|
||||
ImGui::MenuItem("Palette Editor", nullptr, &show_palette_editor);
|
||||
ImGui::MenuItem("Memory Viewer", nullptr, &show_memory_viewer);
|
||||
ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("GUI Tools")) {
|
||||
ImGui::MenuItem("Metrics (ImGui)", nullptr, &show_imgui_metrics);
|
||||
ImGui::MenuItem("Style Editor (ImGui)", nullptr,
|
||||
&show_imgui_style_editor);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::MenuItem("ImGui Metrics", nullptr, &show_imgui_metrics);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ absl::Status OverworldEditor::Update() {
|
||||
if (ImGui::BeginTable(kOWEditTable.data(), 2, kOWEditFlags, ImVec2(0, 0))) {
|
||||
TableSetupColumn("Canvas", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Tile Selector");
|
||||
TableSetupColumn("Tile Selector", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
|
||||
@@ -48,7 +48,7 @@ static constexpr absl::string_view kOverworldSettingsColumnNames[] = {
|
||||
constexpr ImGuiTableFlags kOWMapFlags = ImGuiTableFlags_Borders;
|
||||
constexpr ImGuiTableFlags kToolsetTableFlags = ImGuiTableFlags_SizingFixedFit;
|
||||
constexpr ImGuiTableFlags kOWEditFlags = ImGuiTableFlags_Reorderable |
|
||||
ImGuiTableFlags_Resizable |
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable |
|
||||
ImGuiTableFlags_SizingStretchSame;
|
||||
|
||||
constexpr absl::string_view kWorldList =
|
||||
@@ -184,10 +184,6 @@ class OverworldEditor : public Editor,
|
||||
gfx::BitmapTable graphics_bin_;
|
||||
gfx::BitmapTable current_graphics_set_;
|
||||
gfx::BitmapTable sprite_previews_;
|
||||
|
||||
ImGuiTableFlags ow_edit_flags = ImGuiTableFlags_Reorderable |
|
||||
ImGuiTableFlags_Resizable |
|
||||
ImGuiTableFlags_SizingStretchSame;
|
||||
};
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#include "app/emu/emulator.h"
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui_memory_editor.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "app/core/constants.h"
|
||||
#include "app/emu/snes.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -20,6 +22,65 @@ bool ShouldDisplay(const InstructionEntry& entry, const char* filter,
|
||||
// filter and showAll flag
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawMemoryWindow(Memory* memory) {
|
||||
const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
|
||||
static ImGuiTableFlags flags =
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable |
|
||||
ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg |
|
||||
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX;
|
||||
if (auto outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f);
|
||||
ImGui::BeginTable("table1", 4, flags, outer_size)) {
|
||||
// Table headers
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Memory Area");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Start Address");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Size");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Mapping");
|
||||
|
||||
// Retrieve memory information from MemoryImpl
|
||||
MemoryImpl* memoryImpl = dynamic_cast<MemoryImpl*>(memory);
|
||||
if (memoryImpl) {
|
||||
// Display memory areas
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("ROM");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("0x000000");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d MB", memoryImpl->rom_.size());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("LoROM");
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("RAM");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("0x7E0000");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d KB", memoryImpl->ram_.size());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("LoROM");
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
|
||||
if (ImGui::Button("Open Memory Viewer", ImVec2(200, 50))) {
|
||||
ImGui::OpenPopup("Memory Viewer");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("Memory Viewer", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
static MemoryEditor mem_edit;
|
||||
mem_edit.DrawContents((void*)memoryImpl->data(), memoryImpl->size());
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using ImGui::NextColumn;
|
||||
@@ -30,7 +91,12 @@ using ImGui::Text;
|
||||
|
||||
void Emulator::Run() {
|
||||
if (!snes_.running() && loading_) {
|
||||
if (rom()->isLoaded()) {
|
||||
if (loading_ && !memory_setup_) {
|
||||
snes_.SetupMemory(*rom());
|
||||
memory_setup_ = true;
|
||||
}
|
||||
|
||||
if (rom()->isLoaded() && power_) {
|
||||
snes_.Init(*rom());
|
||||
running_ = true;
|
||||
}
|
||||
@@ -38,6 +104,13 @@ void Emulator::Run() {
|
||||
|
||||
RenderNavBar();
|
||||
|
||||
ImGui::Button(ICON_MD_ARROW_FORWARD_IOS);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_DOUBLE_ARROW);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_SUBDIRECTORY_ARROW_RIGHT);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (running_) {
|
||||
HandleEvents();
|
||||
UpdateEmulator();
|
||||
@@ -67,7 +140,9 @@ void Emulator::RenderNavBar() {
|
||||
|
||||
if (ImGui::BeginMenu("Game")) {
|
||||
MENU_ITEM("Load ROM") { loading_ = true; }
|
||||
MENU_ITEM("Power On") { power_ = true; }
|
||||
MENU_ITEM("Power Off") {
|
||||
power_ = false;
|
||||
running_ = false;
|
||||
loading_ = false;
|
||||
debugger_ = false;
|
||||
@@ -133,6 +208,7 @@ void Emulator::RenderDebugger() {
|
||||
|
||||
TableNextColumn();
|
||||
RenderBreakpointList();
|
||||
DrawMemoryWindow(snes_.Memory());
|
||||
ImGui::EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,9 +39,11 @@ class Emulator : public SharedROM {
|
||||
|
||||
SNES snes_;
|
||||
|
||||
bool power_ = false;
|
||||
bool loading_ = false;
|
||||
bool running_ = false;
|
||||
bool debugger_ = true;
|
||||
bool loading_ = false;
|
||||
bool memory_setup_ = false;
|
||||
bool integrated_debugger_mode_ = true;
|
||||
bool separate_debugger_mode_ = false;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/emu/debug/log.h"
|
||||
@@ -135,9 +136,21 @@ class Memory {
|
||||
virtual uint8_t at(int i) const = 0;
|
||||
};
|
||||
|
||||
enum class MemoryMapping { SNES_LOROM = 0, PC_ADDRESS = 1 };
|
||||
|
||||
class MemoryImpl : public Memory, public Loggable {
|
||||
public:
|
||||
void Initialize(const std::vector<uint8_t>& romData) {
|
||||
void Initialize(const std::vector<uint8_t>& romData,
|
||||
MemoryMapping mapping = MemoryMapping::SNES_LOROM) {
|
||||
mapping_ = mapping;
|
||||
if (mapping == MemoryMapping::PC_ADDRESS) {
|
||||
memory_.resize(romData.size());
|
||||
std::copy(romData.begin(), romData.end(), memory_.begin());
|
||||
return;
|
||||
}
|
||||
|
||||
memory_.reserve(0x1000000); // 16 MB
|
||||
|
||||
const size_t ROM_CHUNK_SIZE = 0x8000; // 32 KB
|
||||
const size_t SRAM_SIZE = 0x10000; // 64 KB
|
||||
const size_t SYSTEM_RAM_SIZE = 0x20000; // 128 KB
|
||||
@@ -322,6 +335,7 @@ class MemoryImpl : public Memory, public Loggable {
|
||||
auto size() const { return memory_.size(); }
|
||||
auto begin() const { return memory_.begin(); }
|
||||
auto end() const { return memory_.end(); }
|
||||
auto data() const { return memory_.data(); }
|
||||
|
||||
// Define memory regions
|
||||
std::vector<uint8_t> rom_;
|
||||
@@ -334,6 +348,10 @@ class MemoryImpl : public Memory, public Loggable {
|
||||
uint32_t bank = address >> 16;
|
||||
uint32_t offset = address & 0xFFFF;
|
||||
|
||||
if (mapping_ == MemoryMapping::PC_ADDRESS) {
|
||||
return address;
|
||||
}
|
||||
|
||||
if (bank <= 0x3F) {
|
||||
if (offset <= 0x1FFF) {
|
||||
return offset; // Shadow RAM
|
||||
@@ -364,10 +382,12 @@ class MemoryImpl : public Memory, public Loggable {
|
||||
std::vector<Observer*> observers_;
|
||||
|
||||
// Memory (64KB)
|
||||
std::array<uint8_t, 0x10000> memory_;
|
||||
std::vector<uint8_t> memory_;
|
||||
|
||||
// Stack Pointer
|
||||
uint16_t SP_ = 0x01FF;
|
||||
|
||||
MemoryMapping mapping_ = MemoryMapping::SNES_LOROM;
|
||||
};
|
||||
|
||||
} // namespace emu
|
||||
|
||||
@@ -108,22 +108,15 @@ ROMInfo SNES::ReadRomHeader(uint32_t offset) {
|
||||
}
|
||||
|
||||
void SNES::Init(ROM& rom) {
|
||||
// Setup observers for the memory space
|
||||
memory_.AddObserver(&apu);
|
||||
memory_.AddObserver(&ppu);
|
||||
|
||||
// Load the ROM into memory and set up the memory mapping
|
||||
memory_.Initialize(rom.vector());
|
||||
|
||||
// Read the ROM header
|
||||
auto header_offset = GetHeaderOffset(memory_);
|
||||
rom_info_ = ReadRomHeader(header_offset);
|
||||
|
||||
// Perform a long jump into a FastROM bank (if the ROM speed is FastROM)
|
||||
// Disable the emulation flag (switch to 65816 native mode)
|
||||
|
||||
// Initialize CPU
|
||||
cpu.Init();
|
||||
|
||||
// Read the ROM header
|
||||
auto header_offset = GetHeaderOffset(memory_);
|
||||
rom_info_ = ReadRomHeader(header_offset);
|
||||
cpu.PC = rom_info_.resetVector;
|
||||
|
||||
// Initialize PPU
|
||||
|
||||
@@ -65,12 +65,22 @@ class SNES : public DMA {
|
||||
|
||||
auto Cpu() -> CPU& { return cpu; }
|
||||
auto Ppu() -> PPU& { return ppu; }
|
||||
auto Memory() -> MemoryImpl* { return &memory_; }
|
||||
|
||||
void SetCpuMode(int mode) { cpu_mode_ = mode; }
|
||||
CPU::UpdateMode GetCpuMode() const {
|
||||
return static_cast<CPU::UpdateMode>(cpu_mode_);
|
||||
}
|
||||
|
||||
void SetupMemory(ROM& rom) {
|
||||
// Setup observers for the memory space
|
||||
memory_.AddObserver(&apu);
|
||||
memory_.AddObserver(&ppu);
|
||||
|
||||
// Load the ROM into memory and set up the memory mapping
|
||||
memory_.Initialize(rom.vector());
|
||||
}
|
||||
|
||||
private:
|
||||
void WriteToRegister(uint16_t address, uint8_t value) {
|
||||
memory_.WriteByte(address, value);
|
||||
|
||||
@@ -8,15 +8,376 @@ namespace app {
|
||||
|
||||
namespace gui {
|
||||
|
||||
void TextWithSeparators(const absl::string_view &text) {
|
||||
void DrawDisplaySettings(ImGuiStyle* ref) {
|
||||
// You can pass in a reference ImGuiStyle structure to compare to, revert to
|
||||
// and save to (without a reference style pointer, we will use one compared
|
||||
// locally as a reference)
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
static ImGuiStyle ref_saved_style;
|
||||
|
||||
// Default to using internal storage as reference
|
||||
static bool init = true;
|
||||
if (init && ref == NULL) ref_saved_style = style;
|
||||
init = false;
|
||||
if (ref == NULL) ref = &ref_saved_style;
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
|
||||
|
||||
if (ImGui::ShowStyleSelector("Colors##Selector")) ref_saved_style = style;
|
||||
ImGui::ShowFontSelector("Fonts##Selector");
|
||||
|
||||
// Simplified Settings (expose floating-pointer border sizes as boolean
|
||||
// representing 0.0f or 1.0f)
|
||||
if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f,
|
||||
"%.0f"))
|
||||
style.GrabRounding = style.FrameRounding; // Make GrabRounding always the
|
||||
// same value as FrameRounding
|
||||
{
|
||||
bool border = (style.WindowBorderSize > 0.0f);
|
||||
if (ImGui::Checkbox("WindowBorder", &border)) {
|
||||
style.WindowBorderSize = border ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
{
|
||||
bool border = (style.FrameBorderSize > 0.0f);
|
||||
if (ImGui::Checkbox("FrameBorder", &border)) {
|
||||
style.FrameBorderSize = border ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
{
|
||||
bool border = (style.PopupBorderSize > 0.0f);
|
||||
if (ImGui::Checkbox("PopupBorder", &border)) {
|
||||
style.PopupBorderSize = border ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Save/Revert button
|
||||
if (ImGui::Button("Save Ref")) *ref = ref_saved_style = style;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Revert Ref")) style = *ref;
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None)) {
|
||||
if (ImGui::BeginTabItem("Sizes")) {
|
||||
ImGui::SeparatorText("Main");
|
||||
ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f,
|
||||
20.0f, "%.0f");
|
||||
ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f,
|
||||
20.0f, "%.0f");
|
||||
ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f,
|
||||
20.0f, "%.0f");
|
||||
ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing,
|
||||
0.0f, 20.0f, "%.0f");
|
||||
ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding,
|
||||
0.0f, 10.0f, "%.0f");
|
||||
ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f,
|
||||
"%.0f");
|
||||
|
||||
ImGui::SeparatorText("Borders");
|
||||
ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f,
|
||||
1.0f, "%.0f");
|
||||
ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f,
|
||||
2.0f, "%.0f");
|
||||
|
||||
ImGui::SeparatorText("Rounding");
|
||||
ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f,
|
||||
12.0f, "%.0f");
|
||||
ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f,
|
||||
"%.0f");
|
||||
|
||||
ImGui::SeparatorText("Tables");
|
||||
ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f,
|
||||
20.0f, "%.0f");
|
||||
ImGui::SliderAngle("TableAngledHeadersAngle",
|
||||
&style.TableAngledHeadersAngle, -50.0f, +50.0f);
|
||||
|
||||
ImGui::SeparatorText("Widgets");
|
||||
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign,
|
||||
0.0f, 1.0f, "%.2f");
|
||||
int window_menu_button_position = style.WindowMenuButtonPosition + 1;
|
||||
if (ImGui::Combo("WindowMenuButtonPosition",
|
||||
(int*)&window_menu_button_position,
|
||||
"None\0Left\0Right\0"))
|
||||
style.WindowMenuButtonPosition = window_menu_button_position - 1;
|
||||
ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition,
|
||||
"Left\0Right\0");
|
||||
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign,
|
||||
0.0f, 1.0f, "%.2f");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SliderFloat2("SelectableTextAlign",
|
||||
(float*)&style.SelectableTextAlign, 0.0f, 1.0f,
|
||||
"%.2f");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SliderFloat("SeparatorTextBorderSize",
|
||||
&style.SeparatorTextBorderSize, 0.0f, 10.0f, "%.0f");
|
||||
ImGui::SliderFloat2("SeparatorTextAlign",
|
||||
(float*)&style.SeparatorTextAlign, 0.0f, 1.0f,
|
||||
"%.2f");
|
||||
ImGui::SliderFloat2("SeparatorTextPadding",
|
||||
(float*)&style.SeparatorTextPadding, 0.0f, 40.0f,
|
||||
"%.0f");
|
||||
ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f,
|
||||
12.0f, "%.0f");
|
||||
|
||||
ImGui::SeparatorText("Tooltips");
|
||||
for (int n = 0; n < 2; n++)
|
||||
if (ImGui::TreeNodeEx(n == 0 ? "HoverFlagsForTooltipMouse"
|
||||
: "HoverFlagsForTooltipNav")) {
|
||||
ImGuiHoveredFlags* p = (n == 0) ? &style.HoverFlagsForTooltipMouse
|
||||
: &style.HoverFlagsForTooltipNav;
|
||||
ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNone", p,
|
||||
ImGuiHoveredFlags_DelayNone);
|
||||
ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayShort", p,
|
||||
ImGuiHoveredFlags_DelayShort);
|
||||
ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNormal", p,
|
||||
ImGuiHoveredFlags_DelayNormal);
|
||||
ImGui::CheckboxFlags("ImGuiHoveredFlags_Stationary", p,
|
||||
ImGuiHoveredFlags_Stationary);
|
||||
ImGui::CheckboxFlags("ImGuiHoveredFlags_NoSharedDelay", p,
|
||||
ImGuiHoveredFlags_NoSharedDelay);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Misc");
|
||||
ImGui::SliderFloat2("DisplaySafeAreaPadding",
|
||||
(float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f,
|
||||
"%.0f");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Colors")) {
|
||||
static int output_dest = 0;
|
||||
static bool output_only_modified = true;
|
||||
if (ImGui::Button("Export")) {
|
||||
if (output_dest == 0)
|
||||
ImGui::LogToClipboard();
|
||||
else
|
||||
ImGui::LogToTTY();
|
||||
ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
|
||||
for (int i = 0; i < ImGuiCol_COUNT; i++) {
|
||||
const ImVec4& col = style.Colors[i];
|
||||
const char* name = ImGui::GetStyleColorName(i);
|
||||
if (!output_only_modified ||
|
||||
memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
|
||||
ImGui::LogText(
|
||||
"colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, "
|
||||
"%.2ff);" IM_NEWLINE,
|
||||
name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
|
||||
}
|
||||
ImGui::LogFinish();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(120);
|
||||
ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Only Modified Colors", &output_only_modified);
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
|
||||
|
||||
static ImGuiColorEditFlags alpha_flags = 0;
|
||||
if (ImGui::RadioButton("Opaque",
|
||||
alpha_flags == ImGuiColorEditFlags_None)) {
|
||||
alpha_flags = ImGuiColorEditFlags_None;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Alpha",
|
||||
alpha_flags == ImGuiColorEditFlags_AlphaPreview)) {
|
||||
alpha_flags = ImGuiColorEditFlags_AlphaPreview;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton(
|
||||
"Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) {
|
||||
alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(
|
||||
ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 10),
|
||||
ImVec2(FLT_MAX, FLT_MAX));
|
||||
ImGui::BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Border,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar |
|
||||
ImGuiWindowFlags_NavFlattened);
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
|
||||
for (int i = 0; i < ImGuiCol_COUNT; i++) {
|
||||
const char* name = ImGui::GetStyleColorName(i);
|
||||
if (!filter.PassFilter(name)) continue;
|
||||
ImGui::PushID(i);
|
||||
ImGui::ColorEdit4("##color", (float*)&style.Colors[i],
|
||||
ImGuiColorEditFlags_AlphaBar | alpha_flags);
|
||||
if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) {
|
||||
// Tips: in a real user application, you may want to merge and use
|
||||
// an icon font into the main font, so instead of "Save"/"Revert"
|
||||
// you'd use icons! Read the FAQ and docs/FONTS.md about using icon
|
||||
// fonts. It's really easy and super convenient!
|
||||
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
if (ImGui::Button("Save")) {
|
||||
ref->Colors[i] = style.Colors[i];
|
||||
}
|
||||
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
if (ImGui::Button("Revert")) {
|
||||
style.Colors[i] = ref->Colors[i];
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
ImGui::TextUnformatted(name);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Fonts")) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImFontAtlas* atlas = io.Fonts;
|
||||
ImGui::ShowFontAtlas(atlas);
|
||||
|
||||
// Post-baking font scaling. Note that this is NOT the nice way of
|
||||
// scaling fonts, read below. (we enforce hard clamping manually as by
|
||||
// default DragFloat/SliderFloat allows CTRL+Click text to get out of
|
||||
// bounds).
|
||||
const float MIN_SCALE = 0.3f;
|
||||
const float MAX_SCALE = 2.0f;
|
||||
|
||||
static float window_scale = 1.0f;
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
if (ImGui::DragFloat(
|
||||
"window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE,
|
||||
"%.2f",
|
||||
ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
|
||||
ImGui::SetWindowFontScale(window_scale);
|
||||
ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE,
|
||||
MAX_SCALE, "%.2f",
|
||||
ImGuiSliderFlags_AlwaysClamp); // Scale everything
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Rendering")) {
|
||||
ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Checkbox("Anti-aliased lines use texture",
|
||||
&style.AntiAliasedLinesUseTex);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::DragFloat("Curve Tessellation Tolerance",
|
||||
&style.CurveTessellationTol, 0.02f, 0.10f, 10.0f,
|
||||
"%.2f");
|
||||
if (style.CurveTessellationTol < 0.10f)
|
||||
style.CurveTessellationTol = 0.10f;
|
||||
|
||||
// When editing the "Circle Segment Max Error" value, draw a preview of
|
||||
// its effect on auto-tessellated circles.
|
||||
ImGui::DragFloat("Circle Tessellation Max Error",
|
||||
&style.CircleTessellationMaxError, 0.005f, 0.10f, 5.0f,
|
||||
"%.2f", ImGuiSliderFlags_AlwaysClamp);
|
||||
const bool show_samples = ImGui::IsItemActive();
|
||||
if (show_samples) ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
|
||||
if (show_samples && ImGui::BeginTooltip()) {
|
||||
ImGui::TextUnformatted("(R = radius, N = number of segments)");
|
||||
ImGui::Spacing();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x;
|
||||
for (int n = 0; n < 8; n++) {
|
||||
const float RAD_MIN = 5.0f;
|
||||
const float RAD_MAX = 70.0f;
|
||||
const float rad =
|
||||
RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Text("R: %.f\nN: %d", rad,
|
||||
draw_list->_CalcCircleAutoSegmentCount(rad));
|
||||
|
||||
const float canvas_width = std::max(min_widget_width, rad * 2.0f);
|
||||
const float offset_x = floorf(canvas_width * 0.5f);
|
||||
const float offset_y = floorf(RAD_MAX);
|
||||
|
||||
const ImVec2 p1 = ImGui::GetCursorScreenPos();
|
||||
draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad,
|
||||
ImGui::GetColorU32(ImGuiCol_Text));
|
||||
ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
|
||||
|
||||
/*
|
||||
const ImVec2 p2 = ImGui::GetCursorScreenPos();
|
||||
draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y),
|
||||
rad, ImGui::GetColorU32(ImGuiCol_Text));
|
||||
ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
|
||||
*/
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f,
|
||||
"%.2f"); // Not exposing zero here so user doesn't
|
||||
// "lose" the UI (zero alpha clips all
|
||||
// widgets). But application code could have a
|
||||
// toggle to switch between zero and non-zero.
|
||||
ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f,
|
||||
1.0f, "%.2f");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void TextWithSeparators(const absl::string_view& text) {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("%s", text.data());
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
void ColorsYaze() {
|
||||
ImGuiStyle *style = &ImGui::GetStyle();
|
||||
ImVec4 *colors = style->Colors;
|
||||
ImGuiStyle* style = &ImGui::GetStyle();
|
||||
ImVec4* colors = style->Colors;
|
||||
|
||||
style->WindowPadding = ImVec2(10.f, 10.f);
|
||||
style->FramePadding = ImVec2(10.f, 2.f);
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace gui {
|
||||
|
||||
void DrawDisplaySettings(ImGuiStyle* ref = nullptr);
|
||||
|
||||
void TextWithSeparators(const absl::string_view& text);
|
||||
|
||||
void ColorsYaze();
|
||||
|
||||
@@ -23,72 +23,125 @@ class DungeonObjectRenderer : public SharedROM {
|
||||
public:
|
||||
struct PseudoVram {
|
||||
std::vector<gfx::Bitmap> sheets;
|
||||
// TODO: Initialize with mock VRAM data
|
||||
};
|
||||
|
||||
void CreateVramFromRoomBlockset() {
|
||||
// auto bitmap_manager = rom()->bitmap_manager();
|
||||
// uint16_t room_id = 0;
|
||||
// auto room_blockset = rom()->room_blockset_ids[room_id];
|
||||
|
||||
// for (const auto blockset_id : room_blockset) {
|
||||
// auto blockset = bitmap_manager[(uint16_t)blockset_id];
|
||||
// vram_.sheets.push_back(*blockset.get());
|
||||
// }
|
||||
DungeonObjectRenderer() {
|
||||
// TODO: Constructor implementation
|
||||
}
|
||||
|
||||
void RenderObjectsAsBitmaps() {
|
||||
rom_data_ = rom()->vector();
|
||||
memory_.Initialize(rom_data_);
|
||||
cpu.Init();
|
||||
void LoadObject(uint16_t objectId) {
|
||||
// Prepare the CPU and memory environment
|
||||
memory_.Initialize(rom()->vector());
|
||||
|
||||
auto subtype1_ptr = core::subtype1_tiles;
|
||||
auto subtype1_routine_ptr = core::subtype1_tiles + 0x200;
|
||||
std::array<uint16_t, 256> routine_ptrs;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint16_t actual_ptr = rom()->toint16(subtype1_routine_ptr + (i * 2));
|
||||
routine_ptrs[i] = actual_ptr;
|
||||
std::cout << std::hex << routine_ptrs[i] << std::endl;
|
||||
// Fetch the subtype pointers for the given object ID
|
||||
auto subtypeInfo = FetchSubtypeInfo(objectId);
|
||||
|
||||
// Configure the object based on the fetched information
|
||||
ConfigureObject(subtypeInfo);
|
||||
|
||||
// Run the CPU emulation for the object's draw routines
|
||||
RenderObject(subtypeInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
struct SubtypeInfo {
|
||||
uint16_t subtypePtr;
|
||||
uint16_t routinePtr;
|
||||
// Additional fields as needed
|
||||
};
|
||||
|
||||
SubtypeInfo FetchSubtypeInfo(uint16_t objectId) {
|
||||
SubtypeInfo info;
|
||||
|
||||
// Determine the subtype based on objectId
|
||||
// Assuming subtype is determined by some bits in objectId; modify as needed
|
||||
uint8_t subtype = (objectId >> 8) & 0xFF; // Example: top 8 bits
|
||||
|
||||
// Based on the subtype, fetch the correct pointers
|
||||
switch (subtype) {
|
||||
case 1: // Subtype 1
|
||||
info.subtypePtr = core::subtype1_tiles + (objectId & 0xFF) * 2;
|
||||
info.routinePtr = core::subtype1_tiles + 0x200 + (objectId & 0xFF) * 2;
|
||||
break;
|
||||
case 2: // Subtype 2
|
||||
info.subtypePtr = core::subtype2_tiles + (objectId & 0x7F) * 2;
|
||||
info.routinePtr = core::subtype2_tiles + 0x80 + (objectId & 0x7F) * 2;
|
||||
break;
|
||||
case 3: // Subtype 3
|
||||
info.subtypePtr = core::subtype3_tiles + (objectId & 0xFF) * 2;
|
||||
info.routinePtr = core::subtype3_tiles + 0x100 + (objectId & 0xFF) * 2;
|
||||
break;
|
||||
default:
|
||||
// Handle unknown subtype
|
||||
throw std::runtime_error("Unknown subtype for object ID: " +
|
||||
std::to_string(objectId));
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (const auto routine_ptr : routine_ptrs) {
|
||||
cpu.PC = routine_ptr - 2;
|
||||
cpu.PB = 0x00;
|
||||
// Convert pointers from ROM-relative to absolute (if necessary)
|
||||
// info.subtypePtr = ConvertToAbsolutePtr(info.subtypePtr);
|
||||
// info.routinePtr = ConvertToAbsolutePtr(info.routinePtr);
|
||||
|
||||
auto cycles_to_run = clock_.GetCycleCount();
|
||||
return info;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
auto opcode = cpu.FetchByte();
|
||||
// Fetch and execute an instruction
|
||||
cpu.ExecuteInstruction(opcode);
|
||||
void ConfigureObject(const SubtypeInfo& info) {
|
||||
// TODO: Use the information in info to set up the object's initial state
|
||||
// This may include setting CPU registers, loading specific tiles into VRAM,
|
||||
// etc.
|
||||
}
|
||||
|
||||
// Handle any interrupts, if necessary
|
||||
cpu.HandleInterrupts();
|
||||
void RenderObject(const SubtypeInfo& info) {
|
||||
// Assuming that the routine pointer and other necessary setup is done in
|
||||
// ConfigureObject Start CPU at the routine's entry point
|
||||
cpu.PC =
|
||||
info.routinePtr; // info should be a member or passed as a parameter
|
||||
cpu.PB = 0x01; // Set the program bank; adjust based on your memory mapping
|
||||
|
||||
// Check if the instruction is RTS
|
||||
if (opcode == 0x60) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if (i > 50) {
|
||||
break;
|
||||
}
|
||||
// Run the CPU emulation loop
|
||||
while (true) {
|
||||
// Fetch the next opcode
|
||||
uint8_t opcode = cpu.FetchByte();
|
||||
|
||||
// Execute the fetched instruction
|
||||
cpu.ExecuteInstruction(opcode);
|
||||
|
||||
// Handle any interrupts, if necessary
|
||||
cpu.HandleInterrupts();
|
||||
|
||||
// Check if the end of the routine is reached (typically RTS instruction)
|
||||
if (opcode == 0x60) { // RTS opcode
|
||||
break;
|
||||
}
|
||||
|
||||
// Additional checks can be added here, e.g., maximum cycles or
|
||||
// instructions
|
||||
|
||||
// Update the PPU state if necessary
|
||||
// ppu.Update();
|
||||
|
||||
// After PPU update, reflect any changes in the Bitmap(s)
|
||||
// UpdateBitmapFromPPU();
|
||||
}
|
||||
|
||||
auto subtype2_ptr = core::subtype2_tiles;
|
||||
auto subtype2_routine_ptr =
|
||||
core::subtype2_tiles + 0x80; // Where the draw routines start
|
||||
std::array<uint16_t, 128> subtype2_routine_ptrs;
|
||||
for (int i = 0; i < 128; i++) {
|
||||
subtype2_routine_ptrs[i] = subtype2_routine_ptr + i * 2;
|
||||
}
|
||||
|
||||
auto subtype3_ptr = core::subtype3_tiles;
|
||||
auto subtype3_routine_ptr =
|
||||
core::subtype3_tiles + 0x100; // Where the draw routines start
|
||||
// Post-rendering operations (if any)
|
||||
// PostRenderOperations();
|
||||
}
|
||||
|
||||
// Helper function to update Bitmap from PPU state
|
||||
void UpdateBitmapFromPPU() {
|
||||
// TODO: Implement logic to transfer PPU state changes to the Bitmap
|
||||
// This involves reading the tile data and other graphics info from PPU
|
||||
// and rendering it to the Bitmap object
|
||||
}
|
||||
|
||||
// Optional: Handle any operations after rendering
|
||||
void PostRenderOperations() {
|
||||
// TODO: Implement any cleanup or additional processing needed after
|
||||
// rendering
|
||||
}
|
||||
|
||||
// Members
|
||||
std::vector<uint8_t> rom_data_;
|
||||
emu::MemoryImpl memory_;
|
||||
emu::ClockImpl clock_;
|
||||
@@ -98,6 +151,43 @@ class DungeonObjectRenderer : public SharedROM {
|
||||
PseudoVram vram_;
|
||||
};
|
||||
|
||||
// void CreateVramFromRoomBlockset() {
|
||||
// // auto bitmap_manager = rom()->bitmap_manager();
|
||||
// // uint16_t room_id = 0;
|
||||
// // auto room_blockset = rom()->room_blockset_ids[room_id];
|
||||
|
||||
// // for (const auto blockset_id : room_blockset) {
|
||||
// // auto blockset = bitmap_manager[(uint16_t)blockset_id];
|
||||
// // vram_.sheets.push_back(*blockset.get());
|
||||
// // }
|
||||
// }
|
||||
|
||||
// int i = 0;
|
||||
// for (const auto routine_ptr : routine_ptrs) {
|
||||
// cpu.PC = routine_ptr - 2;
|
||||
// cpu.PB = 0x01;
|
||||
|
||||
// auto cycles_to_run = clock_.GetCycleCount();
|
||||
|
||||
// while (true) {
|
||||
// auto opcode = cpu.FetchByte();
|
||||
// // Fetch and execute an instruction
|
||||
// cpu.ExecuteInstruction(opcode);
|
||||
|
||||
// // Handle any interrupts, if necessary
|
||||
// cpu.HandleInterrupts();
|
||||
|
||||
// // Check if the instruction is RTS
|
||||
// if (opcode == 0x60) {
|
||||
// break;
|
||||
// }
|
||||
// i++;
|
||||
// if (i > 50) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
enum class SpecialObjectType { Chest, BigChest, InterroomStairs };
|
||||
|
||||
struct Tile {};
|
||||
|
||||
Reference in New Issue
Block a user