yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
scad_format.cc
Go to the documentation of this file.
1#include "scad_format.h"
2
3#include <cstdint>
4#include <cstdlib>
5#include <cstring>
6#include <fstream>
7#include <iostream>
8#include <vector>
9
10#include "absl/status/status.h"
11#include "app/gfx/snes_tile.h"
12#include "util/macro.h"
13
14namespace yaze {
15namespace gfx {
16
18 int matching_position = -1;
19 bool matched = false;
20 std::vector<uint8_t> cgx_rom;
21 std::vector<uint8_t> raw_data_;
22 for (int i = 0;
23 i < cgx_rom.size() - sizeof(kMatchedBytes) - kOffsetFromMatchedBytesEnd;
24 i++) {
25 raw_data_.push_back(cgx_rom[i]);
26 bool is_match = std::equal(std::begin(kMatchedBytes),
27 std::end(kMatchedBytes), &cgx_rom[i]);
28 if (is_match) {
29 matching_position = i;
30 matched = true;
31 break;
32 }
33 }
34 if (matched) {
35 int bpp_marker_position =
36 matching_position + sizeof(kMatchedBytes) + kOffsetFromMatchedBytesEnd;
37 int bpp_marker = cgx_rom[bpp_marker_position];
38 std::string bpp_type = (bpp_marker == 0x31) ? "8bpp" : "4bpp";
39 }
40}
41
42absl::Status LoadCgx(uint8_t bpp, std::string_view filename,
43 std::vector<uint8_t>& cgx_data,
44 std::vector<uint8_t>& cgx_loaded,
45 std::vector<uint8_t>& cgx_header) {
46 std::ifstream file(filename.data(), std::ios::binary);
47 if (!file.is_open()) {
48 return absl::NotFoundError("CGX file not found.");
49 }
50 std::vector<uint8_t> file_content((std::istreambuf_iterator<char>(file)),
51 std::istreambuf_iterator<char>());
52 cgx_data =
53 std::vector<uint8_t>(file_content.begin(), file_content.end() - 0x500);
54 file.seekg(cgx_data.size() + 0x100);
55 cgx_header = std::vector<uint8_t>((std::istreambuf_iterator<char>(file)),
56 std::istreambuf_iterator<char>());
57 file.close();
58
59 if (bpp > 8) {
60 cgx_loaded = gfx::Bpp8SnesToIndexed(cgx_data, 40);
61 return absl::OkStatus();
62 }
63 cgx_loaded = gfx::Bpp8SnesToIndexed(cgx_data, bpp);
64 return absl::OkStatus();
65}
66
67absl::Status LoadScr(std::string_view filename, uint8_t input_value,
68 std::vector<uint8_t>& map_data) {
69 std::ifstream file(filename.data(), std::ios::binary);
70 if (!file.is_open()) {
71 return absl::NotFoundError("SCR/PNL/MAP file not found.");
72 }
73
74 // Check if file extension is PNL
75 bool pnl = false;
76 if (filename.find("PNL") != std::string::npos) {
77 std::vector<uint8_t> scr_data;
78 map_data.resize(0x8000);
79 scr_data.resize(0x8000);
80
81 // Read from file for 0x8000 bytes
82 std::vector<uint8_t> file_content((std::istreambuf_iterator<char>(file)),
83 std::istreambuf_iterator<char>());
84 scr_data = std::vector<uint8_t>(file_content.begin(), file_content.end());
85
86 int md = 0x100;
87
88 for (int i = input_value * 0x400; i < 0x1000 + input_value * 0x400;
89 i += 2) {
90 auto b1_pos = (i - (input_value * 0x400));
91 map_data[b1_pos] = gfx::TileInfoToShort(
92 gfx::GetTilesInfo((uint16_t)scr_data[md + (i * 2)]));
93
94 auto b2_pos = (i - (input_value * 0x400) + 1);
95 map_data[b2_pos] = gfx::TileInfoToShort(
96 gfx::GetTilesInfo((uint16_t)scr_data[md + (i * 2) + 2]));
97 }
98 // 0x900
99
100 } else {
101 int offset = 0;
102 std::vector<uint8_t> scr_data;
103 map_data.resize(0x2000);
104 scr_data.resize(0x2000);
105
106 // read from file for 0x2000 bytes
107 std::vector<uint8_t> file_content((std::istreambuf_iterator<char>(file)),
108 std::istreambuf_iterator<char>());
109 scr_data = std::vector<uint8_t>(file_content.begin(), file_content.end());
110
111 for (int i = 0; i < 0x1000 - offset; i++) {
112 map_data[i] = gfx::TileInfoToShort(
113 gfx::GetTilesInfo((uint16_t)scr_data[((i + offset) * 2)]));
114 }
115 }
116 return absl::OkStatus();
117}
118
119absl::Status DrawScrWithCgx(uint8_t bpp, std::vector<uint8_t>& map_bitmap_data,
120 std::vector<uint8_t>& map_data,
121 std::vector<uint8_t>& cgx_loaded) {
122 const std::vector<uint16_t> dimensions = {0x000, 0x400, 0x800, 0xC00};
123 uint8_t p = 0;
124 for (const auto each_dimension : dimensions) {
125 p = each_dimension;
126 // for each tile on the tile buffer
127 for (int i = 0; i < 0x400; i++) {
128 if (map_data[i + p] != 0xFF) {
129 auto t = gfx::GetTilesInfo(map_data[i + p]);
130
131 for (auto yl = 0; yl < 8; yl++) {
132 for (auto xl = 0; xl < 8; xl++) {
133 int mx = xl * (1 - t.horizontal_mirror_) +
134 (7 - xl) * (t.horizontal_mirror_);
135 int my =
136 yl * (1 - t.vertical_mirror_) + (7 - yl) * (t.vertical_mirror_);
137
138 int ty = (t.id_ / 16) * 1024;
139 int tx = (t.id_ % 16) * 8;
140 auto pixel = cgx_loaded[(tx + ty) + (yl * 128) + xl];
141
142 int index = (((i % 32) * 8) + ((i / 32) * 2048) + mx + (my * 256));
143
144 if (bpp != 8) {
145 map_bitmap_data[index] =
146 (uint8_t)((pixel & 0xFF) + t.palette_ * 16);
147 } else {
148 map_bitmap_data[index] = (uint8_t)(pixel & 0xFF);
149 }
150 }
151 }
152 }
153 }
154 }
155 return absl::OkStatus();
156}
157
158absl::Status SaveCgx(uint8_t bpp, std::string_view filename,
159 const std::vector<uint8_t>& cgx_data,
160 const std::vector<uint8_t>& cgx_header) {
161 std::ofstream file(filename.data(), std::ios::binary);
162 if (!file.is_open()) {
163 return absl::NotFoundError("Could not open file for writing.");
164 }
165
166 CgxHeader header;
167 strncpy(header.file_type, "SCH", 4);
168 std::string bpp_str = std::to_string(bpp) + "BIT";
169 strncpy(header.bit_mode, bpp_str.c_str(), 5);
170 strncpy(header.version_number, "Ver-0.01\n", 9);
171 header.header_size = sizeof(CgxHeader);
172 strncpy(header.hardware_name, "SFC", 4);
173 header.bg_obj_flag = 0;
174 header.color_palette_number = 0;
175
176 file.write(reinterpret_cast<const char*>(&header), sizeof(CgxHeader));
177 file.write(reinterpret_cast<const char*>(cgx_data.data()), cgx_data.size());
178 file.write(reinterpret_cast<const char*>(cgx_header.data()), cgx_header.size());
179
180 file.close();
181 return absl::OkStatus();
182}
183
184
185
186std::vector<SDL_Color> DecodeColFile(const std::string_view filename) {
187 std::vector<SDL_Color> decoded_col;
188 std::ifstream file(filename.data(), std::ios::binary | std::ios::ate);
189
190 if (!file.is_open()) {
191 return decoded_col; // Return an empty vector if the file couldn't be
192 // opened.
193 }
194
195 std::streamsize size = file.tellg();
196 file.seekg(0, std::ios::beg);
197
198 std::vector<char> buffer(size);
199 if (file.read(buffer.data(), size)) {
200 buffer.resize(size - 0x200);
201
202 int k = 0;
203 for (size_t i = 0; i < buffer.size() / 2; i++) {
204 uint16_t current_color = static_cast<unsigned char>(buffer[k]) |
205 (static_cast<unsigned char>(buffer[k + 1]) << 8);
206
207 SDL_Color color;
208 color.r = (current_color & 31) << 3;
209 color.g = ((current_color >> 5) & 31) << 3;
210 color.b = ((current_color >> 10) & 31) << 3;
211 color.a = (i & 0xF) == 0 ? 0 : 255;
212
213 decoded_col.push_back(color);
214 k += 2;
215 }
216 }
217
218 return decoded_col;
219}
220
221absl::Status SaveCol(std::string_view filename, const std::vector<SDL_Color>& palette) {
222 std::ofstream file(filename.data(), std::ios::binary);
223 if (!file.is_open()) {
224 return absl::NotFoundError("Could not open file for writing.");
225 }
226
227 for (const auto& color : palette) {
228 uint16_t snes_color = ((color.b >> 3) << 10) |
229 ((color.g >> 3) << 5) |
230 (color.r >> 3);
231 file.write(reinterpret_cast<const char*>(&snes_color), sizeof(snes_color));
232 }
233
234 file.close();
235 return absl::OkStatus();
236}
237
238absl::Status DecodeObjFile(
239 std::string_view filename, std::vector<uint8_t>& obj_data,
240 std::vector<uint8_t> actual_obj_data,
241 std::unordered_map<std::string, std::vector<uint8_t>> decoded_obj,
242 std::vector<uint8_t>& decoded_extra_obj, int& obj_loaded) {
243 std::vector<uint8_t> header_obj;
244 int obj_range;
245 int expected_cut;
246 if (obj_loaded == 0) {
247 obj_range = 0x180;
248 expected_cut = 0x500;
249 } else {
250 obj_range = 0x300;
251 expected_cut = 0x900;
252 }
253
254 std::ifstream file(filename.data(), std::ios::binary);
255 if (!file.is_open()) {
256 return absl::NotFoundError("OBJ file not found.");
257 }
258
259 std::vector<uint8_t> file_content((std::istreambuf_iterator<char>(file)),
260 std::istreambuf_iterator<char>());
261 obj_data = file_content;
262 file.close();
263
264 int cut = obj_data.size() & 0x0FFF;
265 actual_obj_data =
266 std::vector<uint8_t>(obj_data.begin(), obj_data.end() - cut);
267 decoded_extra_obj =
268 std::vector<uint8_t>(obj_data.begin() + actual_obj_data.size(),
269 obj_data.begin() + actual_obj_data.size() + 0x100);
270 header_obj = std::vector<uint8_t>(
271 actual_obj_data.begin() + actual_obj_data.size(), actual_obj_data.end());
272
273 if (cut > expected_cut) {
274 std::vector<uint8_t> scad_data;
275 int j = 0;
276 int k = (obj_loaded == 0) ? 63 : 127;
277
278 for (size_t i = 0; i < (actual_obj_data.size() / 6); i++) {
279 std::vector<uint8_t> data = {
280 actual_obj_data[k * 6 + 0 + j], // display
281 actual_obj_data[k * 6 + 1 + j], // unknown
282 actual_obj_data[k * 6 + 2 + j], // y-disp
283 actual_obj_data[k * 6 + 3 + j], // x-disp
284 actual_obj_data[k * 6 + 5 + j], // props
285 actual_obj_data[k * 6 + 4 + j] // tile
286 };
287 scad_data.insert(scad_data.end(), data.begin(), data.end());
288
289 k = k - 1;
290 if (k == -1) {
291 k = (obj_loaded == 0) ? 63 : 127;
292 j = j + ((k + 1) * 6);
293 }
294 }
295
296 int extra_data_range = 0x400 * (obj_loaded + 1) + 0x100;
297 for (int i = 0; i < extra_data_range; i++) {
298 scad_data.push_back(header_obj[i]);
299 }
300
301 obj_data = scad_data;
302 actual_obj_data =
303 std::vector<uint8_t>(obj_data.begin(), obj_data.end() - cut);
304 }
305
306 decoded_obj.clear();
307 for (int k = 0; k < 128; k++) {
308 decoded_obj["frame " + std::to_string(k)] = std::vector<uint8_t>(obj_range);
309 for (int i = 0; i < obj_range; i++) {
310 try {
311 decoded_obj["frame " + std::to_string(k)][i] =
312 obj_data[i + (obj_range * k)];
313 } catch (...) {
314 decoded_obj["frame " + std::to_string(k)][i] = 0;
315 }
316 }
317 }
318
319 return absl::OkStatus();
320}
321
322} // namespace gfx
323} // namespace yaze
absl::Status SaveCol(std::string_view filename, const std::vector< SDL_Color > &palette)
Save Col file (palette data)
absl::Status DecodeObjFile(std::string_view filename, std::vector< uint8_t > &obj_data, std::vector< uint8_t > actual_obj_data, std::unordered_map< std::string, std::vector< uint8_t > > decoded_obj, std::vector< uint8_t > &decoded_extra_obj, int &obj_loaded)
Decode obj file.
absl::Status LoadScr(std::string_view filename, uint8_t input_value, std::vector< uint8_t > &map_data)
Load Scr file (screen data)
std::vector< SDL_Color > DecodeColFile(const std::string_view filename)
Decode color file.
absl::Status LoadCgx(uint8_t bpp, std::string_view filename, std::vector< uint8_t > &cgx_data, std::vector< uint8_t > &cgx_loaded, std::vector< uint8_t > &cgx_header)
Load Cgx file (graphical content)
absl::Status SaveCgx(uint8_t bpp, std::string_view filename, const std::vector< uint8_t > &cgx_data, const std::vector< uint8_t > &cgx_header)
Save Cgx file (graphical content)
absl::Status DrawScrWithCgx(uint8_t bpp, std::vector< uint8_t > &map_bitmap_data, std::vector< uint8_t > &map_data, std::vector< uint8_t > &cgx_loaded)
Draw screen tilemap with graphical data.
uint16_t TileInfoToShort(TileInfo tile_info)
Definition snes_tile.cc:323
std::vector< uint8_t > Bpp8SnesToIndexed(std::vector< uint8_t > data, uint64_t bpp)
Definition snes_tile.cc:189
void FindMetastamp()
Find metastamp in CGX file.
constexpr uint16_t kMatchedBytes[]
Definition scad_format.h:47
constexpr uint16_t kOffsetFromMatchedBytesEnd
Definition scad_format.h:48
TileInfo GetTilesInfo(uint16_t tile)
Definition snes_tile.cc:354
Main namespace for the application.
SNES color in 15-bit RGB format (BGR555)
Definition yaze.h:208
Cgx file header.
Definition scad_format.h:35
uint8_t color_palette_number
Definition scad_format.h:42