Update Room, Add RoomObject, RoomNames

This commit is contained in:
scawful
2023-08-18 17:20:11 -04:00
parent 5cc680762e
commit 09df21a439
6 changed files with 997 additions and 90 deletions

View File

@@ -9,7 +9,7 @@ project(yaze VERSION 0.01)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@@ -52,10 +52,11 @@ find_library(SDL_MIXER_LIBRARY
PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
)
add_subdirectory(src/lib/SDL_mixer)
find_package(SDL2_image)
# Asar ------------------------------------------------------------------------
add_subdirectory(src/lib/asar/src)
include(cmake/asar.cmake)
# add_subdirectory(src/lib/asar/src)
# include(cmake/asar.cmake)
# snes-spc --------------------------------------------------------------------
ADD_DEFINITIONS(-DSNES_SPC_EXPORTS)

View File

@@ -1,107 +1,364 @@
#include "room.h"
#include <cstdint>
#include <vector>
#include "app/core/common.h"
#include "app/core/constants.h"
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/gui/canvas.h"
#include "app/rom.h"
#include "app/zelda3/dungeon/room_object.h"
#include "app/zelda3/sprite/sprite.h"
namespace yaze {
namespace app {
namespace zelda3 {
namespace dungeon {
void DrawDungeonRoomBG1(std::vector<uint8_t>& tiles_bg1_buffer,
std::vector<uint8_t>& current_gfx16,
std::vector<uint8_t>& room_bg1_data) {
for (int yy = 0; yy < 64; ++yy) {
for (int xx = 0; xx < 64; ++xx) {
if (tiles_bg1_buffer[xx + (yy * 64)] != 0xFFFF) {
auto t = gfx::GetTilesInfo(tiles_bg1_buffer[xx + (yy * 64)]);
for (int yl = 0; yl < 8; ++yl) {
for (int xl = 0; xl < 4; ++xl) {
int mx = xl * (1 - t.horizontal_mirror_) +
(3 - xl) * t.horizontal_mirror_;
int my =
yl * (1 - t.vertical_mirror_) + (7 - yl) * t.vertical_mirror_;
int ty = (t.id_ / 16) * 512;
int tx = (t.id_ % 16) * 4;
uint8_t pixel = current_gfx16[(tx + ty) + (yl * 64) + xl];
int index = (xx * 8) + (yy * 4096) + ((mx * 2) + (my * 512));
room_bg1_data[index + t.horizontal_mirror_ ^ 1] =
static_cast<uint8_t>((pixel & 0x0F) + t.palette_ * 16);
room_bg1_data[index + t.horizontal_mirror_] =
static_cast<uint8_t>(((pixel >> 4) & 0x0F) + t.palette_ * 16);
}
}
}
}
}
}
void DrawDungeonRoomBG2(std::vector<uint8_t>& tiles_bg2_buffer,
std::vector<uint8_t>& current_gfx16,
std::vector<uint8_t>& room_bg2_data) {
for (int yy = 0; yy < 64; ++yy) {
for (int xx = 0; xx < 64; ++xx) {
if (tiles_bg2_buffer[xx + (yy * 64)] != 0xFFFF) {
auto t = gfx::GetTilesInfo(tiles_bg2_buffer[xx + (yy * 64)]);
for (int yl = 0; yl < 8; ++yl) {
for (int xl = 0; xl < 4; ++xl) {
int mx = xl * (1 - t.horizontal_mirror_) +
(3 - xl) * t.horizontal_mirror_;
int my =
yl * (1 - t.vertical_mirror_) + (7 - yl) * t.vertical_mirror_;
int ty = (t.id_ / 16) * 512;
int tx = (t.id_ % 16) * 4;
uint8_t pixel = current_gfx16[(tx + ty) + (yl * 64) + xl];
int index = (xx * 8) + (yy * 4096) + ((mx * 2) + (my * 512));
room_bg2_data[index + t.horizontal_mirror_ ^ 1] =
static_cast<uint8_t>((pixel & 0x0F) + t.palette_ * 16);
room_bg2_data[index + t.horizontal_mirror_] =
static_cast<uint8_t>(((pixel >> 4) & 0x0F) + t.palette_ * 16);
}
}
}
}
}
}
// ==================================================================
void Room::LoadGfxGroups() {
auto rom_data = rom()->vector();
int gfxPointer =
(rom_[gfx_groups_pointer + 1] << 8) + rom_[gfx_groups_pointer];
(rom_data[gfx_groups_pointer + 1] << 8) + rom_data[gfx_groups_pointer];
gfxPointer = core::SnesToPc(gfxPointer);
for (int i = 0; i < 37; i++) {
for (int j = 0; j < 8; j++) {
mainGfx[i][j] = rom_[gfxPointer + (i * 8) + j];
mainGfx[i][j] = rom_data[gfxPointer + (i * 8) + j];
}
}
for (int i = 0; i < 82; i++) {
for (int j = 0; j < 4; j++) {
roomGfx[i][j] = rom_[entrance_gfx_group + (i * 4) + j];
roomGfx[i][j] = rom_data[entrance_gfx_group + (i * 4) + j];
}
}
for (int i = 0; i < 144; i++) {
for (int j = 0; j < 4; j++) {
spriteGfx[i][j] = rom_[sprite_blockset_pointer + (i * 4) + j];
spriteGfx[i][j] = rom_data[sprite_blockset_pointer + (i * 4) + j];
}
}
for (int i = 0; i < 72; i++) {
for (int j = 0; j < 4; j++) {
paletteGfx[i][j] = rom_[dungeons_palettes_groups + (i * 4) + j];
paletteGfx[i][j] = rom_data[dungeons_palettes_groups + (i * 4) + j];
}
}
}
bool Room::SaveGroupsToROM() {
auto rom_data = rom()->vector();
int gfxPointer =
(rom_[gfx_groups_pointer + 1] << 8) + rom_[gfx_groups_pointer];
(rom_data[gfx_groups_pointer + 1] << 8) + rom_data[gfx_groups_pointer];
gfxPointer = core::SnesToPc(gfxPointer);
for (int i = 0; i < 37; i++) {
for (int j = 0; j < 8; j++) {
rom_.Write(gfxPointer + (i * 8) + j, mainGfx[i][j]);
rom()->Write(gfxPointer + (i * 8) + j, mainGfx[i][j]);
}
}
for (int i = 0; i < 82; i++) {
for (int j = 0; j < 4; j++) {
rom_.Write(entrance_gfx_group + (i * 4) + j, roomGfx[i][j]);
rom()->Write(entrance_gfx_group + (i * 4) + j, roomGfx[i][j]);
}
}
for (int i = 0; i < 144; i++) {
for (int j = 0; j < 4; j++) {
rom_.Write(sprite_blockset_pointer + (i * 4) + j, spriteGfx[i][j]);
rom()->Write(sprite_blockset_pointer + (i * 4) + j, spriteGfx[i][j]);
}
}
for (int i = 0; i < 72; i++) {
for (int j = 0; j < 4; j++) {
rom_.Write(dungeons_palettes_groups + (i * 4) + j, paletteGfx[i][j]);
rom()->Write(dungeons_palettes_groups + (i * 4) + j, paletteGfx[i][j]);
}
}
return false;
}
void Room::LoadChests() {
// ChestList.Clear();
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 cpos = rom_.Read24(core::constants::chests_data_pointer1).SNEStoPC();
// int clength = rom_.Read16(core::constants::chests_length_pointer);
int sprite_address = core::SnesToPc(sprite_address_snes);
bool sortsprites = rom_data[sprite_address] == 1;
sprite_address += 1;
// for (int i = 0; i < clength; i += 3) {
// ushort roomid = (ushort)(rom_.Read16(cpos) & 0x7FFF);
// cpos += 2;
// uchar item = rom_[cpos++]; // get now so cpos is incremented too
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 (roomid == RoomID) {
// ChestList.Add(new DungeonChestItem(ItemReceipt.GetTypeFromID(item)));
// }
// }
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::LoadBlocks() {}
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]);
void Room::LoadTorches() {}
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;
}
void Room::LoadSecrets() {}
chests_in_room.emplace_back(ChestData(rom_data[cpos + (i * 3) + 2], big));
}
}
}
void Room::Resync() {}
void Room::LoadObjects() {
auto rom_data = rom()->vector();
int objectPointer = (rom_data[room_object_pointer + 2] << 16) +
(rom_data[room_object_pointer + 1] << 8) +
(rom_data[room_object_pointer]);
objectPointer = core::SnesToPc(objectPointer);
int room_address = objectPointer + (room_id_ * 3);
void Room::LoadObjectsFromArray(int loc) {}
int tile_address = (rom_data[room_address + 2] << 16) +
(rom_data[room_address + 1] << 8) + rom_data[room_address];
void Room::LoadSpritesFromArray(int loc) {}
int objects_location = core::SnesToPc(tile_address);
if (objects_location == 0x52CA2) {
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);
}
layout = static_cast<uint8_t>((rom_data[objects_location + 1] >> 2) & 0x07);
LoadChests();
staircaseRooms.clear();
int nbr_of_staircase = 0;
int pos = objects_location + 2;
uint8_t b1 = 0;
uint8_t b2 = 0;
uint8_t b3 = 0;
uint8_t posX = 0;
uint8_t posY = 0;
uint8_t sizeX = 0;
uint8_t sizeY = 0;
uint8_t sizeXY = 0;
short oid = 0;
int layer = 0;
bool door = false;
bool endRead = false;
while (!endRead) {
b1 = rom_data[pos];
b2 = rom_data[pos + 1];
if (b1 == 0xFF && b2 == 0xFF) {
pos += 2; // We jump to layer2
layer++;
door = false;
if (layer == 3) {
break;
}
continue;
}
if (b1 == 0xF0 && b2 == 0xFF) {
pos += 2; // We jump to layer2
door = true;
continue;
}
b3 = rom_data[pos + 2];
if (door) {
pos += 2;
} else {
pos += 3;
}
if (!door) {
if (b3 >= 0xF8) {
oid = static_cast<short>((b3 << 4) |
0x80 + (((b2 & 0x03) << 2) + ((b1 & 0x03))));
posX = static_cast<uint8_t>((b1 & 0xFC) >> 2);
posY = static_cast<uint8_t>((b2 & 0xFC) >> 2);
sizeXY = static_cast<uint8_t>((((b1 & 0x03) << 2) + (b2 & 0x03)));
} else {
oid = b3;
posX = static_cast<uint8_t>((b1 & 0xFC) >> 2);
posY = static_cast<uint8_t>((b2 & 0xFC) >> 2);
sizeX = static_cast<uint8_t>((b1 & 0x03));
sizeY = static_cast<uint8_t>((b2 & 0x03));
sizeXY = static_cast<uint8_t>(((sizeX << 2) + sizeY));
}
if (b1 >= 0xFC) {
oid = static_cast<short>((b3 & 0x3F) + 0x100);
posX = static_cast<uint8_t>(((b2 & 0xF0) >> 4) + ((b1 & 0x3) << 4));
posY = static_cast<uint8_t>(((b2 & 0x0F) << 2) + ((b3 & 0xC0) >> 6));
sizeXY = 0;
}
RoomObject r =
AddObject(oid, posX, posY, sizeXY, static_cast<uint8_t>(layer));
/**
if (r != nullptr) {
tilesObjects.push_back(r);
}
for (short stair : stairsObjects) {
if (stair == oid) {
if (nbr_of_staircase < 4) {
tilesObjects.back().options |= ObjectOption::Stairs;
staircaseRooms.push_back(StaircaseRoom(
posX, posY, "To " + staircase_rooms[nbr_of_staircase]));
nbr_of_staircase++;
} else {
tilesObjects.back().options |= ObjectOption::Stairs;
staircaseRooms.push_back(StaircaseRoom(posX, posY, "To ???"));
}
}
}
if (oid == 0xF99) {
if (chests_in_room.size() > 0) {
tilesObjects.back().options |= ObjectOption::Chest;
chest_list.push_back(
Chest(posX, posY, chests_in_room.front().itemIn, false));
chests_in_room.erase(chests_in_room.begin());
}
} else if (oid == 0xFB1) {
if (chests_in_room.size() > 0) {
tilesObjects.back().options |= ObjectOption::Chest;
chest_list.push_back(
Chest(posX + 1, posY, chests_in_room.front().itemIn, true));
chests_in_room.erase(chests_in_room.begin());
}
}
} else {
tilesObjects.push_back(object_door(static_cast<short>((b2 << 8) + b1), 0,
0, 0, static_cast<uint8_t>(layer)));
}
**/
}
}
}
RoomObject Room::AddObject(short oid, uint8_t x, uint8_t y, uint8_t size,
uint8_t layer) {
return RoomObject(oid, x, y, size, layer);
}
void Room::LoadRoomGraphics(uchar entrance_blockset) {
for (int i = 0; i < 8; i++) {
@@ -127,7 +384,7 @@ void Room::LoadRoomGraphics(uchar entrance_blockset) {
blocks[12 + i] = (uchar)(spriteGfx[SpriteTileset + 64][i] + 115);
} // 12-16 sprites
auto newPdata = rom_.GetGraphicsBuffer();
auto newPdata = rom()->GetGraphicsBuffer();
uchar* sheetsData = current_graphics_.data();
// Into "room gfx16" 16 of them
@@ -157,8 +414,8 @@ void Room::LoadRoomGraphics(uchar entrance_blockset) {
void Room::LoadAnimatedGraphics() {
int gfxanimatedPointer = core::SnesToPc(gfx_animated_pointer);
auto newPdata = rom_.GetGraphicsBuffer();
auto newPdata = rom()->GetGraphicsBuffer();
auto rom_data = rom()->vector();
uchar* sheetsData = current_graphics_.data();
int data = 0;
while (data < 512) {
@@ -166,7 +423,8 @@ void Room::LoadAnimatedGraphics() {
sheetsData[data + (7 * 2048)] = mapByte;
mapByte =
newPdata[data + (rom_[gfxanimatedPointer + BackgroundTileset] * 2048) +
newPdata[data +
(rom_data[gfxanimatedPointer + BackgroundTileset] * 2048) +
(512 * animated_frame)];
sheetsData[data + (7 * 2048) - 512] = mapByte;
data++;
@@ -175,14 +433,15 @@ void Room::LoadAnimatedGraphics() {
void Room::LoadRoomFromROM() {
// Load dungeon header
auto rom_data = rom()->vector();
int headerPointer = core::SnesToPc(room_header_pointer);
MessageID = messages_id_dungeon + (RoomID * 2);
message_id_ = messages_id_dungeon + (room_id_ * 2);
int hpos = core::SnesToPc((rom_[room_header_pointers_bank] << 16) |
headerPointer + (RoomID * 2));
int hpos = core::SnesToPc((rom_data[room_header_pointers_bank] << 16) |
headerPointer + (room_id_ * 2));
hpos++;
uchar b = rom_[hpos];
uchar b = rom_data[hpos];
Layer2Mode = (uchar)(b >> 5);
// TODO(@scawful): Make LayerMerging object.
@@ -191,65 +450,54 @@ void Room::LoadRoomFromROM() {
IsDark = (b & 0x01) == 0x01;
hpos++;
Palette = rom_[hpos];
Palette = rom_data[hpos];
hpos++;
BackgroundTileset = rom_[hpos];
BackgroundTileset = rom_data[hpos];
hpos++;
SpriteTileset = rom_[hpos];
SpriteTileset = rom_data[hpos];
hpos++;
Layer2Behavior = rom_[hpos];
Layer2Behavior = rom_data[hpos];
hpos++;
Tag1 = rom_[hpos];
Tag1 = rom_data[hpos];
hpos++;
Tag2 = rom_[hpos];
Tag2 = rom_data[hpos];
hpos++;
b = rom_[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_[hpos] & 0x03);
Stair4.TargetLayer = (uchar)(rom_data[hpos] & 0x03);
hpos++;
Pits.Target = rom_[hpos];
Pits.Target = rom_data[hpos];
hpos++;
Stair1.Target = rom_[hpos];
Stair1.Target = rom_data[hpos];
hpos++;
Stair2.Target = rom_[hpos];
Stair2.Target = rom_data[hpos];
hpos++;
Stair3.Target = rom_[hpos];
Stair3.Target = rom_data[hpos];
hpos++;
Stair4.Target = rom_[hpos];
Stair4.Target = rom_data[hpos];
hpos++;
// Load room objects
int objectPointer = core::SnesToPc(room_object_pointer);
int room_address = objectPointer + (RoomID * 3);
int objects_location = core::SnesToPc(room_address);
LoadObjectsFromArray(objects_location);
// 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 + (RoomID * 2));
LoadSpritesFromArray(sprite_address);
// Load other stuff
LoadChests();
LoadBlocks();
LoadTorches();
LoadSecrets();
Resync();
// int spr_ptr = 0x040000 | rooms_sprite_pointer;
// int sprite_address =
// core::SnesToPc(dungeon_spr_ptrs | spr_ptr + (room_id_ * 2));
}
} // namespace dungeon

View File

@@ -1,6 +1,9 @@
#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_H
#define YAZE_APP_ZELDA3_DUNGEON_ROOM_H
#include <cstdint>
#include <vector>
#include "app/core/common.h"
#include "app/core/constants.h"
#include "app/gfx/bitmap.h"
@@ -8,6 +11,9 @@
#include "app/gfx/snes_tile.h"
#include "app/gui/canvas.h"
#include "app/rom.h"
#include "app/zelda3/dungeon/room_names.h"
#include "app/zelda3/dungeon/room_object.h"
#include "app/zelda3/sprite/sprite.h"
namespace yaze {
namespace app {
@@ -82,37 +88,68 @@ constexpr int door_pos_right = 0x19C6;
constexpr int dungeon_spr_ptrs = 0x090000;
class Room {
public:
Room() = default;
constexpr ushort stairsObjects[] = {0x139, 0x138, 0x13B, 0x12E, 0x12D};
private:
void DrawDungeonRoomBG1(std::vector<uint8_t>& tiles_bg1_buffer,
std::vector<uint8_t>& current_gfx16,
std::vector<uint8_t>& room_bg1_ptr);
void DrawDungeonRoomBG2(std::vector<uint8_t>& tiles_bg2_buffer,
std::vector<uint8_t>& current_gfx16,
std::vector<uint8_t>& room_bg2_ptr);
struct object_door {
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) {}
short id_;
uint8_t x_;
uint8_t y_;
uint8_t size_;
uint8_t type_;
uint8_t layer_;
};
struct ChestData {
ChestData(uchar i, bool s) : id_(i), size_(s){};
uchar id_;
bool size_;
};
struct StaircaseRooms {};
class Room : public SharedROM {
public:
void LoadGfxGroups();
bool SaveGroupsToROM();
void LoadChests();
void LoadBlocks();
void LoadTorches();
void LoadSecrets();
void Resync();
void LoadObjectsFromArray(int loc);
void LoadSpritesFromArray(int loc);
void LoadSprites();
void LoadChests();
void LoadObjects();
RoomObject AddObject(short oid, uint8_t x, uint8_t y, uint8_t size,
uint8_t layer);
void LoadRoomGraphics(uchar entrance_blockset = 0xFF);
void LoadAnimatedGraphics();
void LoadRoomFromROM();
DungeonDestination Pits;
DungeonDestination Stair1;
DungeonDestination Stair2;
DungeonDestination Stair3;
DungeonDestination Stair4;
private:
int animated_frame = 0;
int RoomID = 0;
ushort MessageID = 0;
int room_id_ = 0;
uint8_t floor1;
uint8_t floor2;
uint8_t blockset;
uint8_t spriteset;
uint8_t palette;
uint8_t layout;
ushort message_id_ = 0;
uchar BackgroundTileset;
uchar SpriteTileset;
uchar Layer2Behavior;
@@ -128,12 +165,25 @@ class Room {
uint8_t spriteGfx[144][4];
uint8_t paletteGfx[72][4];
// LayerMergeType LayerMerging;
std::vector<zelda3::Sprite> sprites_;
std::vector<StaircaseRooms> staircaseRooms;
DungeonDestination Pits;
DungeonDestination Stair1;
DungeonDestination Stair2;
DungeonDestination Stair3;
DungeonDestination Stair4;
uchar Tag1;
uchar Tag2;
bool IsDark;
ROM rom_;
bool floor;
// std::vector<Chest> chest_list;
std::vector<ChestData> chests_in_room;
std::vector<uint8_t> current_gfx16_;
std::vector<RoomObject> tilesObjects;
gfx::Bitmap current_graphics_;
};

View File

@@ -0,0 +1,352 @@
#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_NAMES_H
#define YAZE_APP_ZELDA3_DUNGEON_ROOM_NAMES_H
#include <fstream>
#include <string>
#include <string_view>
namespace yaze {
namespace app {
namespace zelda3 {
namespace dungeon {
constexpr std::string_view kRoomNames[] = {
"Ganon",
"Hyrule Castle (North Corridor)",
"Behind Sanctuary (Switch)",
"Houlihan",
"Turtle Rock (Crysta-Roller)",
"Empty",
"Swamp Palace (Arrghus[Boss])",
"Tower of Hera (Moldorm[Boss])",
"Cave (Healing Fairy)",
"Palace of Darkness",
"Palace of Darkness (Stalfos Trap)",
"Palace of Darkness (Turtle)",
"Ganon's Tower (Entrance)",
"Ganon's Tower (Agahnim2[Boss])",
"Ice Palace (Entrance )",
"Empty Clone ",
"Ganon Evacuation Route",
"Hyrule Castle (Bombable Stock )",
"Sanctuary",
"Turtle Rock (Hokku-Bokku Key 2)",
"Turtle Rock (Big Key )",
"Turtle Rock",
"Swamp Palace (Swimming Treadmill)",
"Tower of Hera (Moldorm Fall )",
"Cave",
"Palace of Darkness (Dark Maze)",
"Palace of Darkness (Big Chest )",
"Palace of Darkness (Mimics / Moving Wall )",
"Ganon's Tower (Ice Armos)",
"Ganon's Tower (Final Hallway)",
"Ice Palace (Bomb Floor / Bari )",
"Ice Palace (Pengator / Big Key )",
"Agahnim's Tower (Agahnim[Boss])",
"Hyrule Castle (Key-rat )",
"Hyrule Castle (Sewer Text Trigger )",
"Turtle Rock (West Exit to Balcony)",
"Turtle Rock (Double Hokku-Bokku / Big chest )",
"Empty Clone ",
"Swamp Palace (Statue )",
"Tower of Hera (Big Chest)",
"Swamp Palace (Entrance )",
"Skull Woods (Mothula[Boss])",
"Palace of Darkness (Big Hub )",
"Palace of Darkness (Map Chest / Fairy )",
"Cave",
"Empty Clone ",
"Ice Palace (Compass )",
"Cave (Kakariko Well HP)",
"Agahnim's Tower (Maiden Sacrifice Chamber)",
"Tower of Hera (Hardhat Beetles )",
"Hyrule Castle (Sewer Key Chest )",
"Desert Palace (Lanmolas[Boss])",
"Swamp Palace (Push Block Puzzle / Pre-Big Key )",
"Swamp Palace (Big Key / BS )",
"Swamp Palace (Big Chest )",
"Swamp Palace (Map Chest / Water Fill )",
"Swamp Palace (Key Pot )",
"Skull Woods (Gibdo Key / Mothula Hole )",
"Palace of Darkness (Bombable Floor )",
"Palace of Darkness (Spike Block / Conveyor )",
"Cave",
"Ganon's Tower (Torch 2)",
"Ice Palace (Stalfos Knights / Conveyor Hellway)",
"Ice Palace (Map Chest )",
"Agahnim's Tower (Final Bridge )",
"Hyrule Castle (First Dark )",
"Hyrule Castle (6 Ropes )",
"Desert Palace (Torch Puzzle / Moving Wall )",
"Thieves Town (Big Chest )",
"Thieves Town (Jail Cells )",
"Swamp Palace (Compass Chest )",
"Empty Clone ",
"Empty Clone ",
"Skull Woods (Gibdo Torch Puzzle )",
"Palace of Darkness (Entrance )",
"Palace of Darkness (Warps / South Mimics )",
"Ganon's Tower (Mini-Helmasaur Conveyor )",
"Ganon's Tower (Moldorm )",
"Ice Palace (Bomb-Jump )",
"Ice Palace Clone (Fairy )",
"Hyrule Castle (West Corridor)",
"Hyrule Castle (Throne )",
"Hyrule Castle (East Corridor)",
"Desert Palace (Popos 2 / Beamos Hellway )",
"Swamp Palace (Upstairs Pits )",
"Castle Secret Entrance / Uncle Death ",
"Skull Woods (Key Pot / Trap )",
"Skull Woods (Big Key )",
"Skull Woods (Big Chest )",
"Skull Woods (Final Section Entrance )",
"Palace of Darkness (Helmasaur King[Boss])",
"Ganon's Tower (Spike Pit )",
"Ganon's Tower (Ganon-Ball Z)",
"Ganon's Tower (Gauntlet 1/2/3)",
"Ice Palace (Lonely Firebar)",
"Ice Palace (Hidden Chest / Spike Floor )",
"Hyrule Castle (West Entrance )",
"Hyrule Castle (Main Entrance )",
"Hyrule Castle (East Entrance )",
"Desert Palace (Final Section Entrance )",
"Thieves Town (West Attic )",
"Thieves Town (East Attic )",
"Swamp Palace (Hidden Chest / Hidden Door )",
"Skull Woods (Compass Chest )",
"Skull Woods (Key Chest / Trap )",
"Empty Clone ",
"Palace of Darkness (Rupee )",
"Ganon's Tower (Mimics s)",
"Ganon's Tower (Lanmolas )",
"Ganon's Tower (Gauntlet 4/5)",
"Ice Palace (Pengators )",
"Empty Clone ",
"Hyrule Castle (Small Corridor to Jail Cells)",
"Hyrule Castle (Boomerang Chest )",
"Hyrule Castle (Map Chest )",
"Desert Palace (Big Chest )",
"Desert Palace (Map Chest )",
"Desert Palace (Big Key Chest )",
"Swamp Palace (Water Drain )",
"Tower of Hera (Entrance )",
"Empty Clone ",
"Empty Clone ",
"Empty Clone ",
"Ganon's Tower",
"Ganon's Tower (East Side Collapsing Bridge / Exploding Wall )",
"Ganon's Tower (Winder / Warp Maze )",
"Ice Palace (Hidden Chest / Bombable Floor )",
"Ice Palace ( Big Spike Traps )",
"Hyrule Castle (Jail Cell )",
"Hyrule Castle",
"Hyrule Castle (Basement Chasm )",
"Desert Palace (West Entrance )",
"Desert Palace (Main Entrance )",
"Desert Palace (East Entrance )",
"Empty Clone ",
"Tower of Hera (Tile )",
"Empty Clone ",
"Eastern Palace (Fairy )",
"Empty Clone ",
"Ganon's Tower (Block Puzzle / Spike Skip / Map Chest )",
"Ganon's Tower (East and West Downstairs / Big Chest )",
"Ganon's Tower (Tile / Torch Puzzle )",
"Ice Palace",
"Empty Clone ",
"Misery Mire (Vitreous[Boss])",
"Misery Mire (Final Switch )",
"Misery Mire (Dark Bomb Wall / Switches )",
"Misery Mire (Dark Cane Floor Switch Puzzle )",
"Empty Clone ",
"Ganon's Tower (Final Collapsing Bridge )",
"Ganon's Tower (Torches 1 )",
"Misery Mire (Torch Puzzle / Moving Wall )",
"Misery Mire (Entrance )",
"Eastern Palace (Eyegore Key )",
"Empty Clone ",
"Ganon's Tower (Many Spikes / Warp Maze )",
"Ganon's Tower (Invisible Floor Maze )",
"Ganon's Tower (Compass Chest / Invisible Floor )",
"Ice Palace (Big Chest )",
"Ice Palace",
"Misery Mire (Pre-Vitreous )",
"Misery Mire (Fish )",
"Misery Mire (Bridge Key Chest )",
"Misery Mire",
"Turtle Rock (Trinexx[Boss])",
"Ganon's Tower (Wizzrobes s)",
"Ganon's Tower (Moldorm Fall )",
"Tower of Hera (Fairy )",
"Eastern Palace (Stalfos Spawn )",
"Eastern Palace (Big Chest )",
"Eastern Palace (Map Chest )",
"Thieves Town (Moving Spikes / Key Pot )",
"Thieves Town (Blind The Thief[Boss])",
"Empty Clone ",
"Ice Palace",
"Ice Palace (Ice Bridge )",
"Agahnim's Tower (Circle of Pots)",
"Misery Mire (Hourglass )",
"Misery Mire (Slug )",
"Misery Mire (Spike Key Chest )",
"Turtle Rock (Pre-Trinexx )",
"Turtle Rock (Dark Maze)",
"Turtle Rock (Chain Chomps )",
"Turtle Rock (Map Chest / Key Chest / Roller )",
"Eastern Palace (Big Key )",
"Eastern Palace (Lobby Cannonballs )",
"Eastern Palace (Dark Antifairy / Key Pot )",
"Thieves Town (Hellway)",
"Thieves Town (Conveyor Toilet)",
"Empty Clone ",
"Ice Palace (Block Puzzle )",
"Ice Palace Clone (Switch )",
"Agahnim's Tower (Dark Bridge )",
"Misery Mire (Compass Chest / Tile )",
"Misery Mire (Big Hub )",
"Misery Mire (Big Chest )",
"Turtle Rock (Final Crystal Switch Puzzle )",
"Turtle Rock (Laser Bridge)",
"Turtle Rock",
"Turtle Rock (Torch Puzzle)",
"Eastern Palace (Armos Knights[Boss])",
"Eastern Palace (Entrance )",
"??",
"Thieves Town (North West Entrance )",
"Thieves Town (North East Entrance )",
"Empty Clone ",
"Ice Palace (Hole to Kholdstare )",
"Empty Clone ",
"Agahnim's Tower (Dark Maze)",
"Misery Mire (Conveyor Slug / Big Key )",
"Misery Mire (Mire02 / Wizzrobes )",
"Empty Clone ",
"Empty Clone ",
"Turtle Rock (Laser Key )",
"Turtle Rock (Entrance )",
"Empty Clone ",
"Eastern Palace (Zeldagamer / Pre-Armos Knights )",
"Eastern Palace (Canonball ",
"Eastern Palace",
"Thieves Town (Main (South West) Entrance )",
"Thieves Town (South East Entrance )",
"Empty Clone ",
"Ice Palace (Kholdstare[Boss])",
"Cave",
"Agahnim's Tower (Entrance )",
"Cave (Lost Woods HP)",
"Cave (Lumberjack's Tree HP)",
"Cave (1/2 Magic)",
"Cave (Lost Old Man Final Cave)",
"Cave (Lost Old Man Final Cave)",
"Cave",
"Cave",
"Cave",
"Empty Clone ",
"Cave (Spectacle Rock HP)",
"Cave",
"Empty Clone ",
"Cave",
"Cave (Spiral Cave)",
"Cave (Crystal Switch / 5 Chests )",
"Cave (Lost Old Man Starting Cave)",
"Cave (Lost Old Man Starting Cave)",
"House",
"House (Old Woman (Sahasrahla's Wife?))",
"House (Angry Brothers)",
"House (Angry Brothers)",
"Empty Clone ",
"Empty Clone ",
"Cave",
"Cave",
"Cave",
"Cave",
"Empty Clone ",
"Cave",
"Cave",
"Cave",
"Chest Minigame",
"Houses",
"Sick Boy house",
"Tavern",
"Link's House",
"Sarashrala Hut",
"Chest Minigame",
"Library",
"Chicken House",
"Witch Shop",
"A Aginah's Cave",
"Dam",
"Mimic Cave",
"Mire Shed",
"Cave",
"Shop",
"Shop",
"Archery Minigame",
"DW Church/Shop",
"Grave Cave",
"Fairy Fountain",
"Fairy Upgrade",
"Pyramid Fairy",
"Spike Cave",
"Chest Minigame",
"Blind Hut",
"Bonzai Cave",
"Circle of bush Cave",
"Big Bomb Shop, C-House",
"Blind Hut 2",
"Hype Cave",
"Shop",
"Ice Cave",
"Smith",
"Fortune Teller",
"MiniMoldorm Cave",
"Under Rock Caves",
"Smith",
"Cave",
"Mazeblock Cave",
"Smith Peg Cave"};
class Room_Name {
public:
static std::vector<std::string> room_name;
static void loadFromFile(const std::string& file = "DefaultNames.txt") {
std::ifstream ifs(file);
std::string line;
int l = 0;
bool found = false;
while (getline(ifs, line)) {
if (line == "[Rooms Names]") {
l = 0;
found = true;
continue;
}
if (found) {
if (line.length() > 0) {
if (line[0] == '/' && line[1] == '/') {
continue;
}
if (l >= 0x4B) {
break;
}
room_name[l] = line;
l++;
}
}
}
}
};
} // namespace dungeon
} // namespace zelda3
} // namespace app
} // namespace yaze
#endif // YAZE_APP_ZELDA3_DUNGEON_ROOM_NAMES_H

View File

@@ -0,0 +1,87 @@
#include "room_object.h"
namespace yaze {
namespace app {
namespace zelda3 {
namespace dungeon {
void RoomObject::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) {
if (width < xx + 8) {
width = xx + 8;
}
if (height < yy + 8) {
height = yy + 8;
}
if (preview) {
if (xx < 57 && yy < 57 && xx >= 0 && yy >= 0) {
gfx::TileInfo ti; // t.GetTileInfo();
for (auto yl = 0; yl < 8; yl++) {
for (auto xl = 0; xl < 4; xl++) {
int mx = xl;
int my = yl;
uint8_t r = 0;
if (ti.horizontal_mirror_) {
mx = 3 - xl;
r = 1;
}
if (ti.vertical_mirror_) {
my = 7 - yl;
}
// 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];
// nx,ny = object position, xx,yy = tile position, xl,yl = pixel
// position
int index =
((xx / 8) * 8) + ((yy / 8) * 512) + ((mx * 2) + (my * 64));
preview_object_data_[index + r ^ 1] =
(uint8_t)((pixel & 0x0F) + ti.palette_ * 16);
preview_object_data_[index + r] =
(uint8_t)(((pixel >> 4) & 0x0F) + ti.palette_ * 16);
}
}
}
} else {
if (((xx / 8) + nx + offsetX) + ((ny + offsetY + (yy / 8)) * 64) < 4096 &&
((xx / 8) + nx + offsetX) + ((ny + offsetY + (yy / 8)) * 64) >= 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)]) {
return;
}
tiles_bg1_buffer[((xx / 8) + offsetX + nx) +
((ny + offsetY + (yy / 8)) * 64)] = td;
}
if ((uint8_t)Layer == 1 || allBgs) {
if (tileUnder == tiles_bg2_buffer[((xx / 8) + nx + offsetX) +
((ny + offsetY + (yy / 8)) * 64)]) {
return;
}
tiles_bg2_buffer[((xx / 8) + nx) + offsetX +
((ny + offsetY + (yy / 8)) * 64)] = td;
}
}
}
}
} // namespace dungeon
} // namespace zelda3
} // namespace app
} // namespace yaze

View File

@@ -0,0 +1,169 @@
#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_OBJECT_H
#define YAZE_APP_ZELDA3_DUNGEON_ROOM_OBJECT_H
#include <array>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <vector>
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
namespace yaze {
namespace app {
namespace zelda3 {
namespace dungeon {
enum class SpecialObjectType { Chest, BigChest, InterroomStairs };
struct Tile {};
enum Background2 {
Off,
Parallax,
Dark,
OnTop,
Translucent,
Addition,
Normal,
Transparent,
DarkRoom // TODO: Determine if DarkRoom will stay there or not
};
enum Sorting {
All = 0,
Wall = 1,
Horizontal = 2,
Vertical = 4,
NonScalable = 8,
Dungeons = 16,
Floors = 32,
SortStairs = 64
};
enum ObjectOption {
Nothing = 0,
Door = 1,
Chest = 2,
Block = 4,
Torch = 8,
Bgr = 16,
Stairs = 32
};
struct LayerType {
LayerType(uint8_t t) : type(t) {}
uint8_t type;
};
class RoomObject : public SharedROM {
public:
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),
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) {}
void getObjectSize() {
previousSize = size_;
size_ = 1;
// Draw();
getBaseSize();
UpdateSize();
size_ = 2;
// Draw();
getSizeSized();
UpdateSize();
size_ = previousSize;
// collisionPoint.clear();
}
void getBaseSize() {
basewidth = width;
baseheight = height;
}
void getSizeSized() {
sizeheight = height - baseheight;
sizewidth = width - basewidth;
}
// virtual void Draw() { collisionPoint.clear(); }
void UpdateSize() {
width = 8;
height = 8;
}
void addTiles(int nbr, int pos) {
auto rom_data = rom()->data();
for (int i = 0; i < nbr; i++) {
// tiles.push_back(
// gfx::Tile16(rom_data[pos + (i * 2)], rom_data[pos + (i * 2) + 1]));
}
}
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);
private:
int16_t id;
uint8_t x_;
uint8_t y_;
uint8_t size_;
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;
bool redraw = false;
bool preview = 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;
};
} // namespace dungeon
} // namespace zelda3
} // namespace app
} // namespace yaze
#endif // YAZE_APP_ZELDA3_DUNGEON_ROOM_OBJECT_H