Importing a bunch of code from Skarsnik sneshacking repo
This commit is contained in:
83
src/Application/Graphics/Palette.cc
Normal file
83
src/Application/Graphics/Palette.cc
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "Palette.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
r_palette* palette_create(const unsigned int size, const unsigned int id)
|
||||
{
|
||||
r_palette *new_pal = (r_palette*) malloc(sizeof(r_palette));
|
||||
new_pal->colors = (m_color*) malloc(sizeof(m_color) * size);
|
||||
new_pal->id = id;
|
||||
new_pal->size = size;
|
||||
return new_pal;
|
||||
}
|
||||
|
||||
void palette_free(r_palette* tofree)
|
||||
{
|
||||
free(tofree->colors);
|
||||
free(tofree);
|
||||
}
|
||||
|
||||
|
||||
r_palette *palette_extract(const char* data, const unsigned int offset, const unsigned int palette_size)
|
||||
{
|
||||
r_palette* toret = palette_create(palette_size, 0);
|
||||
unsigned colnum = 0;
|
||||
for (int i = 0; i < palette_size * 2; i += 2)
|
||||
{
|
||||
unsigned short snes_color;
|
||||
snes_color = ((uchar) data[offset + i + 1]) << 8;
|
||||
snes_color = snes_color | ((uchar) data[offset + i]);
|
||||
toret->colors[colnum] = convertcolor_snes_to_rgb(snes_color);
|
||||
colnum++;
|
||||
}
|
||||
return toret;
|
||||
}
|
||||
|
||||
char* palette_convert(const r_palette pal)
|
||||
{
|
||||
char* toret = (char*) malloc(pal.size * 2);
|
||||
for (unsigned int i = 0; i < pal.size; i++)
|
||||
{
|
||||
unsigned short snes_data = convertcolor_rgb_to_snes(pal.colors[i]);
|
||||
toret[i * 2] = snes_data & 0xFF;
|
||||
toret[i * 2 + 1] = snes_data >> 8;
|
||||
}
|
||||
return toret;
|
||||
}
|
||||
|
||||
m_color convertcolor_snes_to_rgb(const unsigned short snes_color)
|
||||
{
|
||||
m_color toret;
|
||||
|
||||
toret.red = ((snes_color ) % 32) * 8;
|
||||
toret.green = ((snes_color / 32) % 32) * 8;
|
||||
toret.blue = ((snes_color / 1024) % 32) * 8;
|
||||
|
||||
toret.red = toret.red + toret.red / 32;
|
||||
toret.green = toret.green + toret.green / 32;
|
||||
toret.blue = toret.blue + toret.blue / 32;
|
||||
return toret;
|
||||
}
|
||||
|
||||
unsigned short convertcolor_rgb_to_snes(const m_color color)
|
||||
{
|
||||
return convertcolor_rgb_to_snes2(color.red, color.green, color.blue);
|
||||
}
|
||||
|
||||
unsigned short convertcolor_rgb_to_snes2(const uchar red, const uchar green, const uchar blue)
|
||||
{
|
||||
uchar R = red / 8;
|
||||
uchar G = green / 8;
|
||||
uchar B = blue / 8;
|
||||
|
||||
return B * 1024 + G * 32 + R;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/Application/Graphics/Palette.h
Normal file
42
src/Application/Graphics/Palette.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef YAZE_APPLICATION_GRAPHICS_PALETTE_H
|
||||
#define YAZE_APPLICATION_GRAPHICS_PALETTE_H
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
typedef struct {
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
} m_color;
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
unsigned int size;
|
||||
m_color* colors;
|
||||
} r_palette;
|
||||
|
||||
r_palette* palette_create(const unsigned int size, const unsigned int id);
|
||||
void palette_free(r_palette* tofree);
|
||||
|
||||
r_palette* palette_extract(const char* data, const unsigned int offset,
|
||||
const unsigned int palette_size);
|
||||
|
||||
char* palette_convert(const r_palette pal);
|
||||
|
||||
m_color convertcolor_snes_to_rgb(const unsigned short snes_color);
|
||||
unsigned short convertcolor_rgb_to_snes(const m_color color);
|
||||
unsigned short convertcolor_rgb_to_snes2(const uchar red, const uchar green,
|
||||
const uchar blue);
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APPLICATION_GRAPHICS_PALETTE_H
|
||||
@@ -1,5 +1,12 @@
|
||||
#include "Tile.h"
|
||||
|
||||
#include <png.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
@@ -21,6 +28,191 @@ ushort TileInfo::toShort() {
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
char* hexString(const char* str, const unsigned int size) {
|
||||
char* toret = (char*)malloc(size * 3 + 1);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
sprintf(toret + i * 3, "%02X ", (unsigned char)str[i]);
|
||||
}
|
||||
toret[size * 3] = 0;
|
||||
return toret;
|
||||
}
|
||||
|
||||
void export_tile_to_png(tile8 rawtile, const r_palette pal,
|
||||
const char* filename) {
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
png_structp png_ptr =
|
||||
png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_strip_alpha(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
png_color* png_palette =
|
||||
(png_color*)png_malloc(png_ptr, pal.size * sizeof(png_color));
|
||||
|
||||
for (unsigned int i = 0; i < pal.size; i++) {
|
||||
png_palette[i].blue = pal.colors[i].blue;
|
||||
png_palette[i].green = pal.colors[i].green;
|
||||
png_palette[i].red = pal.colors[i].red;
|
||||
}
|
||||
png_set_IHDR(png_ptr, info_ptr, 8, 8, 8, PNG_COLOR_TYPE_PALETTE,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
|
||||
PNG_FILTER_TYPE_BASE);
|
||||
png_set_PLTE(png_ptr, info_ptr, png_palette, pal.size);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
png_byte* row_pointers[8];
|
||||
for (unsigned int i = 0; i < 8; i++) {
|
||||
row_pointers[i] = (png_byte*)png_malloc(png_ptr, sizeof(png_byte));
|
||||
memcpy(row_pointers[i], rawtile.data + i * 8, 8);
|
||||
}
|
||||
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
png_free(png_ptr, png_palette);
|
||||
png_free(png_ptr, row_pointers);
|
||||
}
|
||||
|
||||
tile8 unpack_bpp1_tile(const char* data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 1));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp2_tile(const char* data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 2));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp3_tile(const char* data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 3));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp4_tile(const char* data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 4));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp8_tile(const char* data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 8));
|
||||
}
|
||||
|
||||
tile8 unpack_mode7_tile(const char* data, const unsigned int offset) {
|
||||
tile8 tile;
|
||||
memcpy(tile.data, data + offset, 64);
|
||||
return tile;
|
||||
}
|
||||
|
||||
tile8 unpack_bpp_tile(const char* data, const unsigned int offset,
|
||||
const unsigned bpp) {
|
||||
tile8 tile;
|
||||
assert(bpp >= 1 && bpp <= 8);
|
||||
unsigned int bpp_pos[8]; // More for conveniance and readibility
|
||||
for (int col = 0; col < 8; col++) {
|
||||
for (int row = 0; row < 8; row++) {
|
||||
if (bpp == 1) {
|
||||
tile.data[col * 8 + row] = (data[offset + col] >> (7 - row)) & 0x01;
|
||||
continue;
|
||||
}
|
||||
/* SNES bpp format interlace each byte of the first 2 bitplanes.
|
||||
* | byte 1 of first bitplane | byte 1 of the second bitplane | byte 2 of
|
||||
* first bitplane | byte 2 of second bitplane | ..
|
||||
*/
|
||||
bpp_pos[0] = offset + col * 2;
|
||||
bpp_pos[1] = offset + col * 2 + 1;
|
||||
char mask = 1 << (7 - row);
|
||||
tile.data[col * 8 + row] = (data[bpp_pos[0]] & mask) == mask;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[1]] & mask) == mask) << 1;
|
||||
if (bpp == 3) {
|
||||
// When we have 3 bitplanes, the bytes for the third bitplane are after
|
||||
// the 16 bytes of the 2 bitplanes.
|
||||
bpp_pos[2] = offset + 16 + col;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2;
|
||||
}
|
||||
if (bpp >= 4) {
|
||||
// For 4 bitplanes, the 2 added bitplanes are interlaced like the first
|
||||
// two.
|
||||
bpp_pos[2] = offset + 16 + col * 2;
|
||||
bpp_pos[3] = offset + 16 + col * 2 + 1;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[3]] & mask) == mask) << 3;
|
||||
}
|
||||
if (bpp == 8) {
|
||||
bpp_pos[4] = offset + 32 + col * 2;
|
||||
bpp_pos[5] = offset + 32 + col * 2 + 1;
|
||||
bpp_pos[6] = offset + 48 + col * 2;
|
||||
bpp_pos[7] = offset + 48 + col * 2 + 1;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[4]] & mask) == mask) << 4;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[5]] & mask) == mask) << 5;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[6]] & mask) == mask) << 6;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[7]] & mask) == mask) << 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
byte* pack_bpp1_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 1, &p);
|
||||
}
|
||||
|
||||
byte* pack_bpp2_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 2, &p);
|
||||
}
|
||||
|
||||
byte* pack_bpp3_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 3, &p);
|
||||
}
|
||||
|
||||
byte* pack_bpp4_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 4, &p);
|
||||
}
|
||||
|
||||
byte* pack_bpp8_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 8, &p);
|
||||
}
|
||||
|
||||
byte* pack_bpp_tile(tile8 tile, const unsigned int bpp, unsigned int* size) {
|
||||
byte* output = (byte*)malloc(bpp * 8);
|
||||
memset(output, 0, bpp * 8);
|
||||
unsigned maxcolor = 2 << bpp;
|
||||
*size = 0;
|
||||
|
||||
for (unsigned int col = 0; col < 8; col++) {
|
||||
for (unsigned int row = 0; row < 8; row++) {
|
||||
byte color = tile.data[col * 8 + row];
|
||||
if (color > maxcolor) return NULL;
|
||||
|
||||
if (bpp == 1) output[col] += (byte)((color & 1) << (7 - row));
|
||||
if (bpp >= 2) {
|
||||
output[col * 2] += (byte)((color & 1) << (7 - row));
|
||||
output[col * 2 + 1] += (byte)(((color & 2) == 2) << (7 - row));
|
||||
}
|
||||
if (bpp == 3) output[16 + col] += (byte)(((color & 4) == 4) << (7 - row));
|
||||
if (bpp >= 4) {
|
||||
output[16 + col * 2] += (byte)(((color & 4) == 4) << (7 - row));
|
||||
output[16 + col * 2 + 1] += (byte)(((color & 8) == 8) << (7 - row));
|
||||
}
|
||||
if (bpp == 8) {
|
||||
output[32 + col * 2] += (byte)(((color & 16) == 16) << (7 - row));
|
||||
output[32 + col * 2 + 1] += (byte)(((color & 32) == 32) << (7 - row));
|
||||
output[48 + col * 2] += (byte)(((color & 64) == 64) << (7 - row));
|
||||
output[48 + col * 2 + 1] += (byte)(((color & 128) == 128) << (7 - row));
|
||||
}
|
||||
}
|
||||
}
|
||||
*size = bpp * 8;
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
|
||||
@@ -3,13 +3,48 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Palette.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
using byte = unsigned char;
|
||||
using ushort = unsigned short;
|
||||
using uint = unsigned int;
|
||||
|
||||
// SkarAlttp project code
|
||||
extern "C" {
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
char data[64];
|
||||
unsigned int palette_id;
|
||||
} tile8;
|
||||
|
||||
tile8 unpack_bpp8_tile(const char* data, const unsigned int offset);
|
||||
tile8 unpack_bpp4_tile(const char* data, const unsigned int offset);
|
||||
tile8 unpack_bpp3_tile(const char* data, const unsigned int offset);
|
||||
tile8 unpack_bpp2_tile(const char* data, const unsigned int offset);
|
||||
tile8 unpack_bpp1_tile(const char* data, const unsigned int offset);
|
||||
|
||||
tile8 unpack_bpp_tile(const char* data, const unsigned int offset,
|
||||
const unsigned int bpp);
|
||||
|
||||
byte* pack_bpp1_tile(const tile8 tile);
|
||||
byte* pack_bpp2_tile(const tile8 tile);
|
||||
byte* pack_bpp3_tile(const tile8 tile);
|
||||
byte* pack_bpp4_tile(const tile8 tile);
|
||||
byte* pack_bpp8_tile(const tile8 tile);
|
||||
|
||||
byte* pack_bpp_tile(const tile8 tile, const unsigned int bpp,
|
||||
unsigned int* size);
|
||||
|
||||
void export_tile_to_png(tile8 rawtile, const r_palette pal,
|
||||
const char* filename);
|
||||
}
|
||||
|
||||
// End SkarAlttp project code
|
||||
class TileInfo {
|
||||
public:
|
||||
ushort id_;
|
||||
@@ -84,7 +119,8 @@ class Tile16 {
|
||||
;
|
||||
}
|
||||
};
|
||||
} // namespace Data
|
||||
|
||||
} // namespace Graphics
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
|
||||
|
||||
Reference in New Issue
Block a user