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::DisplayFrameBuffer() {
if (!screen_->IsActive()) {
if (!screen_->is_active()) {
screen_->Create(256, 240, 24, frame_buffer_);
rom()->RenderBitmap(screen_.get());
}

View File

@@ -273,7 +273,7 @@ class Ppu : public Observer, public SharedROM {
clock_.SetFrequency(kPpuClockSpeed);
frame_buffer_.resize(256 * 240, 0);
screen_ = std::make_shared<gfx::Bitmap>(256, 240, 8, 0x100);
screen_->SetActive(false);
screen_->set_active(false);
}
// 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
for (int tile_index = 0; tile_index < 512; tile_index++) {
// 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 local_id = tile_id % 32;
@@ -190,7 +190,8 @@ class DungeonObjectRenderer : public SharedROM {
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_;

View File

@@ -31,12 +31,12 @@ 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;
is_light_ = ((rom()->data()[header_location]) & 0x01) == 1;
if (light) {
bg2 = Background2::DarkRoom;
if (is_light_) {
bg2_ = Background2::DarkRoom;
}
palette = ((rom()->data()[header_location + 1] & 0x3F));
@@ -46,16 +46,88 @@ void Room::LoadHeader() {
// tag1 = (TagKey)((rom()->data()[header_location + 5]));
// tag2 = (TagKey)((rom()->data()[header_location + 6]));
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);
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);
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]);
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::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) {
@@ -125,89 +197,19 @@ void Room::LoadAnimatedGraphics() {
auto rom_data = rom()->vector();
int data = 0;
while (data < 512) {
uchar mapByte =
gfx_buffer_data[data + (92 * 2048) + (512 * animated_frame)];
current_gfx16_[data + (7 * 2048)] = mapByte;
uchar map_byte =
gfx_buffer_data[data + (92 * 2048) + (512 * animated_frame_)];
current_gfx16_[data + (7 * 2048)] = map_byte;
mapByte =
gfx_buffer_data[data + (rom_data[gfx_ptr + BackgroundTileset] * 2048) +
(512 * animated_frame)];
current_gfx16_[data + (7 * 2048) - 512] = mapByte;
map_byte =
gfx_buffer_data[data +
(rom_data[gfx_ptr + background_tileset_] * 2048) +
(512 * animated_frame_)];
current_gfx16_[data + (7 * 2048) - 512] = map_byte;
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() {
auto rom_data = rom()->vector();
int objectPointer = (rom_data[room_object_pointer + 2] << 16) +
@@ -225,16 +227,17 @@ void Room::LoadObjects() {
std::cout << "Room ID : " << room_id_ << std::endl;
}
if (floor) {
floor1 = static_cast<uint8_t>(rom_data[objects_location] & 0x0F);
floor2 = static_cast<uint8_t>((rom_data[objects_location] >> 4) & 0x0F);
if (is_floor_) {
floor1_graphics_ = static_cast<uint8_t>(rom_data[objects_location] & 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);
LoadChests();
staircaseRooms.clear();
staircase_rooms_vec_.clear();
int nbr_of_staircase = 0;
int pos = objects_location + 2;
@@ -314,7 +317,7 @@ void Room::LoadObjects() {
if (nbr_of_staircase < 4) {
tilesObjects.back().options |= ObjectOption::Stairs;
staircaseRooms.push_back(StaircaseRoom(
posX, posY, "To " + staircase_rooms[nbr_of_staircase]));
posX, posY, "To " + staircase_rooms_[nbr_of_staircase]));
nbr_of_staircase++;
} else {
tilesObjects.back().options |= ObjectOption::Stairs;
@@ -348,76 +351,76 @@ void Room::LoadObjects() {
}
}
void Room::LoadRoomFromROM() {
// Load dungeon header
void Room::LoadSprites() {
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) +
(rom()->data()[(header_pointer + 1) + (room_id_ * 2)] << 8) +
rom()->data()[(header_pointer) + (room_id_ * 2)];
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];
int hpos = core::SnesToPc(address);
hpos++;
uint8_t b = rom_data[hpos];
if (b1 == 0xFF) {
break;
}
Layer2Mode = (b >> 5);
// TODO(@scawful): Make LayerMerging object.
// LayerMerging = LayerMergeType.ListOf[(b & 0x0C) >> 2];
// sprites_.emplace_back(this, b3, (b2 & 0x1F), (b1 & 0x1F),
// ((b2 & 0xE0) >> 5) + ((b1 & 0x60) >> 2),
// (b1 & 0x80) >> 7);
IsDark = (b & 0x01) == 0x01;
hpos++;
if (sprites_.size() > 1) {
Sprite& spr = sprites_.back();
Sprite& prevSprite = sprites_[sprites_.size() - 2];
Palette = rom_data[hpos];
hpos++;
if (spr.id() == 0xE4 && spr.x() == 0x00 && spr.y() == 0x1E &&
spr.layer() == 1 && spr.subtype() == 0x18) {
// prevSprite.keyDrop() = 1;
sprites_.pop_back();
}
BackgroundTileset = rom_data[hpos];
hpos++;
if (spr.id() == 0xE4 && spr.x() == 0x00 && spr.y() == 0x1D &&
spr.layer() == 1 && spr.subtype() == 0x18) {
// prevSprite.keyDrop() = 2;
sprites_.pop_back();
}
}
SpriteTileset = rom_data[hpos];
hpos++;
sprite_address += 3;
}
}
Layer2Behavior = rom_data[hpos];
hpos++;
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]);
Tag1 = rom_data[hpos];
hpos++;
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;
}
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));
chests_in_room_.emplace_back(
ChestData(rom_data[cpos + (i * 3) + 2], big));
}
}
}
} // namespace dungeon

View File

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