yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_map.cc
Go to the documentation of this file.
1#include "dungeon_map.h"
2
3#include <fstream>
4#include <vector>
5
6#include "util/file_util.h"
7#include "app/core/window.h"
8#include "app/gfx/bitmap.h"
9#include "app/gfx/snes_tile.h"
10#include "app/gfx/tilemap.h"
12#include "app/snes.h"
13#include "util/hex.h"
14
15namespace yaze::zelda3 {
16
17absl::StatusOr<std::vector<DungeonMap>> LoadDungeonMaps(
18 Rom &rom, DungeonMapLabels &dungeon_map_labels) {
19 std::vector<DungeonMap> dungeon_maps;
20 std::vector<std::array<uint8_t, kNumRooms>> current_floor_rooms_d;
21 std::vector<std::array<uint8_t, kNumRooms>> current_floor_gfx_d;
22 int total_floors_d;
23 uint8_t nbr_floor_d;
24 uint8_t nbr_basement_d;
25
26 for (int d = 0; d < kNumDungeons; d++) {
27 current_floor_rooms_d.clear();
28 current_floor_gfx_d.clear();
29 ASSIGN_OR_RETURN(int ptr, rom.ReadWord(kDungeonMapRoomsPtr + (d * 2)));
30 ASSIGN_OR_RETURN(int ptr_gfx, rom.ReadWord(kDungeonMapGfxPtr + (d * 2)));
31 ptr |= 0x0A0000; // Add bank to the short ptr
32 ptr_gfx |= 0x0A0000; // Add bank to the short ptr
33 int pc_ptr = SnesToPc(ptr); // Contains data for the next 25 rooms
34 int pc_ptr_gfx = SnesToPc(ptr_gfx); // Contains data for the next 25 rooms
35
36 ASSIGN_OR_RETURN(uint16_t boss_room_d,
37 rom.ReadWord(kDungeonMapBossRooms + (d * 2)));
38
39 ASSIGN_OR_RETURN(nbr_basement_d, rom.ReadByte(kDungeonMapFloors + (d * 2)));
40 nbr_basement_d &= 0x0F;
41
42 ASSIGN_OR_RETURN(nbr_floor_d, rom.ReadByte(kDungeonMapFloors + (d * 2)));
43 nbr_floor_d &= 0xF0;
44 nbr_floor_d = nbr_floor_d >> 4;
45
46 total_floors_d = nbr_basement_d + nbr_floor_d;
47
48 // for each floor in the dungeon
49 for (int i = 0; i < total_floors_d; i++) {
50 dungeon_map_labels[d].emplace_back();
51
52 std::array<uint8_t, kNumRooms> rdata;
53 std::array<uint8_t, kNumRooms> gdata;
54
55 // for each room on the floor
56 for (int j = 0; j < kNumRooms; j++) {
57 gdata[j] = 0xFF;
58 rdata[j] = rom.data()[pc_ptr + j + (i * kNumRooms)]; // Set the rooms
59
60 gdata[j] = rdata[j] == 0x0F ? 0xFF : rom.data()[pc_ptr_gfx++];
61
62 std::string label = util::HexByte(rdata[j]);
63 dungeon_map_labels[d][i][j] = label;
64 }
65
66 current_floor_gfx_d.push_back(gdata); // Add new floor gfx data
67 current_floor_rooms_d.push_back(rdata); // Add new floor data
68 }
69
70 dungeon_maps.emplace_back(boss_room_d, nbr_floor_d, nbr_basement_d,
71 current_floor_rooms_d, current_floor_gfx_d);
72 }
73
74 return dungeon_maps;
75}
76
77absl::Status SaveDungeonMaps(Rom &rom, std::vector<DungeonMap> &dungeon_maps) {
78 for (int d = 0; d < kNumDungeons; d++) {
79 int ptr = kDungeonMapRoomsPtr + (d * 2);
80 int ptr_gfx = kDungeonMapGfxPtr + (d * 2);
81 int pc_ptr = SnesToPc(ptr);
82 int pc_ptr_gfx = SnesToPc(ptr_gfx);
83
84 const int nbr_floors = dungeon_maps[d].nbr_of_floor;
85 const int nbr_basements = dungeon_maps[d].nbr_of_basement;
86 for (int i = 0; i < nbr_floors + nbr_basements; i++) {
87 for (int j = 0; j < kNumRooms; j++) {
88 RETURN_IF_ERROR(rom.WriteByte(pc_ptr + j + (i * kNumRooms),
89 dungeon_maps[d].floor_rooms[i][j]));
90 RETURN_IF_ERROR(rom.WriteByte(pc_ptr_gfx + j + (i * kNumRooms),
91 dungeon_maps[d].floor_gfx[i][j]));
92 pc_ptr_gfx++;
93 }
94 }
95 }
96
97 return absl::OkStatus();
98}
99
100absl::Status LoadDungeonMapTile16(gfx::Tilemap &tile16_blockset, Rom &rom,
101 const std::vector<uint8_t> &gfx_data,
102 bool bin_mode) {
103 tile16_blockset.tile_size = {16, 16};
104 tile16_blockset.map_size = {186, 186};
105 tile16_blockset.atlas.Create(256, 192, 8,
106 std::vector<uint8_t>(256 * 192, 0x00));
107
108 for (int i = 0; i < kNumDungeonMapTile16; i++) {
109 int addr = kDungeonMapTile16;
110 if (rom.data()[kDungeonMapExpCheck] != 0xB9) {
112 }
113
114 ASSIGN_OR_RETURN(auto tl, rom.ReadWord(addr + (i * 8)));
115 gfx::TileInfo t1 = gfx::WordToTileInfo(tl); // Top left
116
117 ASSIGN_OR_RETURN(auto tr, rom.ReadWord(addr + 2 + (i * 8)));
118 gfx::TileInfo t2 = gfx::WordToTileInfo(tr); // Top right
119
120 ASSIGN_OR_RETURN(auto bl, rom.ReadWord(addr + 4 + (i * 8)));
121 gfx::TileInfo t3 = gfx::WordToTileInfo(bl); // Bottom left
122
123 ASSIGN_OR_RETURN(auto br, rom.ReadWord(addr + 6 + (i * 8)));
124 gfx::TileInfo t4 = gfx::WordToTileInfo(br); // Bottom right
125
126 int sheet_offset = 212;
127 if (bin_mode) {
128 sheet_offset = 0;
129 }
130 ComposeTile16(tile16_blockset, gfx_data, t1, t2, t3, t4, sheet_offset);
131 }
132
133 tile16_blockset.atlas.SetPalette(*rom.mutable_dungeon_palette(3));
134 // TODO: Queue texture for later rendering.
135 // core::Renderer::Get().RenderBitmap(&tile16_blockset.atlas);
136 return absl::OkStatus();
137}
138
139absl::Status SaveDungeonMapTile16(gfx::Tilemap &tile16_blockset, Rom &rom) {
140 for (int i = 0; i < kNumDungeonMapTile16; i++) {
141 int addr = kDungeonMapTile16;
142 if (rom.data()[kDungeonMapExpCheck] != 0xB9) {
144 }
145
146 gfx::TileInfo t1 = tile16_blockset.tile_info[i][0];
147 gfx::TileInfo t2 = tile16_blockset.tile_info[i][1];
148 gfx::TileInfo t3 = tile16_blockset.tile_info[i][2];
149 gfx::TileInfo t4 = tile16_blockset.tile_info[i][3];
150
151 auto tl = gfx::TileInfoToWord(t1);
152 RETURN_IF_ERROR(rom.WriteWord(addr + (i * 8), tl));
153
154 auto tr = gfx::TileInfoToWord(t2);
155 RETURN_IF_ERROR(rom.WriteWord(addr + 2 + (i * 8), tr));
156
157 auto bl = gfx::TileInfoToWord(t3);
158 RETURN_IF_ERROR(rom.WriteWord(addr + 4 + (i * 8), bl));
159
160 auto br = gfx::TileInfoToWord(t4);
161 RETURN_IF_ERROR(rom.WriteWord(addr + 6 + (i * 8), br));
162 }
163 return absl::OkStatus();
164}
165
167 gfx::Tilemap &tile16_blockset,
168 std::array<gfx::Bitmap, 4> &sheets,
169 std::vector<uint8_t> &gfx_bin_data) {
170 std::string bin_file = util::FileDialogWrapper::ShowOpenFileDialog();
171 if (bin_file.empty()) {
172 return absl::InternalError("No file selected");
173 }
174
175 std::ifstream file(bin_file, std::ios::binary);
176 if (!file.is_open()) {
177 return absl::InternalError("Failed to open file");
178 }
179
180 // Read the gfx data into a buffer
181 std::vector<uint8_t> bin_data((std::istreambuf_iterator<char>(file)),
182 std::istreambuf_iterator<char>());
183 auto converted_bin = gfx::SnesTo8bppSheet(bin_data, 4, 4);
184 gfx_bin_data = converted_bin;
185 if (LoadDungeonMapTile16(tile16_blockset, rom, converted_bin, true).ok()) {
186 std::vector<std::vector<uint8_t>> gfx_sheets;
187 for (int i = 0; i < 4; i++) {
188 gfx_sheets.emplace_back(converted_bin.begin() + (i * 0x1000),
189 converted_bin.begin() + ((i + 1) * 0x1000));
190 sheets[i] = gfx::Bitmap(128, 32, 8, gfx_sheets[i]);
191 sheets[i].SetPalette(*rom.mutable_dungeon_palette(3));
192 // TODO: Queue texture for later rendering.
193 // core::Renderer::Get().RenderBitmap(&sheets[i]);
194 }
195 }
196 file.close();
197
198 return absl::OkStatus();
199}
200
201} // namespace yaze::zelda3
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:71
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:725
auto mutable_dungeon_palette(int i)
Definition rom.h:216
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:665
auto data() const
Definition rom.h:203
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:658
absl::Status WriteWord(int addr, uint16_t value)
Definition rom.cc:737
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:66
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
Definition bitmap.cc:162
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap.
Definition bitmap.cc:292
SNES 16-bit tile metadata container.
Definition snes_tile.h:50
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define RETURN_IF_ERROR(expression)
Definition macro.h:53
#define ASSIGN_OR_RETURN(type_variable_name, expression)
Definition macro.h:61
uint16_t TileInfoToWord(TileInfo tile_info)
Definition snes_tile.cc:291
std::vector< uint8_t > SnesTo8bppSheet(std::span< uint8_t > sheet, int bpp, int num_sheets)
Definition snes_tile.cc:129
TileInfo WordToTileInfo(uint16_t word)
Definition snes_tile.cc:308
std::string HexByte(uint8_t byte, HexStringParams params)
Definition hex.cc:30
Zelda 3 specific classes and functions.
absl::Status LoadDungeonMapGfxFromBinary(Rom &rom, gfx::Tilemap &tile16_blockset, std::array< gfx::Bitmap, 4 > &sheets, std::vector< uint8_t > &gfx_bin_data)
Load the dungeon map gfx from binary.
constexpr int kDungeonMapExpCheck
Definition dungeon_map.h:23
absl::Status LoadDungeonMapTile16(gfx::Tilemap &tile16_blockset, Rom &rom, const std::vector< uint8_t > &gfx_data, bool bin_mode)
Load the dungeon map tile16 from the ROM.
constexpr int kDungeonMapFloors
Definition dungeon_map.h:15
constexpr int kDungeonMapTile16
Definition dungeon_map.h:24
constexpr int kNumRooms
Definition dungeon_map.h:35
constexpr int kDungeonMapTile16Expanded
Definition dungeon_map.h:25
absl::Status SaveDungeonMapTile16(gfx::Tilemap &tile16_blockset, Rom &rom)
Save the dungeon map tile16 to the ROM.
constexpr int kDungeonMapBossRooms
Definition dungeon_map.h:28
constexpr int kDungeonMapRoomsPtr
Definition dungeon_map.h:14
constexpr int kNumDungeonMapTile16
Definition dungeon_map.h:36
constexpr int kNumDungeons
Definition dungeon_map.h:34
absl::StatusOr< std::vector< DungeonMap > > LoadDungeonMaps(Rom &rom, DungeonMapLabels &dungeon_map_labels)
Load the dungeon maps from the ROM.
std::array< std::vector< std::array< std::string, kNumRooms > >, kNumDungeons > DungeonMapLabels
Definition dungeon_map.h:60
constexpr int kDungeonMapGfxPtr
Definition dungeon_map.h:17
absl::Status SaveDungeonMaps(Rom &rom, std::vector< DungeonMap > &dungeon_maps)
Save the dungeon maps to the ROM.
uint32_t SnesToPc(uint32_t addr) noexcept
Definition snes.h:8
Tilemap structure for SNES tile-based graphics management.
Definition tilemap.h:109
Pair tile_size
Size of individual tiles (8x8 or 16x16)
Definition tilemap.h:113
Pair map_size
Size of tilemap in tiles.
Definition tilemap.h:114
Bitmap atlas
Master bitmap containing all tiles.
Definition tilemap.h:110
std::vector< std::array< gfx::TileInfo, 4 > > tile_info
Tile metadata (4 tiles per 16x16)
Definition tilemap.h:112