yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
snes_tile.cc
Go to the documentation of this file.
1#include "snes_tile.h"
2
3#include <cassert>
4#include <cstdint>
5#include <stdexcept>
6#include <vector>
7
8namespace yaze {
9namespace gfx {
10
11// Bit set for object priority
12constexpr uint16_t TilePriorityBit = 0x2000;
13
14// Bit set for object hflip
15constexpr uint16_t TileHFlipBit = 0x4000;
16
17// Bit set for object vflip
18constexpr uint16_t TileVFlipBit = 0x8000;
19
20// Bits used for tile name
21constexpr uint16_t TileNameMask = 0x03FF;
22
23snes_tile8 UnpackBppTile(std::span<uint8_t> data, const uint32_t offset,
24 const uint32_t bpp) {
25 snes_tile8 tile;
26 assert(bpp >= 1 && bpp <= 8);
27 unsigned int bpp_pos[8]; // More for conveniance and readibility
28 for (int col = 0; col < 8; col++) {
29 for (int row = 0; row < 8; row++) {
30 if (bpp == 1) {
31 tile.data[col * 8 + row] = (data[offset + col] >> (7 - row)) & 0x01;
32 continue;
33 }
34 /* SNES bpp format interlace each byte of the first 2 bitplanes.
35 * | byte 1 of first bitplane | byte 1 of second bitplane |
36 * | byte 2 of first bitplane | byte 2 of second bitplane | ..
37 */
38 bpp_pos[0] = offset + col * 2;
39 bpp_pos[1] = offset + col * 2 + 1;
40 char mask = 1 << (7 - row);
41 tile.data[col * 8 + row] = (data[bpp_pos[0]] & mask) == mask;
42 tile.data[col * 8 + row] |= ((data[bpp_pos[1]] & mask) == mask) << 1;
43 if (bpp == 3) {
44 // When we have 3 bitplanes, the bytes for the third bitplane are after
45 // the 16 bytes of the 2 bitplanes.
46 bpp_pos[2] = offset + 16 + col;
47 tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2;
48 }
49 if (bpp >= 4) {
50 // For 4 bitplanes, the 2 added bitplanes are interlaced like the first
51 // two.
52 bpp_pos[2] = offset + 16 + col * 2;
53 bpp_pos[3] = offset + 16 + col * 2 + 1;
54 tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2;
55 tile.data[col * 8 + row] |= ((data[bpp_pos[3]] & mask) == mask) << 3;
56 }
57 if (bpp == 8) {
58 bpp_pos[4] = offset + 32 + col * 2;
59 bpp_pos[5] = offset + 32 + col * 2 + 1;
60 bpp_pos[6] = offset + 48 + col * 2;
61 bpp_pos[7] = offset + 48 + col * 2 + 1;
62 tile.data[col * 8 + row] |= ((data[bpp_pos[4]] & mask) == mask) << 4;
63 tile.data[col * 8 + row] |= ((data[bpp_pos[5]] & mask) == mask) << 5;
64 tile.data[col * 8 + row] |= ((data[bpp_pos[6]] & mask) == mask) << 6;
65 tile.data[col * 8 + row] |= ((data[bpp_pos[7]] & mask) == mask) << 7;
66 }
67 }
68 }
69 return tile;
70}
71
72std::vector<uint8_t> PackBppTile(const snes_tile8& tile, const uint32_t bpp) {
73 // Allocate memory for output data
74 std::vector<uint8_t> output(bpp * 8, 0); // initialized with 0
75 unsigned maxcolor = 2 << bpp;
76
77 // Iterate over all columns and rows of the tile
78 for (unsigned int col = 0; col < 8; col++) {
79 for (unsigned int row = 0; row < 8; row++) {
80 uint8_t color = tile.data[col * 8 + row];
81 if (color > maxcolor) {
82 throw std::invalid_argument("Invalid color value.");
83 }
84
85 // 1bpp format
86 if (bpp == 1) output[col] += (uint8_t)((color & 1) << (7 - row));
87
88 // 2bpp format
89 if (bpp >= 2) {
90 output[col * 2] += ((color & 1) << (7 - row));
91 output[col * 2 + 1] += (((color & 2) == 2) << (7 - row));
92 }
93
94 // 3bpp format
95 if (bpp == 3) output[16 + col] += (((color & 4) == 4) << (7 - row));
96
97 // 4bpp format
98 if (bpp >= 4) {
99 output[16 + col * 2] += (((color & 4) == 4) << (7 - row));
100 output[16 + col * 2 + 1] += (((color & 8) == 8) << (7 - row));
101 }
102
103 // 8bpp format
104 if (bpp == 8) {
105 output[32 + col * 2] += (((color & 16) == 16) << (7 - row));
106 output[32 + col * 2 + 1] += (((color & 32) == 32) << (7 - row));
107 output[48 + col * 2] += (((color & 64) == 64) << (7 - row));
108 output[48 + col * 2 + 1] += (((color & 128) == 128) << (7 - row));
109 }
110 }
111 }
112 return output;
113}
114
115std::vector<uint8_t> ConvertBpp(std::span<uint8_t> tiles, uint32_t from_bpp,
116 uint32_t to_bpp) {
117 unsigned int nb_tile = tiles.size() / (from_bpp * 8);
118 std::vector<uint8_t> converted(nb_tile * to_bpp * 8);
119
120 for (unsigned int i = 0; i < nb_tile; i++) {
121 snes_tile8 tile = UnpackBppTile(tiles, i * from_bpp * 8, from_bpp);
122 std::vector<uint8_t> packed_tile = PackBppTile(tile, to_bpp);
123 std::memcpy(converted.data() + i * to_bpp * 8, packed_tile.data(),
124 to_bpp * 8);
125 }
126 return converted;
127}
128
129std::vector<uint8_t> SnesTo8bppSheet(std::span<uint8_t> sheet, int bpp,
130 int num_sheets) {
131 int xx = 0; // positions where we are at on the sheet
132 int yy = 0;
133 int pos = 0;
134 int ypos = 0;
135 int num_tiles = 64;
136 int buffer_size = 0x1000;
137
138 if (bpp == 2) {
139 bpp = 16;
140 num_tiles = 128;
141 buffer_size = 0x2000;
142 } else if (bpp == 3) {
143 bpp = 24;
144 } else if (bpp == 4) {
145 bpp = 32;
146 buffer_size = 0x4000;
147 } else if (bpp == 8) {
148 bpp = 64;
149 }
150
151 if (num_sheets != 1) {
152 num_tiles *= num_sheets;
153 buffer_size *= num_sheets;
154 }
155
156 std::vector<uint8_t> sheet_buffer_out(buffer_size);
157
158 for (int i = 0; i < num_tiles; i++) { // for each tiles, 16 per line
159 for (int y = 0; y < 8; y++) { // for each line
160 for (int x = 0; x < 8; x++) { //[0] + [1] + [16]
161 auto b1 = (sheet[(y * 2) + (bpp * pos)] & (kGraphicsBitmap[x]));
162 auto b2 = (sheet[((y * 2) + (bpp * pos)) + 1] & (kGraphicsBitmap[x]));
163 auto b3 = (sheet[(16 + y) + (bpp * pos)] & (kGraphicsBitmap[x]));
164 unsigned char b = 0;
165 if (b1 != 0) {
166 b |= 1;
167 }
168 if (b2 != 0) {
169 b |= 2;
170 }
171 if (b3 != 0 && bpp != 16) {
172 b |= 4;
173 }
174 sheet_buffer_out[x + xx + (y * 128) + (yy * 1024)] = b;
175 }
176 }
177 pos++;
178 ypos++;
179 xx += 8;
180 if (ypos >= 16) {
181 yy++;
182 xx = 0;
183 ypos = 0;
184 }
185 }
186 return sheet_buffer_out;
187}
188
189std::vector<uint8_t> Bpp8SnesToIndexed(std::vector<uint8_t> data,
190 uint64_t bpp) {
191 // 3BPP
192 // [r0,bp1],[r0,bp2],[r1,bp1],[r1,bp2],[r2,bp1],[r2,bp2],[r3,bp1],[r3,bp2]
193 // [r4,bp1],[r4,bp2],[r5,bp1],[r5,bp2],[r6,bp1],[r6,bp2],[r7,bp1],[r7,bp2]
194 // [r0,bp3],[r0,bp4],[r1,bp3],[r1,bp4],[r2,bp3],[r2,bp4],[r3,bp3],[r3,bp4]
195 // [r4,bp3],[r4,bp4],[r5,bp3],[r5,bp4],[r6,bp3],[r6,bp4],[r7,bp3],[r7,bp4]
196 // [r0,bp5],[r0,bp6],[r1,bp5],[r1,bp6],[r2,bp5],[r2,bp6],[r3,bp5],[r3,bp6]
197 // [r4,bp5],[r4,bp6],[r5,bp5],[r5,bp6],[r6,bp5],[r6,bp6],[r7,bp5],[r7,bp6]
198 // [r0,bp7],[r0,bp8],[r1,bp7],[r1,bp8],[r2,bp7],[r2,bp8],[r3,bp7],[r3,bp8]
199 // [r4,bp7],[r4,bp8],[r5,bp7],[r5,bp8],[r6,bp7],[r6,bp8],[r7,bp7],[r7,bp8]
200
201 // 16 tiles = 1024 bytes
202 auto buffer = std::vector<uint8_t>(data.size());
203 std::vector<std::vector<uint8_t>> bitmap_data;
204 bitmap_data.resize(0x80);
205 for (auto& each : bitmap_data) {
206 each.reserve(0x800);
207 }
208 int yy = 0;
209 int xx = 0;
210 int pos = 0;
211
212 const uint16_t sheet_width = 128;
213
214 // 64 = 4096 bytes
215 // 16 = 1024?
216 int ypos = 0;
217 // for each tiles //16 per lines
218 for (int i = 0; i < 4096; i++) {
219 // for each lines
220 for (int y = 0; y < 8; y++) {
221 //[0] + [1] + [16]
222 for (int x = 0; x < 8; x++) {
223 const uint16_t bitmask[] = {0x80, 0x40, 0x20, 0x10,
224 0x08, 0x04, 0x02, 0x01};
225 auto b1 = (data[(y * 2) + ((bpp * 8) * pos)] & (bitmask[x]));
226 auto b2 = (data[((y * 2) + ((bpp * 8) * pos)) + 1] & (bitmask[x]));
227 auto b3 = (data[(y * 2) + ((bpp * 8) * pos) + 16] & (bitmask[x]));
228 auto b4 = (data[(y * 2) + ((bpp * 8) * pos) + 17] & (bitmask[x]));
229 auto b5 = (data[(y * 2) + ((bpp * 8) * pos) + 32] & (bitmask[x]));
230 auto b6 = (data[(y * 2) + ((bpp * 8) * pos) + 33] & (bitmask[x]));
231 auto b7 = (data[(y * 2) + ((bpp * 8) * pos) + 48] & (bitmask[x]));
232 auto b8 = (data[(y * 2) + ((bpp * 8) * pos) + 49] & (bitmask[x]));
233
234 auto b = 0;
235 if (b1 != 0) {
236 b |= 1;
237 }
238 if (b2 != 0) {
239 b |= 2;
240 }
241 if (bpp >= 4) {
242 if (b3 != 0) {
243 b |= 4;
244 }
245 if (b4 != 0) {
246 b |= 8;
247 }
248 }
249 if (bpp >= 8) {
250 if (b5 != 0) {
251 b |= 0x10;
252 }
253 if (b6 != 0) {
254 b |= 0x20;
255 }
256 if (b7 != 0) {
257 b |= 0x40;
258 }
259 if (b8 != 0) {
260 b |= 0x80;
261 }
262 }
263 // bitmap_data[((x + xx) * sheet_width) + y + (yy * 8)] = b;
264 bitmap_data[x + xx][y + (yy * 8)] = b;
265 }
266 }
267 pos++;
268 ypos++;
269 xx += 8;
270 if (ypos >= 16) {
271 yy++;
272 xx = 0;
273 ypos = 0;
274 }
275 }
276
277 int n = 0;
278
279 for (int y = 0; y < (data.size() / 64); y++) {
280 for (int x = 0; x < sheet_width; x++) { // 128 assumption
281 if (n < data.size()) {
282 // buffer[n] = bitmap_data[(x * sheet_width) + y];
283 buffer[n] = bitmap_data[x][y];
284 n++;
285 }
286 }
287 }
288 return buffer;
289}
290
291uint16_t TileInfoToWord(TileInfo tile_info) {
292 uint16_t result = 0;
293
294 // Copy the id_ value
295 result |= tile_info.id_ & 0x3FF; // ids are 10 bits
296
297 // Set the vertical_mirror_, horizontal_mirror_, and over_ flags
298 result |= (tile_info.vertical_mirror_ ? 1 : 0) << 15;
299 result |= (tile_info.horizontal_mirror_ ? 1 : 0) << 14;
300 result |= (tile_info.over_ ? 1 : 0) << 13;
301
302 // Set the palette_
303 result |= (tile_info.palette_ & 0x07) << 10; // palettes are 3 bits
304
305 return result;
306}
307
308TileInfo WordToTileInfo(uint16_t word) {
309 // Extract the id_ value
310 uint16_t id = word & 0x3FF; // ids are 10 bits
311
312 // Extract the vertical_mirror_, horizontal_mirror_, and over_ flags
313 bool vertical_mirror = (word >> 15) & 0x01;
314 bool horizontal_mirror = (word >> 14) & 0x01;
315 bool over = (word >> 13) & 0x01;
316
317 // Extract the palette_
318 uint8_t palette = (word >> 10) & 0x07; // palettes are 3 bits
319
320 return TileInfo(id, palette, vertical_mirror, horizontal_mirror, over);
321}
322
323uint16_t TileInfoToShort(TileInfo tile_info) {
324 // uint16_t result = 0;
325
326 // Copy the id_ value
327 // result |= tile_info.id_ & 0x3FF; // ids are 10 bits
328
329 // Set the vertical_mirror_, horizontal_mirror_, and over_ flags
330 // result |= (tile_info.vertical_mirror_ ? 1 : 0) << 10;
331 // result |= (tile_info.horizontal_mirror_ ? 1 : 0) << 11;
332 // result |= (tile_info.over_ ? 1 : 0) << 12;
333
334 // Set the palette_
335 // result |= (tile_info.palette_ & 0x07) << 13; // palettes are 3 bits
336
337 uint16_t value = 0;
338 // vhopppcc cccccccc
339 if (tile_info.over_) {
340 value |= TilePriorityBit;
341 }
342 if (tile_info.horizontal_mirror_) {
343 value |= TileHFlipBit;
344 }
345 if (tile_info.vertical_mirror_) {
346 value |= TileVFlipBit;
347 }
348 value |= (uint16_t)((tile_info.palette_ << 10) & 0x1C00);
349 value |= (uint16_t)(tile_info.id_ & TileNameMask);
350
351 return value;
352}
353
354TileInfo GetTilesInfo(uint16_t tile) {
355 // vhopppcc cccccccc
356 uint16_t tid = (uint16_t)(tile & TileNameMask);
357 uint8_t p = (uint8_t)((tile >> 10) & 0x07);
358
359 bool o = ((tile & TilePriorityBit) == TilePriorityBit);
360 bool h = ((tile & TileHFlipBit) == TileHFlipBit);
361 bool v = ((tile & TileVFlipBit) == TileVFlipBit);
362
363 return TileInfo(tid, p, v, h, o);
364}
365
366void CopyTile8bpp16(int x, int y, int tile, std::vector<uint8_t>& bitmap,
367 std::vector<uint8_t>& blockset) {
368 int src_pos =
369 ((tile - ((tile / 0x08) * 0x08)) * 0x10) + ((tile / 0x08) * 2048);
370 int dest_pos = (x + (y * 0x200));
371 for (int yy = 0; yy < 0x10; yy++) {
372 for (int xx = 0; xx < 0x10; xx++) {
373 bitmap[dest_pos + xx + (yy * 0x200)] =
374 blockset[src_pos + xx + (yy * 0x80)];
375 }
376 }
377}
378
380 std::span<uint8_t> src) {
381 std::vector<uint8_t> dest;
382 uint8_t b0;
383 uint8_t b1;
384 uint8_t b2;
385 uint8_t b3;
386 int res;
387 int mul;
388 int y_adder = 0;
389 int src_index;
390 int dest_x;
391 int dest_y;
392 int dest_index;
393 int main_index_limit = src.size() / 32;
394 for (int main_index = 0; main_index <= main_index_limit; main_index += 32) {
395 src_index = (main_index << 5);
396 if (src_index + 31 >= src.size()) {
397 throw std::invalid_argument("src_index + 31 >= src.size()");
398 }
399 dest_x = main_index & 0x0F;
400 dest_y = main_index >> 4;
401 dest_index = ((dest_y << 7) + dest_x) << 3;
402 if (dest_index + 903 >= dest.size()) {
403 throw std::invalid_argument("dest_index + 903 >= dest.size()");
404 }
405 for (int i = 0; i < 16; i += 2) {
406 mul = 1;
407 b0 = src[src_index + i];
408 b1 = src[src_index + i + 1];
409 b2 = src[src_index + i + 16];
410 b3 = src[src_index + i + 17];
411 for (int j = 0; j < 8; j++) {
412 res = ((b0 & mul) | ((b1 & mul) << 1) | ((b2 & mul) << 2) |
413 ((b3 & mul) << 3)) >>
414 j;
415 dest[dest_index + (7 - j) + y_adder] = res;
416 mul <<= 1;
417 }
418 y_adder += 128;
419 }
420 }
421 return dest;
422}
423
424} // namespace gfx
425} // namespace yaze
SNES 16-bit tile metadata container.
Definition snes_tile.h:50
Contains classes for handling graphical data.
Definition arena.cc:8
std::vector< uint8_t > LoadSNES4bppGFXToIndexedColorMatrix(std::span< uint8_t > src)
Definition snes_tile.cc:379
constexpr uint16_t TileNameMask
Definition snes_tile.cc:21
constexpr uint16_t TileVFlipBit
Definition snes_tile.cc:18
void CopyTile8bpp16(int x, int y, int tile, std::vector< uint8_t > &bitmap, std::vector< uint8_t > &blockset)
Definition snes_tile.cc:366
uint16_t TileInfoToWord(TileInfo tile_info)
Definition snes_tile.cc:291
uint16_t TileInfoToShort(TileInfo tile_info)
Definition snes_tile.cc:323
std::vector< uint8_t > PackBppTile(const snes_tile8 &tile, const uint32_t bpp)
Definition snes_tile.cc:72
std::vector< uint8_t > Bpp8SnesToIndexed(std::vector< uint8_t > data, uint64_t bpp)
Definition snes_tile.cc:189
constexpr uint16_t TilePriorityBit
Definition snes_tile.cc:12
std::vector< uint8_t > SnesTo8bppSheet(std::span< uint8_t > sheet, int bpp, int num_sheets)
Definition snes_tile.cc:129
snes_tile8 UnpackBppTile(std::span< uint8_t > data, const uint32_t offset, const uint32_t bpp)
Definition snes_tile.cc:23
TileInfo GetTilesInfo(uint16_t tile)
Definition snes_tile.cc:354
constexpr uint8_t kGraphicsBitmap[8]
Definition snes_tile.h:20
TileInfo WordToTileInfo(uint16_t word)
Definition snes_tile.cc:308
std::vector< uint8_t > ConvertBpp(std::span< uint8_t > tiles, uint32_t from_bpp, uint32_t to_bpp)
Definition snes_tile.cc:115
constexpr uint16_t TileHFlipBit
Definition snes_tile.cc:15
Main namespace for the application.
Definition controller.cc:18
uint8_t data[64]
Definition yaze.h:74