Dungeon object updates
This commit is contained in:
@@ -37,12 +37,12 @@ For developers to reference.
|
|||||||
- These classes are all controlled by [MasterEditor](../src/app/editor/master_editor.h)
|
- These classes are all controlled by [MasterEditor](../src/app/editor/master_editor.h)
|
||||||
- [DungeonEditor](../src/app/editor/dungeon_editor.h)
|
- [DungeonEditor](../src/app/editor/dungeon_editor.h)
|
||||||
- [GraphicsEditor](../src/app/editor/graphics_editor.h)
|
- [GraphicsEditor](../src/app/editor/graphics_editor.h)
|
||||||
- [MusicEditor](../src/app/editor/music_editor.h)
|
|
||||||
- [OverworldEditor](../src/app/editor/overworld_editor.h)
|
- [OverworldEditor](../src/app/editor/overworld_editor.h)
|
||||||
- [ScreenEditor](../src/app/editor/screen_editor.h)
|
- [ScreenEditor](../src/app/editor/screen_editor.h)
|
||||||
- [SpriteEditor](../src/app/editor/sprite_editor.h)
|
- [SpriteEditor](../src/app/editor/sprite_editor.h)
|
||||||
- **Modules**
|
- **Modules**
|
||||||
- [AssemblyEditor](../src/app/editor/modules/assembly_editor.h)
|
- [AssemblyEditor](../src/app/editor/modules/assembly_editor.h)
|
||||||
|
- [MusicEditor](../src/app/editor/modules/music_editor.h)
|
||||||
- [GfxGroupEditor](../src/app/editor/modules/gfx_group_editor.h)
|
- [GfxGroupEditor](../src/app/editor/modules/gfx_group_editor.h)
|
||||||
- [Tile16Editor](../src/app/editor/modules/tile16_editor.h)
|
- [Tile16Editor](../src/app/editor/modules/tile16_editor.h)
|
||||||
- **Emu Namespace**:
|
- **Emu Namespace**:
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ set(
|
|||||||
app/editor/overworld_editor.cc
|
app/editor/overworld_editor.cc
|
||||||
app/editor/screen_editor.cc
|
app/editor/screen_editor.cc
|
||||||
app/editor/sprite_editor.cc
|
app/editor/sprite_editor.cc
|
||||||
app/editor/resources/music_editor.cc
|
app/editor/modules/music_editor.cc
|
||||||
app/editor/resources/palette_editor.cc
|
app/editor/modules/palette_editor.cc
|
||||||
app/editor/modules/assembly_editor.cc
|
app/editor/modules/assembly_editor.cc
|
||||||
app/editor/modules/tile16_editor.cc
|
app/editor/modules/tile16_editor.cc
|
||||||
app/editor/modules/gfx_group_editor.cc
|
app/editor/modules/gfx_group_editor.cc
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ uint32_t PcToSnes(uint32_t addr) {
|
|||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t MapBankToWordAddress(uint8_t bank, uint16_t addr) {
|
||||||
|
uint32_t result = 0;
|
||||||
|
result = (bank << 16) | addr;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int AddressFromBytes(uint8_t addr1, uint8_t addr2, uint8_t addr3) {
|
int AddressFromBytes(uint8_t addr1, uint8_t addr2, uint8_t addr3) {
|
||||||
return (addr1 << 16) | (addr2 << 8) | addr3;
|
return (addr1 << 16) | (addr2 << 8) | addr3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class ExperimentFlags {
|
|||||||
bool kUseBitmapManager = true;
|
bool kUseBitmapManager = true;
|
||||||
|
|
||||||
// Log instructions to the GUI debugger.
|
// Log instructions to the GUI debugger.
|
||||||
bool kLogInstructions = true;
|
bool kLogInstructions = false;
|
||||||
|
|
||||||
// Flag to enable ImGui input config flags. Currently is
|
// Flag to enable ImGui input config flags. Currently is
|
||||||
// handled manually by controller class but should be
|
// handled manually by controller class but should be
|
||||||
@@ -35,7 +35,7 @@ class ExperimentFlags {
|
|||||||
bool kSaveWithChangeQueue = false;
|
bool kSaveWithChangeQueue = false;
|
||||||
|
|
||||||
// Attempt to run the dungeon room draw routine when opening a room.
|
// Attempt to run the dungeon room draw routine when opening a room.
|
||||||
bool kDrawDungeonRoomGraphics = false;
|
bool kDrawDungeonRoomGraphics = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
ExperimentFlags() = default;
|
ExperimentFlags() = default;
|
||||||
@@ -58,11 +58,43 @@ class ExperimentFlags {
|
|||||||
static std::shared_ptr<Flags> flags_;
|
static std::shared_ptr<Flags> flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NotifyFlag is a special type class which stores two copies of a type
|
||||||
|
// and uses that to check if the value was updated last or not
|
||||||
|
// It should have an accessor which says if it was modified or not
|
||||||
|
// and when that is read it should reset the value and state
|
||||||
|
template <typename T>
|
||||||
|
class NotifyFlag {
|
||||||
|
public:
|
||||||
|
NotifyFlag() : value_(), modified_(false) {}
|
||||||
|
|
||||||
|
void set(const T &value) {
|
||||||
|
value_ = value;
|
||||||
|
modified_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T &get() {
|
||||||
|
modified_ = false;
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(const T &value) { set(value); }
|
||||||
|
operator T() const { return get(); }
|
||||||
|
|
||||||
|
bool isModified() const { return modified_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T value_;
|
||||||
|
bool modified_;
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t SnesToPc(uint32_t addr);
|
uint32_t SnesToPc(uint32_t addr);
|
||||||
uint32_t PcToSnes(uint32_t addr);
|
uint32_t PcToSnes(uint32_t addr);
|
||||||
|
|
||||||
|
uint32_t MapBankToWordAddress(uint8_t bank, uint16_t addr);
|
||||||
|
|
||||||
int AddressFromBytes(uint8_t addr1, uint8_t addr2, uint8_t addr3);
|
int AddressFromBytes(uint8_t addr1, uint8_t addr2, uint8_t addr3);
|
||||||
int HexToDec(char *input, int length);
|
int HexToDec(char *input, int length);
|
||||||
|
|
||||||
bool StringReplace(std::string &str, const std::string &from,
|
bool StringReplace(std::string &str, const std::string &from,
|
||||||
const std::string &to);
|
const std::string &to);
|
||||||
|
|
||||||
|
|||||||
@@ -58,92 +58,8 @@ absl::Status DungeonEditor::Update() {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DungeonEditor::DrawRoomSelector() {
|
|
||||||
if (rom()->isLoaded()) {
|
|
||||||
gui::InputHexWord("Room ID", ¤t_room_id_);
|
|
||||||
// gui::InputHexByte("Palette ID", &rooms_[current_room_id_].palette);
|
|
||||||
|
|
||||||
if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)9);
|
|
||||||
ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
|
|
||||||
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
|
||||||
int i = 0;
|
|
||||||
for (const auto each_room_name : zelda3::dungeon::kRoomNames) {
|
|
||||||
ImGui::Selectable(each_room_name.data(), current_room_id_ == i,
|
|
||||||
ImGuiSelectableFlags_AllowDoubleClick);
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
active_rooms_.push_back(i);
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DungeonEditor::DrawDungeonTabView() {
|
|
||||||
static int next_tab_id = 0;
|
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("MyTabBar", kDungeonTabBarFlags)) {
|
|
||||||
// TODO: Manage the room that is being added to the tab bar.
|
|
||||||
if (ImGui::TabItemButton("##tabitem", kDungeonTabFlags)) {
|
|
||||||
active_rooms_.push_back(next_tab_id++); // Add new tab
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit our regular tabs
|
|
||||||
for (int n = 0; n < active_rooms_.Size;) {
|
|
||||||
bool open = true;
|
|
||||||
|
|
||||||
if (ImGui::BeginTabItem(
|
|
||||||
zelda3::dungeon::kRoomNames[active_rooms_[n]].data(), &open,
|
|
||||||
ImGuiTabItemFlags_None)) {
|
|
||||||
DrawDungeonCanvas(active_rooms_[n]);
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!open)
|
|
||||||
active_rooms_.erase(active_rooms_.Data + n);
|
|
||||||
else
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTabBar();
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DungeonEditor::DrawDungeonCanvas(int room_id) {
|
|
||||||
ImGui::BeginGroup();
|
|
||||||
|
|
||||||
gui::InputHexByte("Layout", &rooms_[room_id].layout);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
gui::InputHexByte("Blockset", &rooms_[room_id].blockset);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
gui::InputHexByte("Spriteset", &rooms_[room_id].spriteset);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
gui::InputHexByte("Palette", &rooms_[room_id].palette);
|
|
||||||
|
|
||||||
gui::InputHexByte("Floor1", &rooms_[room_id].floor1);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
gui::InputHexByte("Floor2", &rooms_[room_id].floor2);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
gui::InputHexWord("Message ID", &rooms_[room_id].message_id_);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::EndGroup();
|
|
||||||
|
|
||||||
canvas_.DrawBackground();
|
|
||||||
canvas_.DrawContextMenu();
|
|
||||||
canvas_.DrawGrid();
|
|
||||||
canvas_.DrawOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DungeonEditor::DrawToolset() {
|
void DungeonEditor::DrawToolset() {
|
||||||
if (ImGui::BeginTable("DWToolset", 12, ImGuiTableFlags_SizingFixedFit,
|
if (ImGui::BeginTable("DWToolset", 13, ImGuiTableFlags_SizingFixedFit,
|
||||||
ImVec2(0, 0))) {
|
ImVec2(0, 0))) {
|
||||||
TableSetupColumn("#undoTool");
|
TableSetupColumn("#undoTool");
|
||||||
TableSetupColumn("#redoTool");
|
TableSetupColumn("#redoTool");
|
||||||
@@ -231,10 +147,99 @@ void DungeonEditor::DrawToolset() {
|
|||||||
ImGui::SetTooltip("Blocks");
|
ImGui::SetTooltip("Blocks");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (ImGui::Button(ICON_MD_PALETTE)) {
|
||||||
|
// Open the palette module
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DungeonEditor::DrawRoomSelector() {
|
||||||
|
if (rom()->isLoaded()) {
|
||||||
|
gui::InputHexWord("Room ID", ¤t_room_id_);
|
||||||
|
// gui::InputHexByte("Palette ID", &rooms_[current_room_id_].palette);
|
||||||
|
|
||||||
|
if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)9);
|
||||||
|
ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
|
||||||
|
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||||
|
int i = 0;
|
||||||
|
for (const auto each_room_name : zelda3::dungeon::kRoomNames) {
|
||||||
|
ImGui::Selectable(each_room_name.data(), current_room_id_ == i,
|
||||||
|
ImGuiSelectableFlags_AllowDoubleClick);
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
active_rooms_.push_back(i);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditor::DrawDungeonTabView() {
|
||||||
|
static int next_tab_id = 0;
|
||||||
|
|
||||||
|
if (ImGui::BeginTabBar("MyTabBar", kDungeonTabBarFlags)) {
|
||||||
|
// TODO: Manage the room that is being added to the tab bar.
|
||||||
|
if (ImGui::TabItemButton("##tabitem", kDungeonTabFlags)) {
|
||||||
|
active_rooms_.push_back(next_tab_id++); // Add new tab
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit our regular tabs
|
||||||
|
for (int n = 0; n < active_rooms_.Size;) {
|
||||||
|
bool open = true;
|
||||||
|
|
||||||
|
if (ImGui::BeginTabItem(
|
||||||
|
zelda3::dungeon::kRoomNames[active_rooms_[n]].data(), &open,
|
||||||
|
ImGuiTabItemFlags_None)) {
|
||||||
|
DrawDungeonCanvas(active_rooms_[n]);
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open)
|
||||||
|
active_rooms_.erase(active_rooms_.Data + n);
|
||||||
|
else
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditor::DrawDungeonCanvas(int room_id) {
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
gui::InputHexByte("Layout", &rooms_[room_id].layout);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
gui::InputHexByte("Blockset", &rooms_[room_id].blockset);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
gui::InputHexByte("Spriteset", &rooms_[room_id].spriteset);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
gui::InputHexByte("Palette", &rooms_[room_id].palette);
|
||||||
|
|
||||||
|
gui::InputHexByte("Floor1", &rooms_[room_id].floor1);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
gui::InputHexByte("Floor2", &rooms_[room_id].floor2);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
gui::InputHexWord("Message ID", &rooms_[room_id].message_id_);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
canvas_.DrawBackground();
|
||||||
|
canvas_.DrawContextMenu();
|
||||||
|
canvas_.DrawGrid();
|
||||||
|
canvas_.DrawOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
void DungeonEditor::DrawRoomGraphics() {
|
void DungeonEditor::DrawRoomGraphics() {
|
||||||
const auto height = 0x40;
|
const auto height = 0x40;
|
||||||
room_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1));
|
room_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1));
|
||||||
@@ -301,6 +306,9 @@ void DungeonEditor::DrawObjectRenderer() {
|
|||||||
for (const auto object_name : zelda3::dungeon::Type1RoomObjectNames) {
|
for (const auto object_name : zelda3::dungeon::Type1RoomObjectNames) {
|
||||||
if (ImGui::Selectable(object_name.data(), selected_object == i)) {
|
if (ImGui::Selectable(object_name.data(), selected_object == i)) {
|
||||||
selected_object = i;
|
selected_object = i;
|
||||||
|
object_renderer_.LoadObject(i);
|
||||||
|
rom()->RenderBitmap(object_renderer_.bitmap());
|
||||||
|
object_loaded_ = true;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@@ -312,11 +320,14 @@ void DungeonEditor::DrawObjectRenderer() {
|
|||||||
ImGui::BeginChild("DungeonObjectCanvas", ImVec2(276, 0x10 * 0x40 + 1),
|
ImGui::BeginChild("DungeonObjectCanvas", ImVec2(276, 0x10 * 0x40 + 1),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
dungeon_object_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1));
|
object_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1));
|
||||||
dungeon_object_canvas_.DrawContextMenu();
|
object_canvas_.DrawContextMenu();
|
||||||
dungeon_object_canvas_.DrawTileSelector(32);
|
object_canvas_.DrawTileSelector(32);
|
||||||
dungeon_object_canvas_.DrawGrid(32.0f);
|
// if (object_loaded_) {
|
||||||
dungeon_object_canvas_.DrawOverlay();
|
// object_canvas_.DrawBitmap(*object_renderer_.bitmap(), 0, 0);
|
||||||
|
// }
|
||||||
|
object_canvas_.DrawGrid(32.0f);
|
||||||
|
object_canvas_.DrawOverlay();
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class DungeonEditor : public Editor,
|
|||||||
uint16_t current_room_id_ = 0;
|
uint16_t current_room_id_ = 0;
|
||||||
bool is_loaded_ = false;
|
bool is_loaded_ = false;
|
||||||
bool show_object_render_ = false;
|
bool show_object_render_ = false;
|
||||||
|
bool object_loaded_ = false;
|
||||||
|
|
||||||
gfx::Bitmap room_gfx_bmp_;
|
gfx::Bitmap room_gfx_bmp_;
|
||||||
|
|
||||||
@@ -60,6 +61,11 @@ class DungeonEditor : public Editor,
|
|||||||
|
|
||||||
std::vector<zelda3::dungeon::Room> rooms_;
|
std::vector<zelda3::dungeon::Room> rooms_;
|
||||||
zelda3::dungeon::DungeonObjectRenderer object_renderer_;
|
zelda3::dungeon::DungeonObjectRenderer object_renderer_;
|
||||||
|
gui::Canvas canvas_;
|
||||||
|
gui::Canvas room_gfx_canvas_;
|
||||||
|
gui::Canvas object_canvas_;
|
||||||
|
|
||||||
|
std::vector<gfx::BitmapManager> room_graphics_;
|
||||||
|
|
||||||
enum BackgroundType {
|
enum BackgroundType {
|
||||||
kNoBackground,
|
kNoBackground,
|
||||||
@@ -73,13 +79,6 @@ class DungeonEditor : public Editor,
|
|||||||
int background_type_ = kNoBackground;
|
int background_type_ = kNoBackground;
|
||||||
int placement_type_ = kNoType;
|
int placement_type_ = kNoType;
|
||||||
|
|
||||||
gui::Canvas canvas_;
|
|
||||||
gui::Canvas room_gfx_canvas_;
|
|
||||||
|
|
||||||
gui::Canvas dungeon_object_canvas_;
|
|
||||||
|
|
||||||
std::vector<gfx::BitmapManager> room_graphics_;
|
|
||||||
|
|
||||||
ImGuiTableFlags toolset_table_flags_ =
|
ImGuiTableFlags toolset_table_flags_ =
|
||||||
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable |
|
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable |
|
||||||
ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable;
|
ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/compression.h"
|
#include "app/gfx/compression.h"
|
||||||
#include "app/gfx/scad_format.h"
|
#include "app/gfx/scad_format.h"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
#include "app/gui/canvas.h"
|
#include "app/gui/canvas.h"
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
#include "app/editor/graphics_editor.h"
|
#include "app/editor/graphics_editor.h"
|
||||||
#include "app/editor/modules/assembly_editor.h"
|
#include "app/editor/modules/assembly_editor.h"
|
||||||
#include "app/editor/overworld_editor.h"
|
#include "app/editor/overworld_editor.h"
|
||||||
#include "app/editor/resources/music_editor.h"
|
#include "app/editor/modules/music_editor.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/editor/screen_editor.h"
|
#include "app/editor/screen_editor.h"
|
||||||
#include "app/editor/sprite_editor.h"
|
#include "app/editor/sprite_editor.h"
|
||||||
#include "app/emu/emulator.h"
|
#include "app/emu/emulator.h"
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
#include "app/editor/dungeon_editor.h"
|
#include "app/editor/dungeon_editor.h"
|
||||||
#include "app/editor/graphics_editor.h"
|
#include "app/editor/graphics_editor.h"
|
||||||
#include "app/editor/modules/assembly_editor.h"
|
#include "app/editor/modules/assembly_editor.h"
|
||||||
#include "app/editor/resources/music_editor.h"
|
#include "app/editor/modules/music_editor.h"
|
||||||
#include "app/editor/overworld_editor.h"
|
#include "app/editor/overworld_editor.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/editor/screen_editor.h"
|
#include "app/editor/screen_editor.h"
|
||||||
#include "app/editor/sprite_editor.h"
|
#include "app/editor/sprite_editor.h"
|
||||||
#include "app/emu/emulator.h"
|
#include "app/emu/emulator.h"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "app/core/editor.h"
|
#include "app/core/editor.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "app/core/editor.h"
|
#include "app/core/editor.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "app/core/editor.h"
|
#include "app/core/editor.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "app/core/editor.h"
|
#include "app/core/editor.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "app/core/pipeline.h"
|
#include "app/core/pipeline.h"
|
||||||
#include "app/editor/modules/gfx_group_editor.h"
|
#include "app/editor/modules/gfx_group_editor.h"
|
||||||
#include "app/editor/modules/tile16_editor.h"
|
#include "app/editor/modules/tile16_editor.h"
|
||||||
#include "app/editor/resources/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|||||||
@@ -623,18 +623,18 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags {
|
|||||||
void XCE();
|
void XCE();
|
||||||
|
|
||||||
// Memory access routines
|
// Memory access routines
|
||||||
uint8_t ReadByte(uint16_t address) const override {
|
uint8_t ReadByte(uint32_t address) const override {
|
||||||
auto value = memory.ReadByte(address);
|
auto value = memory.ReadByte(address);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
uint16_t ReadWord(uint16_t address) const override {
|
uint16_t ReadWord(uint32_t address) const override {
|
||||||
return memory.ReadWord(address);
|
return memory.ReadWord(address);
|
||||||
}
|
}
|
||||||
uint32_t ReadWordLong(uint16_t address) const override {
|
uint32_t ReadWordLong(uint32_t address) const override {
|
||||||
return memory.ReadWordLong(address);
|
return memory.ReadWordLong(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> ReadByteVector(uint16_t address,
|
std::vector<uint8_t> ReadByteVector(uint32_t address,
|
||||||
uint16_t size) const override {
|
uint16_t size) const override {
|
||||||
return memory.ReadByteVector(address, size);
|
return memory.ReadByteVector(address, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,11 +48,21 @@ void DrawMemoryWindow(Memory* memory) {
|
|||||||
// Display memory areas
|
// Display memory areas
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("ROM");
|
ImGui::Text("ROM Bank 0-63");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("0x000000");
|
ImGui::Text("0x8000");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("%d MB", memoryImpl->rom_.size());
|
ImGui::Text("128 KB");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("LoROM");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("ROM Bank 64-111");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("0x0000");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("64 KB");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("LoROM");
|
ImGui::Text("LoROM");
|
||||||
|
|
||||||
@@ -60,9 +70,39 @@ void DrawMemoryWindow(Memory* memory) {
|
|||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("RAM");
|
ImGui::Text("RAM");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("0x700000");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("64 KB");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("LoROM");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("System RAM (WRAM)");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("0x7E0000");
|
ImGui::Text("0x7E0000");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("%d KB", memoryImpl->ram_.size());
|
ImGui::Text("128 KB");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("LoROM");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("ROM Bank 128-191");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("0x8000");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("128 KB");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("LoROM");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("ROM Bank 192-255");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("0x0000");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("64 KB");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("LoROM");
|
ImGui::Text("LoROM");
|
||||||
}
|
}
|
||||||
@@ -109,7 +149,6 @@ void Emulator::Run() {
|
|||||||
ImGui::Button(ICON_MD_DOUBLE_ARROW);
|
ImGui::Button(ICON_MD_DOUBLE_ARROW);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Button(ICON_MD_SUBDIRECTORY_ARROW_RIGHT);
|
ImGui::Button(ICON_MD_SUBDIRECTORY_ARROW_RIGHT);
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
if (running_) {
|
if (running_) {
|
||||||
HandleEvents();
|
HandleEvents();
|
||||||
@@ -331,8 +370,9 @@ void Emulator::RenderCPUInstructionLog(
|
|||||||
ImGui::Checkbox("Show All Opcodes", &showAllOpcodes);
|
ImGui::Checkbox("Show All Opcodes", &showAllOpcodes);
|
||||||
|
|
||||||
// Instruction list
|
// Instruction list
|
||||||
ImGui::BeginChild("InstructionList", ImVec2(0, 0),
|
ImGui::BeginChild(
|
||||||
ImGuiChildFlags_AlwaysAutoResize);
|
"InstructionList", ImVec2(0, 0),
|
||||||
|
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY);
|
||||||
for (const auto& entry : instructionLog) {
|
for (const auto& entry : instructionLog) {
|
||||||
if (ShouldDisplay(entry, filterBuf, showAllOpcodes)) {
|
if (ShouldDisplay(entry, filterBuf, showAllOpcodes)) {
|
||||||
if (ImGui::Selectable(absl::StrFormat("%04X: %02X %s %s", entry.address,
|
if (ImGui::Selectable(absl::StrFormat("%04X: %02X %s %s", entry.address,
|
||||||
|
|||||||
@@ -109,10 +109,10 @@ constexpr uint32_t kOAMSize = 0x220;
|
|||||||
class Memory {
|
class Memory {
|
||||||
public:
|
public:
|
||||||
virtual ~Memory() = default;
|
virtual ~Memory() = default;
|
||||||
virtual uint8_t ReadByte(uint16_t address) const = 0;
|
virtual uint8_t ReadByte(uint32_t address) const = 0;
|
||||||
virtual uint16_t ReadWord(uint16_t address) const = 0;
|
virtual uint16_t ReadWord(uint32_t address) const = 0;
|
||||||
virtual uint32_t ReadWordLong(uint16_t address) const = 0;
|
virtual uint32_t ReadWordLong(uint32_t address) const = 0;
|
||||||
virtual std::vector<uint8_t> ReadByteVector(uint16_t address,
|
virtual std::vector<uint8_t> ReadByteVector(uint32_t address,
|
||||||
uint16_t length) const = 0;
|
uint16_t length) const = 0;
|
||||||
|
|
||||||
virtual void WriteByte(uint32_t address, uint8_t value) = 0;
|
virtual void WriteByte(uint32_t address, uint8_t value) = 0;
|
||||||
@@ -149,7 +149,7 @@ class MemoryImpl : public Memory, public Loggable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_.reserve(0x1000000); // 16 MB
|
memory_.resize(0x1000000); // 16 MB
|
||||||
|
|
||||||
const size_t ROM_CHUNK_SIZE = 0x8000; // 32 KB
|
const size_t ROM_CHUNK_SIZE = 0x8000; // 32 KB
|
||||||
const size_t SRAM_SIZE = 0x10000; // 64 KB
|
const size_t SRAM_SIZE = 0x10000; // 64 KB
|
||||||
@@ -229,25 +229,25 @@ class MemoryImpl : public Memory, public Loggable {
|
|||||||
memory_.begin() + kOAMStart + kOAMSize, oam_.begin());
|
memory_.begin() + kOAMStart + kOAMSize, oam_.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ReadByte(uint16_t address) const override {
|
uint8_t ReadByte(uint32_t address) const override {
|
||||||
uint32_t mapped_address = GetMappedAddress(address);
|
uint32_t mapped_address = GetMappedAddress(address);
|
||||||
NotifyObservers(mapped_address, /*data=*/0);
|
NotifyObservers(mapped_address, /*data=*/0);
|
||||||
return memory_.at(mapped_address);
|
return memory_.at(mapped_address);
|
||||||
}
|
}
|
||||||
uint16_t ReadWord(uint16_t address) const override {
|
uint16_t ReadWord(uint32_t address) const override {
|
||||||
uint32_t mapped_address = GetMappedAddress(address);
|
uint32_t mapped_address = GetMappedAddress(address);
|
||||||
NotifyObservers(mapped_address, /*data=*/0);
|
NotifyObservers(mapped_address, /*data=*/0);
|
||||||
return static_cast<uint16_t>(memory_.at(mapped_address)) |
|
return static_cast<uint16_t>(memory_.at(mapped_address)) |
|
||||||
(static_cast<uint16_t>(memory_.at(mapped_address + 1)) << 8);
|
(static_cast<uint16_t>(memory_.at(mapped_address + 1)) << 8);
|
||||||
}
|
}
|
||||||
uint32_t ReadWordLong(uint16_t address) const override {
|
uint32_t ReadWordLong(uint32_t address) const override {
|
||||||
uint32_t mapped_address = GetMappedAddress(address);
|
uint32_t mapped_address = GetMappedAddress(address);
|
||||||
NotifyObservers(mapped_address, /*data=*/0);
|
NotifyObservers(mapped_address, /*data=*/0);
|
||||||
return static_cast<uint32_t>(memory_.at(mapped_address)) |
|
return static_cast<uint32_t>(memory_.at(mapped_address)) |
|
||||||
(static_cast<uint32_t>(memory_.at(mapped_address + 1)) << 8) |
|
(static_cast<uint32_t>(memory_.at(mapped_address + 1)) << 8) |
|
||||||
(static_cast<uint32_t>(memory_.at(mapped_address + 2)) << 16);
|
(static_cast<uint32_t>(memory_.at(mapped_address + 2)) << 16);
|
||||||
}
|
}
|
||||||
std::vector<uint8_t> ReadByteVector(uint16_t address,
|
std::vector<uint8_t> ReadByteVector(uint32_t address,
|
||||||
uint16_t length) const override {
|
uint16_t length) const override {
|
||||||
uint32_t mapped_address = GetMappedAddress(address);
|
uint32_t mapped_address = GetMappedAddress(address);
|
||||||
NotifyObservers(mapped_address, /*data=*/0);
|
NotifyObservers(mapped_address, /*data=*/0);
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ class MockClock : public Clock {
|
|||||||
|
|
||||||
class MockMemory : public Memory {
|
class MockMemory : public Memory {
|
||||||
public:
|
public:
|
||||||
MOCK_CONST_METHOD1(ReadByte, uint8_t(uint16_t address));
|
MOCK_CONST_METHOD1(ReadByte, uint8_t(uint32_t address));
|
||||||
MOCK_CONST_METHOD1(ReadWord, uint16_t(uint16_t address));
|
MOCK_CONST_METHOD1(ReadWord, uint16_t(uint32_t address));
|
||||||
MOCK_CONST_METHOD1(ReadWordLong, uint32_t(uint16_t address));
|
MOCK_CONST_METHOD1(ReadWordLong, uint32_t(uint32_t address));
|
||||||
MOCK_METHOD(std::vector<uint8_t>, ReadByteVector,
|
MOCK_METHOD(std::vector<uint8_t>, ReadByteVector,
|
||||||
(uint16_t address, uint16_t length), (const, override));
|
(uint32_t address, uint16_t length), (const, override));
|
||||||
|
|
||||||
MOCK_METHOD2(WriteByte, void(uint32_t address, uint8_t value));
|
MOCK_METHOD2(WriteByte, void(uint32_t address, uint8_t value));
|
||||||
MOCK_METHOD2(WriteWord, void(uint32_t address, uint16_t value));
|
MOCK_METHOD2(WriteWord, void(uint32_t address, uint16_t value));
|
||||||
@@ -76,20 +76,20 @@ class MockMemory : public Memory {
|
|||||||
void Init() {
|
void Init() {
|
||||||
ON_CALL(*this, ReadByte(::testing::_))
|
ON_CALL(*this, ReadByte(::testing::_))
|
||||||
.WillByDefault(
|
.WillByDefault(
|
||||||
[this](uint16_t address) { return memory_.at(address); });
|
[this](uint32_t address) { return memory_.at(address); });
|
||||||
ON_CALL(*this, ReadWord(::testing::_))
|
ON_CALL(*this, ReadWord(::testing::_))
|
||||||
.WillByDefault([this](uint16_t address) {
|
.WillByDefault([this](uint32_t address) {
|
||||||
return static_cast<uint16_t>(memory_.at(address)) |
|
return static_cast<uint16_t>(memory_.at(address)) |
|
||||||
(static_cast<uint16_t>(memory_.at(address + 1)) << 8);
|
(static_cast<uint16_t>(memory_.at(address + 1)) << 8);
|
||||||
});
|
});
|
||||||
ON_CALL(*this, ReadWordLong(::testing::_))
|
ON_CALL(*this, ReadWordLong(::testing::_))
|
||||||
.WillByDefault([this](uint16_t address) {
|
.WillByDefault([this](uint32_t address) {
|
||||||
return static_cast<uint32_t>(memory_.at(address)) |
|
return static_cast<uint32_t>(memory_.at(address)) |
|
||||||
(static_cast<uint32_t>(memory_.at(address + 1)) << 8) |
|
(static_cast<uint32_t>(memory_.at(address + 1)) << 8) |
|
||||||
(static_cast<uint32_t>(memory_.at(address + 2)) << 16);
|
(static_cast<uint32_t>(memory_.at(address + 2)) << 16);
|
||||||
});
|
});
|
||||||
ON_CALL(*this, ReadByteVector(::testing::_, ::testing::_))
|
ON_CALL(*this, ReadByteVector(::testing::_, ::testing::_))
|
||||||
.WillByDefault([this](uint16_t address, uint16_t length) {
|
.WillByDefault([this](uint32_t address, uint16_t length) {
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
data.push_back(memory_.at(address + i));
|
data.push_back(memory_.at(address + i));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "app/emu/cpu.h"
|
#include "app/emu/cpu.h"
|
||||||
|
#include "app/emu/memory/memory.h"
|
||||||
#include "app/emu/video/ppu.h"
|
#include "app/emu/video/ppu.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
@@ -31,8 +32,9 @@ class DungeonObjectRenderer : public SharedROM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LoadObject(uint16_t objectId) {
|
void LoadObject(uint16_t objectId) {
|
||||||
|
rom_data_ = rom()->vector();
|
||||||
// Prepare the CPU and memory environment
|
// Prepare the CPU and memory environment
|
||||||
memory_.Initialize(rom()->vector());
|
memory_.Initialize(rom_data_);
|
||||||
|
|
||||||
// Fetch the subtype pointers for the given object ID
|
// Fetch the subtype pointers for the given object ID
|
||||||
auto subtypeInfo = FetchSubtypeInfo(objectId);
|
auto subtypeInfo = FetchSubtypeInfo(objectId);
|
||||||
@@ -44,11 +46,12 @@ class DungeonObjectRenderer : public SharedROM {
|
|||||||
RenderObject(subtypeInfo);
|
RenderObject(subtypeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::Bitmap* bitmap() { return &bitmap_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SubtypeInfo {
|
struct SubtypeInfo {
|
||||||
uint16_t subtypePtr;
|
uint32_t subtypePtr;
|
||||||
uint16_t routinePtr;
|
uint32_t routinePtr;
|
||||||
// Additional fields as needed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SubtypeInfo FetchSubtypeInfo(uint16_t objectId) {
|
SubtypeInfo FetchSubtypeInfo(uint16_t objectId) {
|
||||||
@@ -56,13 +59,19 @@ class DungeonObjectRenderer : public SharedROM {
|
|||||||
|
|
||||||
// Determine the subtype based on objectId
|
// Determine the subtype based on objectId
|
||||||
// Assuming subtype is determined by some bits in objectId; modify as needed
|
// Assuming subtype is determined by some bits in objectId; modify as needed
|
||||||
uint8_t subtype = (objectId >> 8) & 0xFF; // Example: top 8 bits
|
uint8_t subtype = 1; // Example: top 8 bits
|
||||||
|
|
||||||
// Based on the subtype, fetch the correct pointers
|
// Based on the subtype, fetch the correct pointers
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case 1: // Subtype 1
|
case 1: // Subtype 1
|
||||||
info.subtypePtr = core::subtype1_tiles + (objectId & 0xFF) * 2;
|
info.subtypePtr = core::subtype1_tiles + (objectId & 0xFF) * 2;
|
||||||
info.routinePtr = core::subtype1_tiles + 0x200 + (objectId & 0xFF) * 2;
|
info.routinePtr = core::subtype1_tiles + 0x200 + (objectId & 0xFF) * 2;
|
||||||
|
std::cout << "Subtype 1 " << std::hex << info.subtypePtr << std::endl;
|
||||||
|
info.routinePtr =
|
||||||
|
memory_.ReadWord(core::MapBankToWordAddress(0x01, info.routinePtr));
|
||||||
|
std::cout << "Subtype 1 " << std::hex << info.routinePtr << std::endl;
|
||||||
|
std::cout << "Subtype 1 " << std::hex << core::SnesToPc(info.routinePtr)
|
||||||
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
case 2: // Subtype 2
|
case 2: // Subtype 2
|
||||||
info.subtypePtr = core::subtype2_tiles + (objectId & 0x7F) * 2;
|
info.subtypePtr = core::subtype2_tiles + (objectId & 0x7F) * 2;
|
||||||
@@ -86,13 +95,57 @@ class DungeonObjectRenderer : public SharedROM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureObject(const SubtypeInfo& info) {
|
void ConfigureObject(const SubtypeInfo& info) {
|
||||||
// TODO: Use the information in info to set up the object's initial state
|
cpu.A = 0x00;
|
||||||
|
cpu.X = 0x00;
|
||||||
|
|
||||||
|
// Might need to set the height and width manually?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example:
|
||||||
|
* the STA $BF, $CD, $C2, $CE are the location of the object in the room
|
||||||
|
* $B2 is used for size loop
|
||||||
|
* so if object size is setted on 07 that draw code will be repeated 7 times
|
||||||
|
* and since Y is increasing by 4 it makes the object draw from left to right
|
||||||
|
|
||||||
|
RoomDraw_Rightwards2x2_1to15or32:
|
||||||
|
#_018B89: JSR RoomDraw_GetSize_1to15or32
|
||||||
|
|
||||||
|
.next
|
||||||
|
#_018B8C: JSR RoomDraw_Rightwards2x2
|
||||||
|
|
||||||
|
#_018B8F: DEC.b $B2
|
||||||
|
#_018B91: BNE .next
|
||||||
|
|
||||||
|
#_018B93: RTS
|
||||||
|
|
||||||
|
RoomDraw_Rightwards2x2:
|
||||||
|
#_019895: LDA.w RoomDrawObjectData+0,X
|
||||||
|
#_019898: STA.b [$BF],Y
|
||||||
|
|
||||||
|
#_01989A: LDA.w RoomDrawObjectData+2,X
|
||||||
|
#_01989D: STA.b [$CB],Y
|
||||||
|
|
||||||
|
#_01989F: LDA.w RoomDrawObjectData+4,X
|
||||||
|
#_0198A2: STA.b [$C2],Y
|
||||||
|
|
||||||
|
#_0198A4: LDA.w RoomDrawObjectData+6,X
|
||||||
|
#_0198A7: STA.b [$CE],Y
|
||||||
|
|
||||||
|
#_0198A9: INY
|
||||||
|
#_0198AA: INY
|
||||||
|
#_0198AB: INY
|
||||||
|
#_0198AC: INY
|
||||||
|
|
||||||
|
#_0198AD: RTS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
void RenderObject(const SubtypeInfo& info) {
|
void RenderObject(const SubtypeInfo& info) {
|
||||||
cpu.PC = info.routinePtr;
|
cpu.PC = info.routinePtr;
|
||||||
cpu.PB = 0x01;
|
cpu.PB = 0x01;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint8_t opcode = cpu.FetchByte();
|
uint8_t opcode = cpu.FetchByte();
|
||||||
cpu.ExecuteInstruction(opcode);
|
cpu.ExecuteInstruction(opcode);
|
||||||
@@ -103,12 +156,32 @@ class DungeonObjectRenderer : public SharedROM {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i > 50) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
UpdateObjectBitmap();
|
UpdateObjectBitmap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateObjectBitmap() {
|
void UpdateObjectBitmap() {
|
||||||
// TODO: Implement logic to transfer object draw data to the Bitmap
|
// Object draw data
|
||||||
|
uint8_t room_object_draw_data0 = memory_.ReadByte(0x7E00BF);
|
||||||
|
uint8_t room_object_draw_data1 = memory_.ReadByte(0x7E00CB);
|
||||||
|
uint8_t room_object_draw_data2 = memory_.ReadByte(0x7E00C2);
|
||||||
|
uint8_t room_object_draw_data3 = memory_.ReadByte(0x7E00CE);
|
||||||
|
|
||||||
|
// Used with Y to index the room object draw data
|
||||||
|
uint8_t size_loop = memory_.ReadByte(0x7E00B2);
|
||||||
|
|
||||||
|
// Update the bitmap with this data by copying the tiles from vram.
|
||||||
|
|
||||||
|
std::cout << "Object draw data: " << std::hex << (int)room_object_draw_data0
|
||||||
|
<< " " << (int)room_object_draw_data1 << " "
|
||||||
|
<< (int)room_object_draw_data2 << " "
|
||||||
|
<< (int)room_object_draw_data3 << std::endl;
|
||||||
|
std::cout << "Size loop: " << std::hex << (int)size_loop << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> rom_data_;
|
std::vector<uint8_t> rom_data_;
|
||||||
@@ -116,7 +189,7 @@ class DungeonObjectRenderer : public SharedROM {
|
|||||||
emu::ClockImpl clock_;
|
emu::ClockImpl clock_;
|
||||||
emu::CPU cpu{memory_, clock_};
|
emu::CPU cpu{memory_, clock_};
|
||||||
emu::PPU ppu{memory_, clock_};
|
emu::PPU ppu{memory_, clock_};
|
||||||
gfx::Bitmap bitmap;
|
gfx::Bitmap bitmap_;
|
||||||
PseudoVram vram_;
|
PseudoVram vram_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user