OverworldExit updates and refactoring

This commit is contained in:
scawful
2024-01-14 11:15:34 -05:00
parent 5e025a3257
commit c9d0fb9573
4 changed files with 185 additions and 78 deletions

View File

@@ -316,6 +316,8 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0,
canvas_p0.y + scrolling.y);
dragged_entrance_->x_ = io.MousePos.x - origin.x - 8;
dragged_entrance_->y_ = io.MousePos.y - origin.y - 8;
each.x_ = dragged_entrance_->x_;
each.y_ = dragged_entrance_->y_;
is_dragging_entrance_ = false;
}
}

View File

@@ -340,6 +340,14 @@ class ROM : public core::ExperimentFlags {
return absl::OkStatus();
}
absl::Status WriteByte(int addr, uint8_t value) {
if (addr >= rom_data_.size()) {
return absl::InvalidArgumentError("Address out of range");
}
rom_data_[addr] = value;
return absl::OkStatus();
}
absl::Status WriteShort(uint32_t addr, uint16_t value) {
if (addr + 1 >= rom_data_.size()) {
return absl::InvalidArgumentError("Address out of range");

View File

@@ -150,17 +150,16 @@ absl::Status Overworld::Load(ROM &rom) {
return absl::OkStatus();
}
OWBlockset &Overworld::GetMapTiles(int world_type) {
switch (world_type) {
case 0:
return map_tiles_.light_world;
case 1:
return map_tiles_.dark_world;
case 2:
return map_tiles_.special_world;
default:
return map_tiles_.light_world;
}
absl::Status Overworld::Save(ROM &rom) {
rom_ = rom;
RETURN_IF_ERROR(SaveMap16Tiles())
RETURN_IF_ERROR(SaveMap32Tiles())
RETURN_IF_ERROR(SaveOverworldMaps())
RETURN_IF_ERROR(SaveEntrances())
RETURN_IF_ERROR(SaveExits())
return absl::OkStatus();
}
absl::Status Overworld::LoadOverworldMaps() {
@@ -300,13 +299,13 @@ absl::Status Overworld::SaveLargeMaps() {
int parentyPos = overworld_maps_[i].Parent() / 8;
int parentxPos = overworld_maps_[i].Parent() % 8;
std::unordered_map<uint8_t, uint8_t> checkedMap;
std::unordered_map<uint8_t, uint8_t> checked_map;
// Always write the map parent since it should not matter
RETURN_IF_ERROR(
rom()->Write(overworldMapParentId + i, overworld_maps_[i].Parent()))
if (checkedMap.count(overworld_maps_[i].Parent()) > 0) {
if (checked_map.count(overworld_maps_[i].Parent()) > 0) {
continue;
}
@@ -404,20 +403,20 @@ absl::Status Overworld::SaveLargeMaps() {
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 2,
0x0060}))
uint16_t lowerSubmaps;
uint16_t lower_submaps;
// If parentX == 0 then lower submaps == 0x0060 too
if (parentxPos == 0) {
lowerSubmaps = 0x0060;
lower_submaps = 0x0060;
} else {
// Otherwise lower submaps == 0x1060
lowerSubmaps = 0x1060;
lower_submaps = 0x1060;
}
RETURN_IF_ERROR(rom()->RunTransaction(
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 16,
uint16_t(lowerSubmaps)},
uint16_t(lower_submaps)},
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 18,
uint16_t(lowerSubmaps)},
uint16_t(lower_submaps)},
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 128,
uint16_t(0x0080)}, // Always 0x0080
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 128,
@@ -448,10 +447,10 @@ absl::Status Overworld::SaveLargeMaps() {
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 384,
uint16_t(0x2040)})) // Always 0x2000
checkedMap.emplace(i, 1);
checkedMap.emplace((i + 1), 1);
checkedMap.emplace((i + 8), 1);
checkedMap.emplace((i + 9), 1);
checked_map.emplace(i, 1);
checked_map.emplace((i + 1), 1);
checked_map.emplace((i + 8), 1);
checked_map.emplace((i + 9), 1);
} else {
RETURN_IF_ERROR(rom()->RunTransaction(
@@ -480,7 +479,7 @@ absl::Status Overworld::SaveLargeMaps() {
WriteAction{overworldTransitionPositionY + (i * 2),
uint16_t(yPos * 0x200)}))
checkedMap.emplace(i, 1);
checked_map.emplace(i, 1);
}
}
return absl::OkStatus();
@@ -862,82 +861,140 @@ void Overworld::FetchLargeMaps() {
void Overworld::LoadEntrances() {
for (int i = 0; i < 129; i++) {
short mapId = rom()->toint16(OWEntranceMap + (i * 2));
ushort mapPos = rom()->toint16(OWEntrancePos + (i * 2));
uchar entranceId = (rom_[OWEntranceEntranceId + i]);
int p = mapPos >> 1;
short map_id = rom()->toint16(OWEntranceMap + (i * 2));
ushort map_pos = rom()->toint16(OWEntrancePos + (i * 2));
uchar entrance_id = rom_[OWEntranceEntranceId + i];
int p = map_pos >> 1;
int x = (p % 64);
int y = (p >> 6);
bool deleted = false;
if (mapPos == 0xFFFF) {
if (map_pos == 0xFFFF) {
deleted = true;
}
all_entrances_.emplace_back(
(x * 16) + (((mapId % 64) - (((mapId % 64) / 8) * 8)) * 512),
(y * 16) + (((mapId % 64) / 8) * 512), entranceId, mapId, mapPos,
(x * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512),
(y * 16) + (((map_id % 64) / 8) * 512), entrance_id, map_id, map_pos,
deleted);
}
for (int i = 0; i < 0x13; i++) {
auto mapId = (short)((rom_[OWHoleArea + (i * 2) + 1] << 8) +
(rom_[OWHoleArea + (i * 2)]));
auto mapPos = (short)((rom_[OWHolePos + (i * 2) + 1] << 8) +
(rom_[OWHolePos + (i * 2)]));
uchar entranceId = (rom_[OWHoleEntrance + i]);
int p = (mapPos + 0x400) >> 1;
auto map_id = (short)((rom_[OWHoleArea + (i * 2) + 1] << 8) +
(rom_[OWHoleArea + (i * 2)]));
auto map_pos = (short)((rom_[OWHolePos + (i * 2) + 1] << 8) +
(rom_[OWHolePos + (i * 2)]));
uchar entrance_id = (rom_[OWHoleEntrance + i]);
int p = (map_pos + 0x400) >> 1;
int x = (p % 64);
int y = (p >> 6);
all_holes_.emplace_back(
(x * 16) + (((mapId % 64) - (((mapId % 64) / 8) * 8)) * 512),
(y * 16) + (((mapId % 64) / 8) * 512), entranceId, mapId,
(ushort)(mapPos + 0x400), true);
(x * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512),
(y * 16) + (((map_id % 64) / 8) * 512), entrance_id, map_id,
(ushort)(map_pos + 0x400), true);
}
}
absl::Status Overworld::SaveEntrances() {
for (int i = 0; i < 129; i++) {
RETURN_IF_ERROR(
rom()->WriteShort(OWEntranceMap + (i * 2), all_entrances_[i].map_id_))
RETURN_IF_ERROR(
rom()->WriteShort(OWEntrancePos + (i * 2), all_entrances_[i].map_pos_))
RETURN_IF_ERROR(rom()->WriteByte(OWEntranceEntranceId + i,
all_entrances_[i].entrance_id_))
}
for (int i = 0; i < 0x13; i++) {
RETURN_IF_ERROR(
rom()->WriteShort(OWHoleArea + (i * 2), all_holes_[i].map_id_))
RETURN_IF_ERROR(
rom()->WriteShort(OWHolePos + (i * 2), all_holes_[i].map_pos_))
RETURN_IF_ERROR(
rom()->WriteByte(OWHoleEntrance + i, all_holes_[i].entrance_id_))
}
return absl::OkStatus();
}
absl::Status Overworld::SaveExits() {
for (int i = 0; i < 0x4F; i++) {
RETURN_IF_ERROR(
rom()->WriteShort(OWExitRoomId + (i * 2), all_exits_[i].room_id_))
RETURN_IF_ERROR(rom()->WriteByte(OWExitMapId + i, all_exits_[i].map_id_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitVram + (i * 2), all_exits_[i].map_pos_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitYScroll + (i * 2), all_exits_[i].y_scroll_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitXScroll + (i * 2), all_exits_[i].x_scroll_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitYPlayer + (i * 2), all_exits_[i].y_player_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitXPlayer + (i * 2), all_exits_[i].x_player_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitYCamera + (i * 2), all_exits_[i].y_camera_))
RETURN_IF_ERROR(
rom()->WriteShort(OWExitXCamera + (i * 2), all_exits_[i].x_camera_))
RETURN_IF_ERROR(
rom()->WriteByte(OWExitUnk1 + i, all_exits_[i].scroll_mod_y_))
RETURN_IF_ERROR(
rom()->WriteByte(OWExitUnk2 + i, all_exits_[i].scroll_mod_x_))
RETURN_IF_ERROR(rom()->WriteShort(OWExitDoorType1 + (i * 2),
all_exits_[i].door_type_1_))
RETURN_IF_ERROR(rom()->WriteShort(OWExitDoorType2 + (i * 2),
all_exits_[i].door_type_2_))
}
return absl::OkStatus();
}
void Overworld::LoadExits() {
const int NumberOfOverworldExits = 0x4F;
std::vector<OverworldExit> exits;
for (int i = 0; i < NumberOfOverworldExits; i++) {
auto rom_data = rom()->data();
ushort exitRoomID = (ushort)((rom_data[OWExitRoomId + (i * 2) + 1] << 8) +
rom_data[OWExitRoomId + (i * 2)]);
ushort exitMapID = rom_data[OWExitMapId + i];
ushort exitVRAM = (ushort)((rom_data[OWExitVram + (i * 2) + 1] << 8) +
rom_data[OWExitVram + (i * 2)]);
ushort exitYScroll = (ushort)((rom_data[OWExitYScroll + (i * 2) + 1] << 8) +
rom_data[OWExitYScroll + (i * 2)]);
ushort exitXScroll = (ushort)((rom_data[OWExitXScroll + (i * 2) + 1] << 8) +
rom_data[OWExitXScroll + (i * 2)]);
ushort exit_room_id = (ushort)((rom_data[OWExitRoomId + (i * 2) + 1] << 8) +
rom_data[OWExitRoomId + (i * 2)]);
ushort exit_map_id = rom_data[OWExitMapId + i];
ushort exit_vram = (ushort)((rom_data[OWExitVram + (i * 2) + 1] << 8) +
rom_data[OWExitVram + (i * 2)]);
ushort exit_y_scroll =
(ushort)((rom_data[OWExitYScroll + (i * 2) + 1] << 8) +
rom_data[OWExitYScroll + (i * 2)]);
ushort exit_x_scroll =
(ushort)((rom_data[OWExitXScroll + (i * 2) + 1] << 8) +
rom_data[OWExitXScroll + (i * 2)]);
ushort py = (ushort)((rom_data[OWExitYPlayer + (i * 2) + 1] << 8) +
rom_data[OWExitYPlayer + (i * 2)]);
ushort px = (ushort)((rom_data[OWExitXPlayer + (i * 2) + 1] << 8) +
rom_data[OWExitXPlayer + (i * 2)]);
ushort exitYCamera = (ushort)((rom_data[OWExitYCamera + (i * 2) + 1] << 8) +
rom_data[OWExitYCamera + (i * 2)]);
ushort exitXCamera = (ushort)((rom_data[OWExitXCamera + (i * 2) + 1] << 8) +
rom_data[OWExitXCamera + (i * 2)]);
ushort exitScrollModY = rom_data[OWExitUnk1 + i];
ushort exitScrollModX = rom_data[OWExitUnk2 + i];
ushort exitDoorType1 =
ushort exit_y_camera =
(ushort)((rom_data[OWExitYCamera + (i * 2) + 1] << 8) +
rom_data[OWExitYCamera + (i * 2)]);
ushort exit_x_camera =
(ushort)((rom_data[OWExitXCamera + (i * 2) + 1] << 8) +
rom_data[OWExitXCamera + (i * 2)]);
ushort exit_scroll_mod_y = rom_data[OWExitUnk1 + i];
ushort exit_scroll_mod_x = rom_data[OWExitUnk2 + i];
ushort exit_door_type_1 =
(ushort)((rom_data[OWExitDoorType1 + (i * 2) + 1] << 8) +
rom_data[OWExitDoorType1 + (i * 2)]);
ushort exitDoorType2 =
ushort exit_door_type_2 =
(ushort)((rom_data[OWExitDoorType2 + (i * 2) + 1] << 8) +
rom_data[OWExitDoorType2 + (i * 2)]);
OverworldExit exit(exitRoomID, exitMapID, exitVRAM, exitYScroll,
exitXScroll, py, px, exitYCamera, exitXCamera,
exitScrollModY, exitScrollModX, exitDoorType1,
exitDoorType2);
OverworldExit exit(exit_room_id, exit_map_id, exit_vram, exit_y_scroll,
exit_x_scroll, py, px, exit_y_camera, exit_x_camera,
exit_scroll_mod_y, exit_scroll_mod_x, exit_door_type_1,
exit_door_type_2);
std::cout << "Exit: " << i << " RoomID: " << exitRoomID
<< " MapID: " << exitMapID << " VRAM: " << exitVRAM
<< " YScroll: " << exitYScroll << " XScroll: " << exitXScroll
std::cout << "Exit: " << i << " RoomID: " << exit_room_id
<< " MapID: " << exit_map_id << " VRAM: " << exit_vram
<< " YScroll: " << exit_y_scroll << " XScroll: " << exit_x_scroll
<< " YPlayer: " << py << " XPlayer: " << px
<< " YCamera: " << exitYCamera << " XCamera: " << exitXCamera
<< " ScrollModY: " << exitScrollModY
<< " ScrollModX: " << exitScrollModX
<< " DoorType1: " << exitDoorType1
<< " DoorType2: " << exitDoorType2 << std::endl;
<< " YCamera: " << exit_y_camera << " XCamera: " << exit_x_camera
<< " ScrollModY: " << exit_scroll_mod_y
<< " ScrollModX: " << exit_scroll_mod_x
<< " DoorType1: " << exit_door_type_1
<< " DoorType2: " << exit_door_type_2 << std::endl;
if (px == 0xFFFF && py == 0xFFFF) {
exit.deleted = true;
@@ -1050,6 +1107,19 @@ absl::Status Overworld::LoadPrototype(ROM &rom,
return absl::OkStatus();
}
OWBlockset &Overworld::GetMapTiles(int world_type) {
switch (world_type) {
case 0:
return map_tiles_.light_world;
case 1:
return map_tiles_.dark_world;
case 2:
return map_tiles_.special_world;
default:
return map_tiles_.light_world;
}
}
} // namespace zelda3
} // namespace app
} // namespace yaze

View File

@@ -64,8 +64,19 @@ class OverworldExit {
public:
int x_;
int y_;
ushort y_scroll_;
ushort x_scroll_;
uchar y_player_;
uchar x_player_;
uchar y_camera_;
uchar x_camera_;
uchar scroll_mod_y_;
uchar scroll_mod_x_;
ushort door_type_1_;
ushort door_type_2_;
ushort room_id_;
ushort map_pos_;
ushort map_pos_; // Position in the vram
uchar entrance_id_;
uchar area_x_;
uchar area_y_;
@@ -84,7 +95,18 @@ class OverworldExit {
area_x_(0),
area_y_(0),
map_id_(mapID),
is_hole_(false) {
is_hole_(false),
room_id_(roomID),
y_scroll_(yScroll),
x_scroll_(xScroll),
y_player_(playerY),
x_player_(playerX),
y_camera_(cameraY),
x_camera_(cameraX),
scroll_mod_y_(scrollModY),
scroll_mod_x_(scrollModX),
door_type_1_(doorType1),
door_type_2_(doorType2) {
int mapX = (map_id_ - ((map_id_ / 8) * 8));
int mapY = (map_id_ / 8);
@@ -207,13 +229,13 @@ class OverworldEntrance {
bool is_hole_ = false;
bool deleted = false;
OverworldEntrance(int x, int y, uchar entranceId, short mapId, ushort mapPos,
bool hole)
OverworldEntrance(int x, int y, uchar entrance_id, short map_id,
ushort map_pos, bool hole)
: x_(x),
y_(y),
map_pos_(mapPos),
entrance_id_(entranceId),
map_id_(mapId),
map_pos_(map_pos),
entrance_id_(entrance_id),
map_id_(map_id),
is_hole_(hole) {
int mapX = (map_id_ - ((map_id_ / 8) * 8));
int mapY = (map_id_ / 8);
@@ -227,8 +249,8 @@ class OverworldEntrance {
is_hole_);
}
void updateMapStuff(short mapId) {
map_id_ = mapId;
void UpdateMapStuff(short map_id) {
map_id_ = map_id;
if (map_id_ >= 64) {
map_id_ -= 64;
@@ -317,10 +339,14 @@ struct MapData {
class Overworld : public SharedROM, public core::ExperimentFlags {
public:
absl::Status Load(ROM &rom);
absl::Status Save(ROM &rom);
OWBlockset &GetMapTiles(int world_type);
absl::Status LoadOverworldMaps();
absl::Status SaveOverworldMaps();
absl::Status SaveLargeMaps();
absl::Status SaveEntrances();
absl::Status SaveExits();
bool CreateTile32Tilemap(bool onlyShow = false);
absl::Status SaveMap16Tiles();
@@ -376,10 +402,11 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
void LoadSprites();
void LoadSpritesFromMap(int spriteStart, int spriteCount, int spriteIndex);
bool is_loaded_ = false;
int game_state_ = 0;
int current_map_ = 0;
uchar map_parent_[160];
bool is_loaded_ = false;
ROM rom_;
OWMapTiles map_tiles_;