diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index a8d3d1b9..f985acfe 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -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; } } diff --git a/src/app/rom.h b/src/app/rom.h index c9b951c3..086b8a11 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -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"); diff --git a/src/app/zelda3/overworld.cc b/src/app/zelda3/overworld.cc index 9193d045..4040f5a2 100644 --- a/src/app/zelda3/overworld.cc +++ b/src/app/zelda3/overworld.cc @@ -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 checkedMap; + std::unordered_map 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 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 \ No newline at end of file diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index 7909c425..d2e5ba05 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -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_;