Dungeon graphics loaded per room

This commit is contained in:
scawful
2023-11-22 00:49:55 -05:00
parent 7a842d4669
commit e93ff212af
6 changed files with 199 additions and 229 deletions

View File

@@ -26,17 +26,9 @@ absl::Status DungeonEditor::Update() {
for (int i = 0; i < 0x100; i++) {
rooms_.emplace_back(zelda3::dungeon::Room(i));
rooms_[i].LoadHeader();
rooms_[i].LoadRoomFromROM();
if (flags()->kDrawDungeonRoomGraphics) {
rooms_[i].LoadRoomGraphics();
auto blocks = rooms_[i].blocks();
room_graphics_.emplace_back();
int current_sheet = 0;
for (auto& block : blocks) {
room_graphics_[i].CopyBitmap(rom()->bitmap_manager().GetBitmap(block),
current_sheet);
current_sheet += 1;
}
}
}
is_loaded_ = true;
@@ -68,7 +60,8 @@ absl::Status DungeonEditor::Update() {
void DungeonEditor::DrawRoomSelector() {
if (rom()->isLoaded()) {
ImGui::InputInt("Room ID", (int*)&current_room_id_, 1, 1);
gui::InputHexWord("Room ID", &current_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,
@@ -90,8 +83,6 @@ void DungeonEditor::DrawRoomSelector() {
void DungeonEditor::DrawDungeonTabView() {
static int next_tab_id = 0;
// Using ImGui Custom Tabs show each individual room the user selects from the
// Buttons above to open a canvas for each individual room.
if (ImGui::BeginTabBar("MyTabBar", kDungeonTabBarFlags)) {
// TODO: Manage the room that is being added to the tab bar.
if (ImGui::TabItemButton("##tabitem", kDungeonTabFlags)) {
@@ -154,19 +145,19 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) {
void DungeonEditor::DrawToolset() {
if (ImGui::BeginTable("DWToolset", 12, ImGuiTableFlags_SizingFixedFit,
ImVec2(0, 0))) {
ImGui::TableSetupColumn("#undoTool");
ImGui::TableSetupColumn("#redoTool");
ImGui::TableSetupColumn("#separator");
ImGui::TableSetupColumn("#anyTool");
TableSetupColumn("#undoTool");
TableSetupColumn("#redoTool");
TableSetupColumn("#separator");
TableSetupColumn("#anyTool");
ImGui::TableSetupColumn("#bg1Tool");
ImGui::TableSetupColumn("#bg2Tool");
ImGui::TableSetupColumn("#bg3Tool");
ImGui::TableSetupColumn("#separator");
ImGui::TableSetupColumn("#spriteTool");
ImGui::TableSetupColumn("#itemTool");
ImGui::TableSetupColumn("#doorTool");
ImGui::TableSetupColumn("#blockTool");
TableSetupColumn("#bg1Tool");
TableSetupColumn("#bg2Tool");
TableSetupColumn("#bg3Tool");
TableSetupColumn("#separator");
TableSetupColumn("#spriteTool");
TableSetupColumn("#itemTool");
TableSetupColumn("#doorTool");
TableSetupColumn("#blockTool");
ImGui::TableNextColumn();
if (ImGui::Button(ICON_MD_UNDO)) {
@@ -245,14 +236,30 @@ void DungeonEditor::DrawToolset() {
}
void DungeonEditor::DrawRoomGraphics() {
// room_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1));
// room_gfx_canvas_.DrawContextMenu();
// room_gfx_canvas_.DrawTileSelector(32);
// room_gfx_canvas_.DrawBitmap(room_gfx_bmp_, 2, is_loaded_);
// room_gfx_canvas_.DrawGrid(32.0f);
// room_gfx_canvas_.DrawOverlay();
core::GraphicsManagerCanvasPipeline(256, 0x10 * 0x40, 32, 0x10, 0, is_loaded_,
room_graphics_[current_room_id_]);
const auto height = 0x40;
room_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1));
room_gfx_canvas_.DrawContextMenu();
room_gfx_canvas_.DrawTileSelector(32);
if (is_loaded_) {
auto blocks = rooms_[current_room_id_].blocks();
int current_block = 0;
for (int block : blocks) {
auto bitmap = rom()->graphics_bin()[block];
int offset = height * (current_block + 1);
int top_left_y = room_gfx_canvas_.GetZeroPoint().y + 2;
if (current_block >= 1) {
top_left_y = room_gfx_canvas_.GetZeroPoint().y + height * current_block;
}
room_gfx_canvas_.GetDrawList()->AddImage(
(void*)bitmap.texture(),
ImVec2(room_gfx_canvas_.GetZeroPoint().x + 2, top_left_y),
ImVec2(room_gfx_canvas_.GetZeroPoint().x + 0x100,
room_gfx_canvas_.GetZeroPoint().y + offset));
current_block += 1;
}
}
room_gfx_canvas_.DrawGrid(32.0f);
room_gfx_canvas_.DrawOverlay();
}
void DungeonEditor::DrawTileSelector() {
@@ -282,10 +289,9 @@ void DungeonEditor::DrawObjectRenderer() {
ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter |
ImGuiTableFlags_BordersV,
ImVec2(0, 0))) {
ImGui::TableSetupColumn("Dungeon Objects",
ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x);
ImGui::TableSetupColumn("Canvas");
TableSetupColumn("Dungeon Objects", ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x);
TableSetupColumn("Canvas");
ImGui::TableNextColumn();
ImGui::BeginChild("DungeonObjectButtons", ImVec2(0, 0), true);

View File

@@ -150,12 +150,11 @@ class BitmapManager {
return bitmap;
}
std::shared_ptr<gfx::Bitmap> CopyBitmap(std::shared_ptr<gfx::Bitmap> bitmap,
int id) {
auto copy = std::make_shared<gfx::Bitmap>(bitmap->width(), bitmap->height(),
bitmap->depth(), bitmap->data());
bitmap_cache_[id] = copy;
return copy;
std::shared_ptr<gfx::Bitmap> CopyBitmap(const gfx::Bitmap &bitmap, int id) {
auto new_bitmap = std::make_shared<gfx::Bitmap>(
bitmap.width(), bitmap.height(), bitmap.depth(), bitmap.data());
bitmap_cache_[id] = new_bitmap;
return new_bitmap;
}
std::shared_ptr<gfx::Bitmap> operator[](int id) {

View File

@@ -91,9 +91,9 @@ void Room::LoadHeader() {
auto header_location = core::SnesToPc(address);
// bg2 = (Background2)((rom()->data()[header_location] >> 5) & 0x07);
bg2 = (Background2)((rom()->data()[header_location] >> 5) & 0x07);
// collision = (CollisionKey)((rom()->data()[header_location] >> 2) & 0x07);
// light = ((rom()->data()[header_location]) & 0x01) == 1;
light = ((rom()->data()[header_location]) & 0x01) == 1;
if (light) {
bg2 = Background2::DarkRoom;
@@ -137,13 +137,13 @@ void Room::LoadHeader() {
}
void Room::LoadRoomGraphics(uchar entrance_blockset) {
auto mainGfx = rom()->main_blockset_ids;
auto roomGfx = rom()->room_blockset_ids;
auto spriteGfx = rom()->spriteset_ids;
const auto& mainGfx = rom()->main_blockset_ids;
const auto& roomGfx = rom()->room_blockset_ids;
const auto& spriteGfx = rom()->spriteset_ids;
current_gfx16_.reserve(0x4000);
for (int i = 0; i < 8; i++) {
blocks_[i] = mainGfx[BackgroundTileset][i];
blocks_[i] = mainGfx[blockset][i];
if (i >= 6 && i <= 6) {
// 3-6
if (entrance_blockset != 0xFF) {
@@ -162,7 +162,7 @@ void Room::LoadRoomGraphics(uchar entrance_blockset) {
blocks_[10] = 115 + 6;
blocks_[11] = 115 + 7;
for (int i = 0; i < 4; i++) {
blocks_[12 + i] = (uchar)(spriteGfx[SpriteTileset + 64][i] + 115);
blocks_[12 + i] = (uchar)(spriteGfx[spriteset + 64][i] + 115);
} // 12-16 sprites
}
@@ -427,12 +427,15 @@ void Room::LoadRoomFromROM() {
message_id_ = messages_id_dungeon + (room_id_ * 2);
int hpos = core::SnesToPc((rom_data[kRoomHeaderPointerBank] << 16) |
header_pointer + (room_id_ * 2));
hpos++;
uchar b = rom_data[hpos];
int address = (rom()->data()[kRoomHeaderPointerBank] << 16) +
(rom()->data()[(header_pointer + 1) + (room_id_ * 2)] << 8) +
rom()->data()[(header_pointer) + (room_id_ * 2)];
Layer2Mode = (uchar)(b >> 5);
int hpos = core::SnesToPc(address);
hpos++;
uint8_t b = rom_data[hpos];
Layer2Mode = (b >> 5);
// TODO(@scawful): Make LayerMerging object.
// LayerMerging = LayerMergeType.ListOf[(b & 0x0C) >> 2];

View File

@@ -160,14 +160,14 @@ class Room : public SharedROM {
uint8_t staircase_plane[4];
uint8_t staircase_rooms[4];
uchar BackgroundTileset;
uchar SpriteTileset;
uchar Layer2Behavior;
uchar Palette;
uchar Floor1Graphics;
uchar Floor2Graphics;
uchar Layer2Mode;
std::array<uchar, 16> blocks_;
uint8_t BackgroundTileset;
uint8_t SpriteTileset;
uint8_t Layer2Behavior;
uint8_t Palette;
uint8_t Floor1Graphics;
uint8_t Floor2Graphics;
uint8_t Layer2Mode;
std::array<uint8_t, 16> blocks_;
std::array<uchar, 16> ChestList;
std::vector<zelda3::Sprite> sprites_;

View File

@@ -11,14 +11,14 @@ void RoomObject::DrawTile(Tile t, int xx, int yy,
std::vector<uint8_t>& tiles_bg2_buffer,
ushort tileUnder) {
bool preview = false;
if (width < xx + 8) {
width = xx + 8;
if (width_ < xx + 8) {
width_ = xx + 8;
}
if (height < yy + 8) {
height = yy + 8;
if (height_ < yy + 8) {
height_ = yy + 8;
}
if (preview) {
if (xx < 57 && yy < 57 && xx >= 0 && yy >= 0) {
if (xx < 0x39 && yy < 0x39 && xx >= 0 && yy >= 0) {
gfx::TileInfo ti; // t.GetTileInfo();
for (auto yl = 0; yl < 8; yl++) {
for (auto xl = 0; xl < 4; xl++) {
@@ -36,47 +36,51 @@ void RoomObject::DrawTile(Tile t, int xx, int yy,
// Formula information to get tile index position in the array.
//((ID / nbrofXtiles) * (imgwidth/2) + (ID - ((ID/16)*16) ))
int tx =
((ti.id_ / 16) * 512) + ((ti.id_ - ((ti.id_ / 16) * 16)) * 4);
auto pixel = current_gfx16[tx + (yl * 64) + xl];
int tx = ((ti.id_ / 0x10) * 0x200) +
((ti.id_ - ((ti.id_ / 0x10) * 0x10)) * 4);
auto pixel = current_gfx16[tx + (yl * 0x40) + xl];
// nx,ny = object position, xx,yy = tile position, xl,yl = pixel
// position
int index =
((xx / 8) * 8) + ((yy / 8) * 512) + ((mx * 2) + (my * 64));
((xx / 8) * 8) + ((yy / 8) * 0x200) + ((mx * 2) + (my * 0x40));
preview_object_data_[index + r ^ 1] =
(uint8_t)((pixel & 0x0F) + ti.palette_ * 16);
(uint8_t)((pixel & 0x0F) + ti.palette_ * 0x10);
preview_object_data_[index + r] =
(uint8_t)(((pixel >> 4) & 0x0F) + ti.palette_ * 16);
(uint8_t)(((pixel >> 4) & 0x0F) + ti.palette_ * 0x10);
}
}
}
} else {
if (((xx / 8) + nx + offsetX) + ((ny + offsetY + (yy / 8)) * 64) < 4096 &&
((xx / 8) + nx + offsetX) + ((ny + offsetY + (yy / 8)) * 64) >= 0) {
if (((xx / 8) + nx_ + offset_x_) + ((ny_ + offset_y_ + (yy / 8)) * 0x40) <
0x1000 &&
((xx / 8) + nx_ + offset_x_) + ((ny_ + offset_y_ + (yy / 8)) * 0x40) >=
0) {
ushort td = 0; // gfx::GetTilesInfo(); // TODO t.GetTileInfo()
// collisionPoint.Add(
// new Point(xx + ((nx + offsetX) * 8), yy + ((ny + +offsetY) * 8)));
if (Layer == 0 || (uint8_t)Layer == 2 || allBgs) {
if (tileUnder == tiles_bg1_buffer[((xx / 8) + offsetX + nx) +
((ny + offsetY + (yy / 8)) * 64)]) {
if (layer_ == 0 || (uint8_t)layer_ == 2 || all_bgs_) {
if (tileUnder ==
tiles_bg1_buffer[((xx / 8) + offset_x_ + nx_) +
((ny_ + offset_y_ + (yy / 8)) * 0x40)]) {
return;
}
tiles_bg1_buffer[((xx / 8) + offsetX + nx) +
((ny + offsetY + (yy / 8)) * 64)] = td;
tiles_bg1_buffer[((xx / 8) + offset_x_ + nx_) +
((ny_ + offset_y_ + (yy / 8)) * 0x40)] = td;
}
if ((uint8_t)Layer == 1 || allBgs) {
if (tileUnder == tiles_bg2_buffer[((xx / 8) + nx + offsetX) +
((ny + offsetY + (yy / 8)) * 64)]) {
if ((uint8_t)layer_ == 1 || all_bgs_) {
if (tileUnder ==
tiles_bg2_buffer[((xx / 8) + nx_ + offset_x_) +
((ny_ + offset_y_ + (yy / 8)) * 0x40)]) {
return;
}
tiles_bg2_buffer[((xx / 8) + nx) + offsetX +
((ny + offsetY + (yy / 8)) * 64)] = td;
tiles_bg2_buffer[((xx / 8) + nx_ + offset_x_) +
((ny_ + offset_y_ + (yy / 8)) * 0x40)] = td;
}
}
}

View File

@@ -87,61 +87,30 @@ class DungeonObjectRenderer : public SharedROM {
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.
}
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
cpu.PC = info.routinePtr;
cpu.PB = 0x01;
// 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)
// Check if the end of the routine is reached
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();
UpdateObjectBitmap();
}
// 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
void UpdateObjectBitmap() {
// TODO: Implement logic to transfer object draw data to the Bitmap
}
// 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_;
@@ -151,43 +120,6 @@ 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 {};
@@ -236,55 +168,55 @@ class RoomObject : public SharedROM {
enum LayerType { BG1 = 0, BG2 = 1, BG3 = 2 };
RoomObject(int16_t id, uint8_t x, uint8_t y, uint8_t size, uint8_t layer = 0)
: id(id),
: id_(id),
x_(x),
y_(y),
size_(size),
Layer(static_cast<LayerType>(layer)),
nx(x),
ny(y),
ox(x),
oy(y),
width(16),
height(16),
uniqueID(0) {}
layer_(static_cast<LayerType>(layer)),
nx_(x),
ny_(y),
ox_(x),
oy_(y),
width_(16),
height_(16),
unique_id_(0) {}
virtual void Draw() {
// ... Draw function implementation here
}
void getObjectSize() {
previousSize = size_;
void GetObjectSize() {
previous_size_ = size_;
size_ = 1;
// Draw();
getBaseSize();
GetBaseSize();
UpdateSize();
size_ = 2;
// Draw();
getSizeSized();
GetSizeSized();
UpdateSize();
size_ = previousSize;
// collisionPoint.clear();
size_ = previous_size_;
// collision_point_.clear();
}
void getBaseSize() {
basewidth = width;
baseheight = height;
void GetBaseSize() {
base_width_ = width_;
base_height_ = height_;
}
void getSizeSized() {
sizeheight = height - baseheight;
sizewidth = width - basewidth;
void GetSizeSized() {
size_height_ = height_ - base_height_;
size_width_ = width_ - base_width_;
}
// virtual void Draw() { collisionPoint.clear(); }
// virtual void Draw() { collision_point_.clear(); }
void UpdateSize() {
width = 8;
height = 8;
width_ = 8;
height_ = 8;
}
void addTiles(int nbr, int pos) {
void AddTiles(int nbr, int pos) {
auto rom_data = rom()->data();
for (int i = 0; i < nbr; i++) {
// tiles.push_back(
@@ -295,46 +227,46 @@ class RoomObject : public SharedROM {
void DrawTile(Tile t, int xx, int yy, std::vector<uint8_t>& current_gfx16,
std::vector<uint8_t>& tiles_bg1_buffer,
std::vector<uint8_t>& tiles_bg2_buffer,
ushort tileUnder = 0xFFFF);
ushort tile_under = 0xFFFF);
protected:
int16_t id;
int16_t id_;
uint8_t x_;
uint8_t y_;
uint8_t size_;
LayerType Layer;
LayerType layer_;
std::vector<uint8_t> preview_object_data_;
bool allBgs = false;
bool lit = false;
std::vector<gfx::Tile16> tiles;
int tileIndex = 0;
std::string name;
uint8_t nx;
uint8_t ny;
uint8_t ox;
uint8_t oy;
int width;
int height;
int basewidth;
int baseheight;
int sizewidth;
int sizeheight;
ObjectOption options = ObjectOption::Nothing;
int offsetX = 0;
int offsetY = 0;
bool diagonalFix = false;
bool selected = false;
int previewId = 0;
uint8_t previousSize = 0;
bool showRectangle = false;
// std::vector<Point> collisionPoint;
int uniqueID = 0;
uint8_t z = 0;
bool deleted = false;
bool all_bgs_ = false;
bool lit_ = false;
std::vector<gfx::Tile16> tiles_;
int tile_index_ = 0;
std::string name_;
uint8_t nx_;
uint8_t ny_;
uint8_t ox_;
uint8_t oy_;
int width_;
int height_;
int base_width_;
int base_height_;
int size_width_;
int size_height_;
ObjectOption options_ = ObjectOption::Nothing;
int offset_x_ = 0;
int offset_y_ = 0;
bool diagonal_fix_ = false;
bool selected_ = false;
int preview_id_ = 0;
uint8_t previous_size_ = 0;
bool show_rectangle_ = false;
// std::vector<Point> collision_point_;
int unique_id_ = 0;
uint8_t z_ = 0;
bool deleted_ = false;
};
class Subtype1 : public RoomObject {
@@ -355,7 +287,7 @@ class Subtype1 : public RoomObject {
static_cast<int16_t>(
(rom_data[core::subtype1_tiles + ((id & 0xFF) * 2) + 1] << 8) +
rom_data[core::subtype1_tiles + ((id & 0xFF) * 2)]);
addTiles(tile_count_, pos);
AddTiles(tile_count_, pos);
sort = (Sorting)(Sorting::Horizontal | Sorting::Wall);
}
@@ -368,33 +300,59 @@ class Subtype1 : public RoomObject {
}
};
class Subtype2_Multiple : public RoomObject {
class Subtype2 : public RoomObject {
public:
int tx = 0;
int ty = 0;
std::vector<Tile> tiles;
std::string name;
bool allBgs;
Sorting sort;
Subtype2_Multiple(int16_t id, uint8_t x, uint8_t y, uint8_t size,
uint8_t layer)
Subtype2(int16_t id, uint8_t x, uint8_t y, uint8_t size, uint8_t layer)
: RoomObject(id, x, y, size, layer) {
// ... Constructor implementation here
auto rom_data = rom()->data();
name = Type2RoomObjectNames[id & 0x7F];
int pos =
core::tile_address +
static_cast<int16_t>(
(rom_data[core::subtype2_tiles + ((id & 0x7F) * 2) + 1] << 8) +
rom_data[core::subtype2_tiles + ((id & 0x7F) * 2)]);
AddTiles(8, pos);
sort = (Sorting)(Sorting::Horizontal | Sorting::Wall);
}
void Draw() override {
// ... Draw function implementation here
for (int i = 0; i < 8; i++) {
// DrawTile(tiles[i], x_ * 8, (y_ + i) * 8);
}
}
void setdata(const std::string& name, int tx, int ty, bool allbg = false) {
// ... setdata function implementation here
}
// Other member functions and variables
};
class Subtype3 : public RoomObject {};
class Subtype3 : public RoomObject {
public:
std::vector<Tile> tiles;
std::string name;
bool allBgs;
Sorting sort;
Subtype3(int16_t id, uint8_t x, uint8_t y, uint8_t size, uint8_t layer)
: RoomObject(id, x, y, size, layer) {
auto rom_data = rom()->data();
name = Type3RoomObjectNames[id & 0xFF];
int pos =
core::tile_address +
static_cast<int16_t>(
(rom_data[core::subtype3_tiles + ((id & 0xFF) * 2) + 1] << 8) +
rom_data[core::subtype3_tiles + ((id & 0xFF) * 2)]);
AddTiles(8, pos);
sort = (Sorting)(Sorting::Horizontal | Sorting::Wall);
}
void Draw() override {
for (int i = 0; i < 8; i++) {
// DrawTile(tiles[i], x_ * 8, (y_ + i) * 8);
}
}
};
} // namespace dungeon
} // namespace zelda3