Dungeon Room Object refactor

This commit is contained in:
scawful
2024-01-10 23:14:49 -05:00
parent 9ba6af9c4c
commit 08b95df7ad
5 changed files with 196 additions and 190 deletions

View File

@@ -424,7 +424,7 @@ void Ppu::ApplyEffects() {}
void Ppu::ComposeLayers() {} void Ppu::ComposeLayers() {}
void Ppu::DisplayFrameBuffer() { void Ppu::DisplayFrameBuffer() {
if (!screen_->IsActive()) { if (!screen_->is_active()) {
screen_->Create(256, 240, 24, frame_buffer_); screen_->Create(256, 240, 24, frame_buffer_);
rom()->RenderBitmap(screen_.get()); rom()->RenderBitmap(screen_.get());
} }

View File

@@ -273,7 +273,7 @@ class Ppu : public Observer, public SharedROM {
clock_.SetFrequency(kPpuClockSpeed); clock_.SetFrequency(kPpuClockSpeed);
frame_buffer_.resize(256 * 240, 0); frame_buffer_.resize(256 * 240, 0);
screen_ = std::make_shared<gfx::Bitmap>(256, 240, 8, 0x100); screen_ = std::make_shared<gfx::Bitmap>(256, 240, 8, 0x100);
screen_->SetActive(false); screen_->set_active(false);
} }
// Resets the PPU to its initial state // Resets the PPU to its initial state

View File

@@ -173,7 +173,7 @@ class DungeonObjectRenderer : public SharedROM {
// Iterate over tilemap in memory to read tile IDs // Iterate over tilemap in memory to read tile IDs
for (int tile_index = 0; tile_index < 512; tile_index++) { for (int tile_index = 0; tile_index < 512; tile_index++) {
// Read the tile ID from memory // Read the tile ID from memory
int tile_id = memory_.ReadWord(0x7E4000 + tile_index); int tile_id = memory_.ReadWord(0x7E2000 + tile_index);
int sheet_number = tile_id / 32; int sheet_number = tile_id / 32;
int local_id = tile_id % 32; int local_id = tile_id % 32;
@@ -190,7 +190,8 @@ class DungeonObjectRenderer : public SharedROM {
sheet->Get8x8Tile(tile_id, x, y, tilemap_, tilemap_offset); sheet->Get8x8Tile(tile_id, x, y, tilemap_, tilemap_offset);
} }
bitmap_.Create(256, 256, 8, tilemap_); bitmap_.mutable_data() = tilemap_;
bitmap_.Create(256, 256, 8, tilemap_.size());
} }
std::vector<uint8_t> tilemap_; std::vector<uint8_t> tilemap_;

View File

@@ -31,12 +31,12 @@ void Room::LoadHeader() {
auto header_location = core::SnesToPc(address); 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); // collision = (CollisionKey)((rom()->data()[header_location] >> 2) & 0x07);
light = ((rom()->data()[header_location]) & 0x01) == 1; is_light_ = ((rom()->data()[header_location]) & 0x01) == 1;
if (light) { if (is_light_) {
bg2 = Background2::DarkRoom; bg2_ = Background2::DarkRoom;
} }
palette = ((rom()->data()[header_location + 1] & 0x3F)); palette = ((rom()->data()[header_location + 1] & 0x3F));
@@ -46,16 +46,88 @@ void Room::LoadHeader() {
// tag1 = (TagKey)((rom()->data()[header_location + 5])); // tag1 = (TagKey)((rom()->data()[header_location + 5]));
// tag2 = (TagKey)((rom()->data()[header_location + 6])); // tag2 = (TagKey)((rom()->data()[header_location + 6]));
staircase_plane[0] = ((rom()->data()[header_location + 7] >> 2) & 0x03); staircase_plane_[0] = ((rom()->data()[header_location + 7] >> 2) & 0x03);
staircase_plane[1] = ((rom()->data()[header_location + 7] >> 4) & 0x03); staircase_plane_[1] = ((rom()->data()[header_location + 7] >> 4) & 0x03);
staircase_plane[2] = ((rom()->data()[header_location + 7] >> 6) & 0x03); staircase_plane_[2] = ((rom()->data()[header_location + 7] >> 6) & 0x03);
staircase_plane[3] = ((rom()->data()[header_location + 8]) & 0x03); staircase_plane_[3] = ((rom()->data()[header_location + 8]) & 0x03);
holewarp = (rom()->data()[header_location + 9]); holewarp = (rom()->data()[header_location + 9]);
staircase_rooms[0] = (rom()->data()[header_location + 10]); staircase_rooms_[0] = (rom()->data()[header_location + 10]);
staircase_rooms[1] = (rom()->data()[header_location + 11]); staircase_rooms_[1] = (rom()->data()[header_location + 11]);
staircase_rooms[2] = (rom()->data()[header_location + 12]); staircase_rooms_[2] = (rom()->data()[header_location + 12]);
staircase_rooms[3] = (rom()->data()[header_location + 13]); staircase_rooms_[3] = (rom()->data()[header_location + 13]);
}
void Room::LoadRoomFromROM() {
// Load dungeon header
auto rom_data = rom()->vector();
int header_pointer = core::SnesToPc(kRoomHeaderPointer);
message_id_ = messages_id_dungeon + (room_id_ * 2);
int address = (rom()->data()[kRoomHeaderPointerBank] << 16) +
(rom()->data()[(header_pointer + 1) + (room_id_ * 2)] << 8) +
rom()->data()[(header_pointer) + (room_id_ * 2)];
int hpos = core::SnesToPc(address);
hpos++;
uint8_t b = rom_data[hpos];
layer2_mode_ = (b >> 5);
// TODO(@scawful): Make LayerMerging object.
// LayerMerging = LayerMergeType.ListOf[(b & 0x0C) >> 2];
is_dark_ = (b & 0x01) == 0x01;
hpos++;
palette_ = rom_data[hpos];
hpos++;
background_tileset_ = rom_data[hpos];
hpos++;
sprite_tileset_ = rom_data[hpos];
hpos++;
layer2_behavior_ = rom_data[hpos];
hpos++;
tag1_ = rom_data[hpos];
hpos++;
tag2_ = rom_data[hpos];
hpos++;
b = rom_data[hpos];
pits_.TargetLayer = (uchar)(b & 0x03);
stair1_.TargetLayer = (uchar)((b >> 2) & 0x03);
stair2_.TargetLayer = (uchar)((b >> 4) & 0x03);
stair3_.TargetLayer = (uchar)((b >> 6) & 0x03);
hpos++;
stair4_.TargetLayer = (uchar)(rom_data[hpos] & 0x03);
hpos++;
pits_.Target = rom_data[hpos];
hpos++;
stair1_.Target = rom_data[hpos];
hpos++;
stair2_.Target = rom_data[hpos];
hpos++;
stair3_.Target = rom_data[hpos];
hpos++;
stair4_.Target = rom_data[hpos];
hpos++;
// Load room objects
// int objectPointer = core::SnesToPc(room_object_pointer);
// int room_address = objectPointer + (room_id_ * 3);
// int objects_location = core::SnesToPc(room_address);
// Load sprites
// int spr_ptr = 0x040000 | rooms_sprite_pointer;
// int sprite_address =
// core::SnesToPc(dungeon_spr_ptrs | spr_ptr + (room_id_ * 2));
} }
void Room::LoadRoomGraphics(uchar entrance_blockset) { void Room::LoadRoomGraphics(uchar entrance_blockset) {
@@ -125,89 +197,19 @@ void Room::LoadAnimatedGraphics() {
auto rom_data = rom()->vector(); auto rom_data = rom()->vector();
int data = 0; int data = 0;
while (data < 512) { while (data < 512) {
uchar mapByte = uchar map_byte =
gfx_buffer_data[data + (92 * 2048) + (512 * animated_frame)]; gfx_buffer_data[data + (92 * 2048) + (512 * animated_frame_)];
current_gfx16_[data + (7 * 2048)] = mapByte; current_gfx16_[data + (7 * 2048)] = map_byte;
mapByte = map_byte =
gfx_buffer_data[data + (rom_data[gfx_ptr + BackgroundTileset] * 2048) + gfx_buffer_data[data +
(512 * animated_frame)]; (rom_data[gfx_ptr + background_tileset_] * 2048) +
current_gfx16_[data + (7 * 2048) - 512] = mapByte; (512 * animated_frame_)];
current_gfx16_[data + (7 * 2048) - 512] = map_byte;
data++; data++;
} }
} }
void Room::LoadSprites() {
auto rom_data = rom()->vector();
int spritePointer = (0x04 << 16) + (rom_data[rooms_sprite_pointer + 1] << 8) +
(rom_data[rooms_sprite_pointer]);
int sprite_address_snes =
(0x09 << 16) + (rom_data[spritePointer + (room_id_ * 2) + 1] << 8) +
rom_data[spritePointer + (room_id_ * 2)];
int sprite_address = core::SnesToPc(sprite_address_snes);
bool sortsprites = rom_data[sprite_address] == 1;
sprite_address += 1;
while (true) {
uint8_t b1 = rom_data[sprite_address];
uint8_t b2 = rom_data[sprite_address + 1];
uint8_t b3 = rom_data[sprite_address + 2];
if (b1 == 0xFF) {
break;
}
// sprites_.emplace_back(this, b3, (b2 & 0x1F), (b1 & 0x1F),
// ((b2 & 0xE0) >> 5) + ((b1 & 0x60) >> 2),
// (b1 & 0x80) >> 7);
if (sprites_.size() > 1) {
Sprite& spr = sprites_.back();
Sprite& prevSprite = sprites_[sprites_.size() - 2];
if (spr.id() == 0xE4 && spr.x() == 0x00 && spr.y() == 0x1E &&
spr.layer() == 1 && spr.subtype() == 0x18) {
// prevSprite.keyDrop() = 1;
sprites_.pop_back();
}
if (spr.id() == 0xE4 && spr.x() == 0x00 && spr.y() == 0x1D &&
spr.layer() == 1 && spr.subtype() == 0x18) {
// prevSprite.keyDrop() = 2;
sprites_.pop_back();
}
}
sprite_address += 3;
}
}
void Room::LoadChests() {
auto rom_data = rom()->vector();
int cpos = (rom_data[chests_data_pointer1 + 2] << 16) +
(rom_data[chests_data_pointer1 + 1] << 8) +
(rom_data[chests_data_pointer1]);
cpos = core::SnesToPc(cpos);
int clength = (rom_data[chests_length_pointer + 1] << 8) +
(rom_data[chests_length_pointer]);
for (int i = 0; i < clength; i++) {
if ((((rom_data[cpos + (i * 3) + 1] << 8) + (rom_data[cpos + (i * 3)])) &
0x7FFF) == room_id_) {
// There's a chest in that room !
bool big = false;
if ((((rom_data[cpos + (i * 3) + 1] << 8) + (rom_data[cpos + (i * 3)])) &
0x8000) == 0x8000) // ?????
{
big = true;
}
chests_in_room.emplace_back(ChestData(rom_data[cpos + (i * 3) + 2], big));
}
}
}
void Room::LoadObjects() { void Room::LoadObjects() {
auto rom_data = rom()->vector(); auto rom_data = rom()->vector();
int objectPointer = (rom_data[room_object_pointer + 2] << 16) + int objectPointer = (rom_data[room_object_pointer + 2] << 16) +
@@ -225,16 +227,17 @@ void Room::LoadObjects() {
std::cout << "Room ID : " << room_id_ << std::endl; std::cout << "Room ID : " << room_id_ << std::endl;
} }
if (floor) { if (is_floor_) {
floor1 = static_cast<uint8_t>(rom_data[objects_location] & 0x0F); floor1_graphics_ = static_cast<uint8_t>(rom_data[objects_location] & 0x0F);
floor2 = static_cast<uint8_t>((rom_data[objects_location] >> 4) & 0x0F); floor2_graphics_ =
static_cast<uint8_t>((rom_data[objects_location] >> 4) & 0x0F);
} }
layout = static_cast<uint8_t>((rom_data[objects_location + 1] >> 2) & 0x07); layout = static_cast<uint8_t>((rom_data[objects_location + 1] >> 2) & 0x07);
LoadChests(); LoadChests();
staircaseRooms.clear(); staircase_rooms_vec_.clear();
int nbr_of_staircase = 0; int nbr_of_staircase = 0;
int pos = objects_location + 2; int pos = objects_location + 2;
@@ -314,7 +317,7 @@ void Room::LoadObjects() {
if (nbr_of_staircase < 4) { if (nbr_of_staircase < 4) {
tilesObjects.back().options |= ObjectOption::Stairs; tilesObjects.back().options |= ObjectOption::Stairs;
staircaseRooms.push_back(StaircaseRoom( staircaseRooms.push_back(StaircaseRoom(
posX, posY, "To " + staircase_rooms[nbr_of_staircase])); posX, posY, "To " + staircase_rooms_[nbr_of_staircase]));
nbr_of_staircase++; nbr_of_staircase++;
} else { } else {
tilesObjects.back().options |= ObjectOption::Stairs; tilesObjects.back().options |= ObjectOption::Stairs;
@@ -348,76 +351,76 @@ void Room::LoadObjects() {
} }
} }
void Room::LoadRoomFromROM() { void Room::LoadSprites() {
// Load dungeon header
auto rom_data = rom()->vector(); auto rom_data = rom()->vector();
int header_pointer = core::SnesToPc(kRoomHeaderPointer); int spritePointer = (0x04 << 16) + (rom_data[rooms_sprite_pointer + 1] << 8) +
(rom_data[rooms_sprite_pointer]);
int sprite_address_snes =
(0x09 << 16) + (rom_data[spritePointer + (room_id_ * 2) + 1] << 8) +
rom_data[spritePointer + (room_id_ * 2)];
message_id_ = messages_id_dungeon + (room_id_ * 2); int sprite_address = core::SnesToPc(sprite_address_snes);
bool sortsprites = rom_data[sprite_address] == 1;
sprite_address += 1;
int address = (rom()->data()[kRoomHeaderPointerBank] << 16) + while (true) {
(rom()->data()[(header_pointer + 1) + (room_id_ * 2)] << 8) + uint8_t b1 = rom_data[sprite_address];
rom()->data()[(header_pointer) + (room_id_ * 2)]; uint8_t b2 = rom_data[sprite_address + 1];
uint8_t b3 = rom_data[sprite_address + 2];
int hpos = core::SnesToPc(address); if (b1 == 0xFF) {
hpos++; break;
uint8_t b = rom_data[hpos]; }
Layer2Mode = (b >> 5); // sprites_.emplace_back(this, b3, (b2 & 0x1F), (b1 & 0x1F),
// TODO(@scawful): Make LayerMerging object. // ((b2 & 0xE0) >> 5) + ((b1 & 0x60) >> 2),
// LayerMerging = LayerMergeType.ListOf[(b & 0x0C) >> 2]; // (b1 & 0x80) >> 7);
IsDark = (b & 0x01) == 0x01; if (sprites_.size() > 1) {
hpos++; Sprite& spr = sprites_.back();
Sprite& prevSprite = sprites_[sprites_.size() - 2];
Palette = rom_data[hpos]; if (spr.id() == 0xE4 && spr.x() == 0x00 && spr.y() == 0x1E &&
hpos++; spr.layer() == 1 && spr.subtype() == 0x18) {
// prevSprite.keyDrop() = 1;
sprites_.pop_back();
}
BackgroundTileset = rom_data[hpos]; if (spr.id() == 0xE4 && spr.x() == 0x00 && spr.y() == 0x1D &&
hpos++; spr.layer() == 1 && spr.subtype() == 0x18) {
// prevSprite.keyDrop() = 2;
sprites_.pop_back();
}
}
SpriteTileset = rom_data[hpos]; sprite_address += 3;
hpos++; }
}
Layer2Behavior = rom_data[hpos]; void Room::LoadChests() {
hpos++; auto rom_data = rom()->vector();
int cpos = (rom_data[chests_data_pointer1 + 2] << 16) +
(rom_data[chests_data_pointer1 + 1] << 8) +
(rom_data[chests_data_pointer1]);
cpos = core::SnesToPc(cpos);
int clength = (rom_data[chests_length_pointer + 1] << 8) +
(rom_data[chests_length_pointer]);
Tag1 = rom_data[hpos]; for (int i = 0; i < clength; i++) {
hpos++; if ((((rom_data[cpos + (i * 3) + 1] << 8) + (rom_data[cpos + (i * 3)])) &
0x7FFF) == room_id_) {
// There's a chest in that room !
bool big = false;
if ((((rom_data[cpos + (i * 3) + 1] << 8) + (rom_data[cpos + (i * 3)])) &
0x8000) == 0x8000) // ?????
{
big = true;
}
Tag2 = rom_data[hpos]; chests_in_room_.emplace_back(
hpos++; ChestData(rom_data[cpos + (i * 3) + 2], big));
}
b = rom_data[hpos]; }
Pits.TargetLayer = (uchar)(b & 0x03);
Stair1.TargetLayer = (uchar)((b >> 2) & 0x03);
Stair2.TargetLayer = (uchar)((b >> 4) & 0x03);
Stair3.TargetLayer = (uchar)((b >> 6) & 0x03);
hpos++;
Stair4.TargetLayer = (uchar)(rom_data[hpos] & 0x03);
hpos++;
Pits.Target = rom_data[hpos];
hpos++;
Stair1.Target = rom_data[hpos];
hpos++;
Stair2.Target = rom_data[hpos];
hpos++;
Stair3.Target = rom_data[hpos];
hpos++;
Stair4.Target = rom_data[hpos];
hpos++;
// Load room objects
// int objectPointer = core::SnesToPc(room_object_pointer);
// int room_address = objectPointer + (room_id_ * 3);
// int objects_location = core::SnesToPc(room_address);
// Load sprites
// int spr_ptr = 0x040000 | rooms_sprite_pointer;
// int sprite_address =
// core::SnesToPc(dungeon_spr_ptrs | spr_ptr + (room_id_ * 2));
} }
} // namespace dungeon } // namespace dungeon

View File

@@ -92,7 +92,6 @@ class DungeonDestination {
uint8_t Index; uint8_t Index;
uint8_t Target = 0; uint8_t Target = 0;
uint8_t TargetLayer = 0; uint8_t TargetLayer = 0;
// RoomObject* AssociatedObject = nullptr;
}; };
struct object_door { struct object_door {
@@ -124,31 +123,34 @@ class Room : public SharedROM {
Room(int room_id) : room_id_(room_id) {} Room(int room_id) : room_id_(room_id) {}
~Room() = default; ~Room() = default;
void LoadHeader(); void LoadHeader();
void LoadRoomFromROM();
void LoadRoomGraphics(uchar entrance_blockset = 0xFF); void LoadRoomGraphics(uchar entrance_blockset = 0xFF);
void CopyRoomGraphicsToBuffer(); void CopyRoomGraphicsToBuffer();
void LoadAnimatedGraphics(); void LoadAnimatedGraphics();
void LoadObjects();
void LoadSprites(); void LoadSprites();
void LoadChests(); void LoadChests();
void LoadObjects();
void LoadRoomFromROM();
auto blocks() const { return blocks_; } auto blocks() const { return blocks_; }
auto& mutable_blocks() { return blocks_; } auto& mutable_blocks() { return blocks_; }
auto layer1() const { return background_bmps_[0]; }
auto layer2() const { return background_bmps_[1]; }
auto layer3() const { return background_bmps_[2]; }
RoomObject AddObject(short oid, uint8_t x, uint8_t y, uint8_t size, RoomObject AddObject(short oid, uint8_t x, uint8_t y, uint8_t size,
uint8_t layer) { uint8_t layer) {
return RoomObject(oid, x, y, size, layer); return RoomObject(oid, x, y, size, layer);
} }
uint8_t floor1 = 0;
uint8_t floor2 = 0;
uint8_t blockset = 0; uint8_t blockset = 0;
uint8_t spriteset = 0; uint8_t spriteset = 0;
uint8_t palette = 0; uint8_t palette = 0;
uint8_t layout = 0; uint8_t layout = 0;
uint8_t holewarp = 0; uint8_t holewarp = 0;
uint8_t floor1 = 0;
uint8_t floor2 = 0;
uint16_t message_id_ = 0; uint16_t message_id_ = 0;
@@ -158,44 +160,44 @@ class Room : public SharedROM {
std::vector<uint8_t> current_gfx16_; std::vector<uint8_t> current_gfx16_;
private: private:
bool light = false; bool is_light_;
bool is_loaded_ = false; bool is_loaded_;
bool IsDark = false; bool is_dark_;
bool floor = false; bool is_floor_;
int room_id_ = 0; int room_id_;
int animated_frame = 0; int animated_frame_;
uchar Tag1; uchar tag1_;
uchar Tag2; uchar tag2_;
uint8_t staircase_plane[4]; uint8_t staircase_plane_[4];
uint8_t staircase_rooms[4]; uint8_t staircase_rooms_[4];
uint8_t BackgroundTileset; uint8_t background_tileset_;
uint8_t SpriteTileset; uint8_t sprite_tileset_;
uint8_t Layer2Behavior; uint8_t layer2_behavior_;
uint8_t Palette; uint8_t palette_;
uint8_t Floor1Graphics; uint8_t floor1_graphics_;
uint8_t Floor2Graphics; uint8_t floor2_graphics_;
uint8_t Layer2Mode; uint8_t layer2_mode_;
std::array<uint8_t, 16> blocks_; std::array<uint8_t, 16> blocks_;
std::array<uchar, 16> ChestList; std::array<uchar, 16> chest_list_;
std::array<gfx::Bitmap, 3> background_bmps_; std::array<gfx::Bitmap, 3> background_bmps_;
std::vector<zelda3::Sprite> sprites_; std::vector<zelda3::Sprite> sprites_;
std::vector<StaircaseRooms> staircaseRooms; std::vector<StaircaseRooms> staircase_rooms_vec_;
Background2 bg2; Background2 bg2_;
DungeonDestination Pits; DungeonDestination pits_;
DungeonDestination Stair1; DungeonDestination stair1_;
DungeonDestination Stair2; DungeonDestination stair2_;
DungeonDestination Stair3; DungeonDestination stair3_;
DungeonDestination Stair4; DungeonDestination stair4_;
std::vector<ChestData> chests_in_room; std::vector<ChestData> chests_in_room_;
std::vector<RoomObject> tilesObjects; std::vector<RoomObject> tile_objects_;
}; };
} // namespace dungeon } // namespace dungeon