Add Debugger interface, RoomObject class

- Log instructions to debugger using experiment flag
- Use BitmapManager for more functionality
- Draw framebuffer and integrated debugger
This commit is contained in:
scawful
2023-11-13 14:51:01 -05:00
parent 75ef4fd9b0
commit 299770922c
27 changed files with 740 additions and 234 deletions

View File

@@ -78,6 +78,64 @@ void DrawDungeonRoomBG2(std::vector<uint8_t>& tiles_bg2_buffer,
}
}
void Room::LoadHeader() {
// Address of the room header
int headerPointer = (rom()->data()[core::room_header_pointer + 2] << 16) +
(rom()->data()[core::room_header_pointer + 1] << 8) +
(rom()->data()[core::room_header_pointer]);
headerPointer = core::SnesToPc(headerPointer);
int address = (rom()->data()[core::room_header_pointers_bank] << 16) +
(rom()->data()[(headerPointer + 1) + (room_id_ * 2)] << 8) +
rom()->data()[(headerPointer) + (room_id_ * 2)];
auto header_location = core::SnesToPc(address);
// bg2 = (Background2)((rom()->data()[header_location] >> 5) & 0x07);
// collision = (CollisionKey)((rom()->data()[header_location] >> 2) & 0x07);
// light = ((rom()->data()[header_location]) & 0x01) == 1;
if (light) {
bg2 = Background2::DarkRoom;
}
palette = ((rom()->data()[header_location + 1] & 0x3F));
blockset = (rom()->data()[header_location + 2]);
spriteset = (rom()->data()[header_location + 3]);
// effect = (EffectKey)((rom()->data()[header_location + 4]));
// tag1 = (TagKey)((rom()->data()[header_location + 5]));
// tag2 = (TagKey)((rom()->data()[header_location + 6]));
// holewarpPlane = ((rom()->data()[header_location + 7]) & 0x03);
staircase_plane[0] = ((rom()->data()[header_location + 7] >> 2) & 0x03);
staircase_plane[1] = ((rom()->data()[header_location + 7] >> 4) & 0x03);
staircase_plane[2] = ((rom()->data()[header_location + 7] >> 6) & 0x03);
staircase_plane[3] = ((rom()->data()[header_location + 8]) & 0x03);
// if (holewarpPlane == 2) {
// Console::WriteLine("Room Index Plane 1 : Used in room id = " +
// index.ToString("X2"));
// } else if (staircasePlane[0] == 2) {
// Console::WriteLine("Room Index Plane 1 : Used in room id = " +
// index.ToString("X2"));
// } else if (staircasePlane[1] == 2) {
// Console::WriteLine("Room Index Plane 1 : Used in room id = " +
// index.ToString("X2"));
// } else if (staircasePlane[2] == 2) {
// Console::WriteLine("Room Index Plane 1 : Used in room id = " +
// index.ToString("X2"));
// } else if (staircasePlane[3] == 2) {
// Console::WriteLine("Room Index Plane 1 : Used in room id = " +
// index.ToString("X2"));
// }
// holewarp = (rom()->data()[header_location + 9]);
staircase_rooms[0] = (rom()->data()[header_location + 10]);
staircase_rooms[1] = (rom()->data()[header_location + 11]);
staircase_rooms[2] = (rom()->data()[header_location + 12]);
staircase_rooms[3] = (rom()->data()[header_location + 13]);
}
void Room::LoadSprites() {
auto rom_data = rom()->vector();
int spritePointer = (0x04 << 16) + (rom_data[rooms_sprite_pointer + 1] << 8) +
@@ -295,6 +353,10 @@ RoomObject Room::AddObject(short oid, uint8_t x, uint8_t y, uint8_t size,
}
void Room::LoadRoomGraphics(uchar entrance_blockset) {
auto mainGfx = rom()->main_blockset_ids;
auto roomGfx = rom()->room_blockset_ids;
auto spriteGfx = rom()->spriteset_ids;
for (int i = 0; i < 8; i++) {
blocks[i] = mainGfx[BackgroundTileset][i];
if (i >= 6 && i <= 6) {

View File

@@ -80,6 +80,8 @@ void DrawDungeonRoomBG2(std::vector<uint8_t>& tiles_bg2_buffer,
class DungeonDestination {
public:
DungeonDestination() = default;
~DungeonDestination() = default;
DungeonDestination(uint8_t i) : Index(i) {}
uint8_t Index;
@@ -89,6 +91,7 @@ class DungeonDestination {
};
struct object_door {
object_door() = default;
object_door(short id, uint8_t x, uint8_t y, uint8_t size, uint8_t layer)
: id_(id), x_(x), y_(y), size_(size), layer_(layer) {}
@@ -101,6 +104,7 @@ struct object_door {
};
struct ChestData {
ChestData() = default;
ChestData(uchar i, bool s) : id_(i), size_(s){};
uchar id_;
@@ -111,6 +115,10 @@ struct StaircaseRooms {};
class Room : public SharedROM {
public:
Room() = default;
Room(int room_id) : room_id_(room_id) {}
~Room() = default;
void LoadHeader();
void LoadSprites();
void LoadChests();
@@ -124,19 +132,29 @@ class Room : public SharedROM {
void LoadRoomFromROM();
uint8_t floor1 = 0;
uint8_t floor2 = 0;
uint8_t blockset = 0;
uint8_t spriteset = 0;
uint8_t palette = 0;
uint8_t layout = 0;
uint16_t message_id_ = 0;
gfx::Bitmap current_graphics_;
private:
int animated_frame = 0;
int room_id_ = 0;
uint8_t floor1;
uint8_t floor2;
uint8_t blockset;
uint8_t spriteset;
uint8_t palette;
uint8_t layout;
bool light;
bool is_loaded_ = false;
Background2 bg2;
uint8_t staircase_plane[4];
uint8_t staircase_rooms[4];
ushort message_id_ = 0;
uchar BackgroundTileset;
uchar SpriteTileset;
uchar Layer2Behavior;
@@ -147,11 +165,6 @@ class Room : public SharedROM {
std::array<uchar, 16> blocks;
std::array<uchar, 16> ChestList;
uint8_t mainGfx[37][8];
uint8_t roomGfx[82][4];
uint8_t spriteGfx[144][4];
uint8_t paletteGfx[72][4];
std::vector<zelda3::Sprite> sprites_;
std::vector<StaircaseRooms> staircaseRooms;
@@ -171,8 +184,6 @@ class Room : public SharedROM {
std::vector<ChestData> chests_in_room;
std::vector<uint8_t> current_gfx16_;
std::vector<RoomObject> tilesObjects;
gfx::Bitmap current_graphics_;
};
} // namespace dungeon

View File

@@ -7,6 +7,8 @@
#include <string>
#include <vector>
#include "app/emu/cpu.h"
#include "app/emu/video/ppu.h"
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
@@ -17,6 +19,61 @@ namespace app {
namespace zelda3 {
namespace dungeon {
class DungeonObjectRenderer : public SharedROM {
public:
struct PseudoVram {
std::vector<gfx::Bitmap> sheets;
};
void CreateVramFromRoomBlockset() {
auto bitmap_manager = rom()->BitmapManager();
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());
}
}
void RenderObjectsAsBitmaps() {
auto subtype1_ptr = core::subtype1_tiles;
auto subtype1_routine_ptr =
core::subtype1_tiles + 0x200; // Where the draw routines start
auto subtype2_ptr = core::subtype2_tiles;
auto subtype2_routine_ptr =
core::subtype2_tiles + 0x80; // Where the draw routines start
auto subtype3_ptr = core::subtype3_tiles;
auto subtype3_routine_ptr =
core::subtype3_tiles + 0x100; // Where the draw routines start
auto data = (*rom()).vector();
// Construct a copy of the rooms VRAM
// Jump to the routine that draws the object based on the ID
// Run the routine and get the VRAM data using the CPU and PPU
// Render the VRAM data to a bitmap
memory_.Initialize(data);
cpu.PC = subtype1_routine_ptr;
cpu.JMP(cpu.FetchWord());
auto dest = cpu.PC + 0x10;
while (cpu.PC < dest) {
cpu.ExecuteInstruction(cpu.FetchByte());
}
}
emu::MemoryImpl memory_;
emu::ClockImpl clock_;
emu::CPU cpu{memory_, clock_};
emu::PPU ppu{memory_, clock_};
gfx::Bitmap bitmap;
PseudoVram vram_;
};
enum class SpecialObjectType { Chest, BigChest, InterroomStairs };
struct Tile {};
@@ -223,9 +280,7 @@ class Subtype2_Multiple : public RoomObject {
// Other member functions and variables
};
class Subtype3 : public RoomObject {
};
class Subtype3 : public RoomObject {};
} // namespace dungeon
} // namespace zelda3

View File

@@ -11,6 +11,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "app/core/constants.h"
#include "app/core/common.h"
#include "app/gfx/bitmap.h"
#include "app/gfx/compression.h"
#include "app/gfx/snes_tile.h"